new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / util / rootcheck_control.c
1 /* Copyright (C) 2019 OSSEC Foundation
2  * All right reserved.
3  *
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
7  * Foundation
8  */
9
10 #include "addagent/manage_agents.h"
11 #include "sec.h"
12 #include <external/cJSON/cJSON.h>
13
14
15 #undef ARGV0
16 #define ARGV0 "rootcheck_control"
17
18 /* Prototypes */
19 static void helpmsg(void) __attribute__((noreturn));
20
21
22 static void helpmsg()
23 {
24     printf("\nOSSEC HIDS %s: Manages the policy and auditing database.\n",
25            ARGV0);
26     printf("Available options:\n");
27     printf("\t-h          This help message.\n");
28     printf("\t-l          List available (active or not) agents.\n");
29     printf("\t-lc         List only active agents.\n");
30     printf("\t-u <id>     Updates (clear) the database for the agent.\n");
31     printf("\t-u all      Updates (clear) the database for all agents.\n");
32     printf("\t-i <id>     Prints database for the agent.\n");
33     printf("\t-r          Used with -i, prints all the resolved issues.\n");
34     printf("\t-q          Used with -i, prints all the outstanding issues.\n");
35     printf("\t-L          Used with -i, prints the last scan.\n");
36     printf("\t-s          Changes the output to CSV (comma delimited).\n");
37     printf("\t-j          Changes the output to JSON.\n");
38     exit(1);
39 }
40
41 int main(int argc, char **argv)
42 {
43     const char *dir = DEFAULTDIR;
44     const char *group = GROUPGLOBAL;
45     const char *user = USER;
46     const char *agent_id = NULL;
47
48     gid_t gid;
49     uid_t uid;
50     int c = 0, info_agent = 0, update_rootcheck = 0,
51         list_agents = 0, show_last = 0,
52         resolved_only = 0;
53     int active_only = 0, csv_output = 0, json_output = 0;
54
55     char shost[512];
56     cJSON *json_root = NULL;
57
58
59     /* Set the name */
60     OS_SetName(ARGV0);
61
62     /* User arguments */
63     if (argc < 2) {
64         helpmsg();
65     }
66
67     while ((c = getopt(argc, argv, "VhqrDdLlcsju:i:")) != -1) {
68         switch (c) {
69             case 'V':
70                 print_version();
71                 break;
72             case 'h':
73                 helpmsg();
74                 break;
75             case 'D':
76                 nowDebug();
77                 break;
78             case 'l':
79                 list_agents++;
80                 break;
81             case 's':
82                 csv_output = 1;
83                 break;
84             case 'j':
85                 json_output = 1;
86                 break;
87             case 'c':
88                 active_only++;
89                 break;
90             case 'r':
91                 resolved_only = 1;
92                 break;
93             case 'q':
94                 resolved_only = 2;
95                 break;
96             case 'L':
97                 show_last = 1;
98                 break;
99             case 'i':
100                 info_agent++;
101                 if (!optarg) {
102                     merror("%s: -u needs an argument", ARGV0);
103                     helpmsg();
104                 }
105                 agent_id = optarg;
106                 break;
107             case 'u':
108                 if (!optarg) {
109                     merror("%s: -u needs an argument", ARGV0);
110                     helpmsg();
111                 }
112                 agent_id = optarg;
113                 update_rootcheck = 1;
114                 break;
115             default:
116                 helpmsg();
117                 break;
118         }
119
120     }
121
122     /* Get the group name */
123     gid = Privsep_GetGroup(group);
124     uid = Privsep_GetUser(user);
125     if (uid == (uid_t) - 1 || gid == (gid_t) - 1) {
126         ErrorExit(USER_ERROR, ARGV0, user, group);
127     }
128
129     /* Set the group */
130     if (Privsep_SetGroup(gid) < 0) {
131         ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
132     }
133
134     /* Chroot to the default directory */
135     if (Privsep_Chroot(dir) < 0) {
136         ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
137     }
138
139     /* Inside chroot now */
140     nowChroot();
141
142     /* Set the user */
143     if (Privsep_SetUser(uid) < 0) {
144         ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno));
145     }
146
147     /* Get server hostname */
148     memset(shost, '\0', 512);
149     if (gethostname(shost, 512 - 1) != 0) {
150         strncpy(shost, "localhost", 32);
151         return (0);
152     }
153
154     /* List available agents */
155     if (list_agents) {
156         if (!csv_output) {
157             printf("\nOSSEC HIDS %s. List of available agents:",
158                    ARGV0);
159             printf("\n   ID: 000, Name: %s (server), IP: 127.0.0.1, "
160                    "Active/Local\n", shost);
161         } else {
162             printf("000,%s (server),127.0.0.1,Active/Local,\n", shost);
163         }
164         print_agents(1, active_only, csv_output, 0);
165         printf("\n");
166         exit(0);
167     }
168
169     /* Update rootcheck database */
170     if (update_rootcheck) {
171         char json_buffer[1024];
172
173         /* Clean all agents (and server) db */
174         if (strcmp(agent_id, "all") == 0) {
175             DIR *sys_dir;
176             struct dirent *entry;
177
178             sys_dir = opendir(ROOTCHECK_DIR);
179             if (!sys_dir) {
180                 if (json_output) {
181                     cJSON_AddNumberToObject(json_root, "error", 11);
182                     snprintf(json_buffer, 1023, "%s: Unable to open: '%s'", ARGV0, ROOTCHECK_DIR);
183                     cJSON_AddStringToObject(json_root, "description", json_buffer);
184                     printf("%s", cJSON_PrintUnformatted(json_root));
185                     exit(1);
186                 } else
187                     ErrorExit("%s: Unable to open: '%s'", ARGV0, ROOTCHECK_DIR);
188
189             }
190
191             while ((entry = readdir(sys_dir)) != NULL) {
192                 FILE *fp;
193                 char full_path[OS_MAXSTR + 1];
194
195                 /* Do not even attempt to delete . and .. :) */
196                 if ((strcmp(entry->d_name, ".") == 0) ||
197                         (strcmp(entry->d_name, "..") == 0)) {
198                     continue;
199                 }
200
201                 snprintf(full_path, OS_MAXSTR, "%s/%s", ROOTCHECK_DIR,
202                          entry->d_name);
203
204                 fp = fopen(full_path, "w");
205                 if (fp) {
206                     fclose(fp);
207                 }
208                 if (entry->d_name[0] == '.') {
209                     unlink(full_path);
210                 }
211             }
212
213             closedir(sys_dir);
214             if (json_output) {
215                 cJSON_AddNumberToObject(json_root, "error", 0);
216                 cJSON_AddStringToObject(json_root, "response", "Policy and auditing database updated");
217                 printf("%s", cJSON_PrintUnformatted(json_root));
218             } else
219                 printf("\n** Policy and auditing database updated.\n\n");
220
221             exit(0);
222         }
223
224         else if ((strcmp(agent_id, "000") == 0) ||
225                  (strcmp(agent_id, "local") == 0)) {
226             char final_dir[1024];
227             FILE *fp;
228             snprintf(final_dir, 1020, "/%s/rootcheck", ROOTCHECK_DIR);
229
230             fp = fopen(final_dir, "w");
231             if (fp) {
232                 fclose(fp);
233             }
234             unlink(final_dir);
235             if (json_output) {
236                 cJSON_AddNumberToObject(json_root, "error", 0);
237                 cJSON_AddStringToObject(json_root, "response", "Policy and auditing database updated");
238                 printf("%s", cJSON_PrintUnformatted(json_root));
239             } else
240                 printf("\n** Policy and auditing database updated.\n\n");
241
242             exit(0);
243         }
244
245         /* Database from remote agents */
246         else {
247             int i;
248             keystore keys;
249
250             OS_ReadKeys(&keys);
251
252             i = OS_IsAllowedID(&keys, agent_id);
253             if (i < 0) {
254                 if (json_output) {
255                     cJSON_AddNumberToObject(json_root, "error", 12);
256                     snprintf(json_buffer, 1023, "Invalid agent id '%s'.", agent_id);
257                     cJSON_AddStringToObject(json_root, "description", json_buffer);
258                     printf("%s", cJSON_PrintUnformatted(json_root));
259                     exit(1);
260                 } else {
261                     printf("\n** Invalid agent id '%s'.\n", agent_id);
262                     helpmsg();
263                 }
264
265             }
266
267             /* Delete syscheck */
268             delete_rootcheck(keys.keyentries[i]->name,
269                              keys.keyentries[i]->ip->ip, 0);
270
271             if (json_output) {
272                  cJSON_AddNumberToObject(json_root, "error", 0);
273                  cJSON_AddStringToObject(json_root, "response", "Policy and auditing database updated");
274                  printf("%s", cJSON_PrintUnformatted(json_root));
275             } else
276                 printf("\n** Policy and auditing database updated.\n\n");
277
278
279             exit(0);
280         }
281     }
282
283     /* Print information from an agent */
284     if (info_agent) {
285         int i;
286         char final_ip[IPSIZE + 4];
287         keystore keys;
288         cJSON *json_events = NULL;
289         if (json_output)
290             json_events = cJSON_CreateArray();
291
292         if ((strcmp(agent_id, "000") == 0) ||
293                 (strcmp(agent_id, "local") == 0)) {
294             if (!(csv_output || json_output))
295
296                 printf("\nPolicy and auditing events for local system '%s - %s':\n",
297                        shost, "127.0.0.1");
298
299             print_rootcheck(NULL, NULL, NULL, resolved_only, csv_output,
300                             json_events, show_last);
301
302             if (json_output) {
303                 cJSON_AddNumberToObject(json_root, "error", 0);
304                 cJSON_AddItemToObject(json_root, "response", json_events);
305                 printf("%s", cJSON_PrintUnformatted(json_root));
306             }
307
308         } else {
309             OS_ReadKeys(&keys);
310
311             i = OS_IsAllowedID(&keys, agent_id);
312             if (i < 0) {
313                 if (json_output) {
314                     char json_buffer[1024];
315                     snprintf(json_buffer, 1023, "Invalid agent id '%s'", agent_id);
316                     cJSON_AddNumberToObject(json_root, "error", 13);
317                     cJSON_AddStringToObject(json_root, "description", json_buffer);
318                     printf("%s", cJSON_PrintUnformatted(json_root));
319                     exit(1);
320                 } else {
321                     printf("\n** Invalid agent id '%s'.\n", agent_id);
322                     helpmsg();
323                 }
324
325             }
326
327             /* Getting full address/prefixlength from ip. */
328             final_ip[(sizeof final_ip) - 1] = '\0';
329             snprintf(final_ip, sizeof final_ip, "%s/%u",
330                      keys.keyentries[i]->ip->ip,
331                      keys.keyentries[i]->ip->prefixlength);
332
333             if (!(csv_output || json_output))
334                 printf("\nPolicy and auditing events for agent "
335                        "'%s (%s) - %s':\n",
336                        keys.keyentries[i]->name, keys.keyentries[i]->id,
337                        final_ip);
338
339             print_rootcheck(keys.keyentries[i]->name,
340                             keys.keyentries[i]->ip->ip, NULL,
341                             resolved_only, csv_output, json_events, show_last);
342
343             if (json_output) {
344                 cJSON_AddNumberToObject(json_root, "error", 0);
345                 cJSON_AddItemToObject(json_root, "response", json_events);
346                 printf("%s", cJSON_PrintUnformatted(json_root));
347             }
348
349
350         }
351
352         exit(0);
353     }
354
355     if (json_output) {
356         cJSON_AddNumberToObject(json_root, "error", 10);
357         cJSON_AddStringToObject(json_root, "description", "Invalid argument combination");
358         printf("%s", cJSON_PrintUnformatted(json_root));
359         exit(1);
360     } else {
361         printf("\n** Invalid argument combination.\n");
362         helpmsg();
363     }
364
365
366     return (0);
367 }
368