1 /* Copyright (C) 2019 OSSEC Foundation
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
10 #include "addagent/manage_agents.h"
14 #define ARGV0 "syscheck_control"
17 static void helpmsg(void) __attribute__((noreturn));
22 printf("\nOSSEC HIDS %s: Manages the integrity checking database.\n",
24 printf("Available options:\n");
25 printf("\t-h This help message.\n");
26 printf("\t-l List available (active or inactive) agents.\n");
27 printf("\t-lc List only active agents.\n");
28 printf("\t-u <id> Updates (clears) the database for the agent.\n");
29 printf("\t-u all Updates (clears) the database for all agents.\n");
30 printf("\t-i <id> List modified files for the agent.\n");
31 printf("\t-r -i <id> List modified registry entries for the agent "
33 printf("\t-f <file> Prints information about a modified file.\n");
34 printf("\t Must be used with -i <id>.\n");
35 printf("\t-z Used with -f, zeroes the auto-ignore counter.\n");
36 printf("\t-d Used with -f, ignores that file.\n");
37 printf("\t-s Changes the output to CSV (comma delimited).\n");
38 printf("\t-j Changes the output to JSON.\n");
40 printf("\tExamples:\n");
42 printf("\t'Show information about /etc/passwd from agent with ID 019'\n");
43 printf("\t%s -i 019 -f /etc/passwd\n", ARGV0);
47 int main(int argc, char **argv)
49 const char *dir = DEFAULTDIR;
50 const char *group = GROUPGLOBAL;
51 const char *user = USER;
52 const char *agent_id = NULL;
53 const char *fname = NULL;
57 int c = 0, info_agent = 0, update_syscheck = 0,
58 list_agents = 0, zero_counter = 0,
60 int active_only = 0, csv_output = 0, json_output = 0;
73 while ((c = getopt(argc, argv, "VhzrDdlcsju:i:f:")) != -1) {
108 merror("%s: -u needs an argument", ARGV0);
115 merror("%s: -u needs an argument", ARGV0);
122 merror("%s: -u needs an argument", ARGV0);
134 /* Get the group name */
135 gid = Privsep_GetGroup(group);
136 uid = Privsep_GetUser(user);
137 if (uid == (uid_t) - 1 || gid == (gid_t) - 1) {
138 ErrorExit(USER_ERROR, ARGV0, user, group);
142 if (Privsep_SetGroup(gid) < 0) {
143 ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
146 /* Chroot to the default directory */
147 if (Privsep_Chroot(dir) < 0) {
148 ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
151 /* Inside chroot now */
155 if (Privsep_SetUser(uid) < 0) {
156 ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno));
159 /* Get server hostname */
160 memset(shost, '\0', 512);
161 if (gethostname(shost, 512 - 1) != 0) {
162 strncpy(shost, "localhost", 32);
167 json_root = cJSON_CreateObject();
169 /* List available agents */
171 cJSON *json_agents = NULL;
174 cJSON *first = cJSON_CreateObject();
175 json_agents = cJSON_CreateArray();
176 cJSON_AddNumberToObject(json_root, "error", 0);
177 cJSON_AddStringToObject(first, "id", "000");
178 cJSON_AddStringToObject(first, "name", shost);
179 cJSON_AddStringToObject(first, "ip", "127.0.0.1");
180 cJSON_AddStringToObject(first, "status", "Active");
181 cJSON_AddItemToArray(json_agents, first);
182 } else if (csv_output)
183 printf("000,%s (server),127.0.0.1,Active/Local,\n", shost);
185 printf("\nOSSEC HIDS %s. List of available agents:", ARGV0);
186 printf("\n ID: 000, Name: %s (server), IP: 127.0.0.1, "
187 "Active/Local\n", shost);
190 print_agents(1, active_only, csv_output, json_agents);
193 cJSON_AddItemToObject(json_root, "response", json_agents);
194 printf("%s", cJSON_PrintUnformatted(json_root));
201 /* Update syscheck database */
202 if (update_syscheck) {
203 /* Clean all agents (and server) db */
204 if (strcmp(agent_id, "all") == 0) {
206 struct dirent *entry;
208 sys_dir = opendir(SYSCHECK_DIR);
212 cJSON_AddNumberToObject(json_root, "error", 31);
213 snprintf(buffer, 1023, "%s: Unable to open: '%s'", ARGV0, SYSCHECK_DIR);
214 cJSON_AddStringToObject(json_root, "description", buffer);
215 printf("%s", cJSON_PrintUnformatted(json_root));
218 ErrorExit("%s: Unable to open: '%s'", ARGV0, SYSCHECK_DIR);
221 while ((entry = readdir(sys_dir)) != NULL) {
223 char full_path[OS_MAXSTR + 1];
225 /* Do not even attempt to delete . and .. :) */
226 if ((strcmp(entry->d_name, ".") == 0) ||
227 (strcmp(entry->d_name, "..") == 0)) {
231 snprintf(full_path, OS_MAXSTR, "%s/%s", SYSCHECK_DIR,
234 fp = fopen(full_path, "w");
238 if (entry->d_name[0] == '.') {
246 cJSON_AddNumberToObject(json_root, "error", 0);
247 cJSON_AddStringToObject(json_root, "response", "Integrity check database updated");
248 printf("%s", cJSON_PrintUnformatted(json_root));
250 printf("\n** Integrity check database updated.\n\n");
255 else if ((strcmp(agent_id, "000") == 0) ||
256 (strcmp(agent_id, "local") == 0)) {
257 char final_dir[1024];
259 snprintf(final_dir, 1020, "/%s/syscheck", SYSCHECK_DIR);
261 fp = fopen(final_dir, "w");
268 /* Deleting cpt file */
269 snprintf(final_dir, 1020, "/%s/.syscheck.cpt", SYSCHECK_DIR);
271 fp = fopen(final_dir, "w");
278 cJSON_AddNumberToObject(json_root, "error", 0);
279 cJSON_AddStringToObject(json_root, "response", "Integrity check database updated");
280 printf("%s", cJSON_PrintUnformatted(json_root));
282 printf("\n** Integrity check database updated.\n\n");
287 /* Database from remote agents */
294 i = OS_IsAllowedID(&keys, agent_id);
298 cJSON_AddNumberToObject(json_root, "error", 33);
299 snprintf(buffer, 1023, "Invalid agent id '%s'.", agent_id);
300 cJSON_AddStringToObject(json_root, "description", buffer);
301 printf("%s", cJSON_PrintUnformatted(json_root));
304 printf("\n** Invalid agent id '%s'.\n", agent_id);
309 /* Delete syscheck */
310 delete_syscheck(keys.keyentries[i]->name,
311 keys.keyentries[i]->ip->ip, 0);
314 cJSON_AddNumberToObject(json_root, "error", 0);
315 cJSON_AddStringToObject(json_root, "response", "Integrity check database updated");
316 printf("%s", cJSON_PrintUnformatted(json_root));
318 printf("\n** Integrity check database updated.\n\n");
324 /* Print information from an agent */
327 char final_ip[IPSIZE + 4];
329 cJSON *json_entries = NULL;
332 json_entries = cJSON_CreateArray();
334 if ((strcmp(agent_id, "000") == 0) ||
335 (strcmp(agent_id, "local") == 0)) {
336 if (!(csv_output || json_output)) {
337 printf("\nIntegrity checking changes for local system '%s - %s':\n",
340 printf("Detailed information for entries matching: '%s'\n",
345 print_syscheck(NULL, NULL, fname, 0, 0, csv_output, json_entries, zero_counter);
346 } else if (strchr(agent_id, '@')) {
347 if (fname && ! (csv_output || json_output)) {
348 printf("Detailed information for entries matching: '%s'\n",
351 print_syscheck(agent_id, NULL, fname, registry_only, 0,
352 csv_output, json_entries, zero_counter);
357 i = OS_IsAllowedID(&keys, agent_id);
361 cJSON_AddNumberToObject(json_root, "error", 32);
362 snprintf(buffer, 1023, "Invalid agent id '%s'.", agent_id);
363 cJSON_AddStringToObject(json_root, "description", buffer);
364 printf("%s", cJSON_PrintUnformatted(json_root));
367 printf("\n** Invalid agent id '%s'.\n", agent_id);
372 /* Getting full address/prefix length from ip. */
373 final_ip[(sizeof final_ip) - 1] = '\0';
374 snprintf(final_ip, sizeof final_ip, "%s/%u",
375 keys.keyentries[i]->ip->ip,
376 keys.keyentries[i]->ip->prefixlength);
378 if (!(csv_output || json_output)) {
380 printf("\nIntegrity changes for 'Windows Registry' of"
381 " agent '%s (%s) - %s':\n",
382 keys.keyentries[i]->name, keys.keyentries[i]->id,
385 printf("\nIntegrity changes for agent "
387 keys.keyentries[i]->name, keys.keyentries[i]->id,
392 printf("Detailed information for entries matching: '%s'\n",
397 print_syscheck(keys.keyentries[i]->name, keys.keyentries[i]->ip->ip, fname,
398 registry_only, 0, csv_output, json_entries, zero_counter);
402 cJSON_AddNumberToObject(json_root, "error", 0);
403 cJSON_AddItemToObject(json_root, "response", json_entries);
404 printf("%s", cJSON_PrintUnformatted(json_root));
411 cJSON_AddNumberToObject(json_root, "error", 30);
412 cJSON_AddStringToObject(json_root, "description", "Invalid argument combination");
413 printf("%s", cJSON_PrintUnformatted(json_root));
416 printf("\n** Invalid argument combination.\n");