1 /* @(#) $Id: ./src/rootcheck/common_rcl.c, 2011/09/08 dcid Exp $
4 /* Copyright (C) 2009 Trend Micro Inc.
7 * This program is a free software; you can redistribute it
8 * and/or modify it under the terms of the GNU General Public
9 * License (version 2) as published by the FSF - Free Software
12 * License details at the LICENSE file included with OSSEC or
13 * online at: http://www.ossec.net/main/license/
18 #include "rootcheck.h"
22 #define RKCL_TYPE_FILE 1
23 #define RKCL_TYPE_REGISTRY 2
24 #define RKCL_TYPE_PROCESS 3
25 #define RKCL_TYPE_DIR 4
27 #define RKCL_COND_ALL 0x001
28 #define RKCL_COND_ANY 0x002
29 #define RKCL_COND_REQ 0x004
30 #define RKCL_COND_INV 0x010
34 /** char *_rkcl_getrootdir()
36 char *_rkcl_getrootdir(char *root_dir, int dir_size)
39 char final_file[2048 +1];
43 final_file[2048] = '\0';
45 ExpandEnvironmentStrings("%WINDIR%", final_file, 2047);
47 tmp = strchr(final_file, '\\');
51 strncpy(root_dir, final_file, dir_size);
64 /** char *_rkcl_getfp: Get next available buffer in file.
66 char *_rkcl_getfp(FILE *fp, char *buf)
68 while(fgets(buf, OS_SIZE_1024, fp) != NULL)
72 /* Removing end of line */
73 nbuf = strchr(buf, '\n');
79 /* Assigning buf to be used */
83 /* Excluding commented lines or blanked ones */
86 if(*nbuf == ' ' || *nbuf == '\t')
102 /* Going to next line if empty */
116 /** int _rkcl_is_name
118 int _rkcl_is_name(char *buf)
120 if(*buf == '[' && buf[strlen(buf) -1] == ']')
129 /** int _rkcl_get_vars(vars, nbuf)
131 int _rkcl_get_vars(OSStore *vars, char *nbuf)
137 /* If not a variable, return 0 */
144 /* Removing ; from the end. */
145 tmp = strchr(nbuf, ';');
157 tmp = strchr(nbuf, '=');
169 /* Dumping the variable options. */
170 os_strdup(nbuf, var_name);
171 os_strdup(tmp, var_value);
174 /* Adding entry to the storage */
175 OSStore_Put(vars, var_name, var_value);
181 /** int _rkcl_get_name
183 char *_rkcl_get_name(char *buf, char *ref, int *condition)
190 /* Checking if name is valid */
191 if(!_rkcl_is_name(buf))
198 tmp_location = strchr(buf, ']');
203 *tmp_location = '\0';
206 /* Getting condition */
208 if(*tmp_location != ' ' && tmp_location[1] != '[')
214 tmp_location2 = strchr(tmp_location, ']');
219 *tmp_location2 = '\0';
223 /* Getting condition */
224 if(strcmp(tmp_location, "all") == 0)
226 *condition |= RKCL_COND_ALL;
228 else if(strcmp(tmp_location,"any") == 0)
230 *condition |= RKCL_COND_ANY;
232 else if(strcmp(tmp_location,"any required") == 0)
234 *condition |= RKCL_COND_ANY;
235 *condition |= RKCL_COND_REQ;
237 else if(strcmp(tmp_location, "all required") == 0)
239 *condition |= RKCL_COND_ALL;
240 *condition |= RKCL_COND_REQ;
244 *condition = RKCL_COND_INV;
249 /* Getting reference */
250 if(*tmp_location2 != ' ' && tmp_location2[1] != '[')
256 tmp_location = strchr(tmp_location2, ']');
261 *tmp_location = '\0';
263 /* Copying reference */
264 strncpy(ref, tmp_location2, 255);
271 /** char *_rkcl_get_pattern(char *value)
273 char *_rkcl_get_pattern(char *value)
275 while(*value != '\0')
277 if((*value == ' ') && (value[1] == '-') &&
278 (value[2] == '>') && (value[3] == ' '))
293 /** char *_rkcl_get_value
295 char *_rkcl_get_value(char *buf, int *type)
300 /* Zeroing type before using it --make sure return is valid
305 value = strchr(buf, ':');
314 tmp_str = strchr(value, ';');
322 /* Getting types - removing negate flag (using later) */
328 if(strcmp(buf, "f") == 0)
330 *type = RKCL_TYPE_FILE;
332 else if(strcmp(buf, "r") == 0)
334 *type = RKCL_TYPE_REGISTRY;
336 else if(strcmp(buf, "p") == 0)
338 *type = RKCL_TYPE_PROCESS;
340 else if(strcmp(buf, "d") == 0)
342 *type = RKCL_TYPE_DIR;
354 /** int rkcl_get_entry:
356 int rkcl_get_entry(FILE *fp, char *msg, void *p_list_p)
358 int type = 0, condition = 0, root_dir_len = 0;
360 char buf[OS_SIZE_1024 +2];
361 char root_dir[OS_SIZE_1024 +2];
362 char final_file[2048 +1];
369 OSList *p_list = (OSList *)p_list_p;
372 /* Cleaning up vars */
373 memset(buf, '\0', sizeof(buf));
374 memset(root_dir, '\0', sizeof(root_dir));
375 memset(final_file, '\0', sizeof(final_file));
376 memset(ref, '\0', sizeof(ref));
379 root_dir_len = sizeof(root_dir) -1;
383 /* Getting Windows rootdir */
384 _rkcl_getrootdir(root_dir, root_dir_len);
385 if(root_dir[0] == '\0')
387 merror(INVALID_ROOTDIR, ARGV0);
392 /* Getting variables */
393 vars = OSStore_Create();
396 /* We first read all variables -- they must be defined at the top. */
400 nbuf = _rkcl_getfp(fp, buf);
406 rc_code = _rkcl_get_vars(vars, nbuf);
411 else if(rc_code == -1)
413 merror(INVALID_RKCL_VAR, ARGV0, nbuf);
419 /* Getting first name */
420 name = _rkcl_get_name(nbuf, ref, &condition);
421 if(name == NULL || condition == RKCL_COND_INV)
423 merror(INVALID_RKCL_NAME, ARGV0, nbuf);
429 /* Getting the real entries. */
435 /* Getting entry name */
438 merror(INVALID_RKCL_NAME, ARGV0, "NULL");
442 debug2("%s: DEBUG: Checking entry: '%s'.", ARGV0, name);
445 /* Getting each value */
452 nbuf = _rkcl_getfp(fp, buf);
459 /* We first try to get the name, looking for new entries */
460 if(_rkcl_is_name(nbuf))
466 /* Getting value to look for */
467 value = _rkcl_get_value(nbuf, &type);
470 merror(INVALID_RKCL_VALUE, ARGV0, nbuf);
475 /* Getting negate value */
483 /* Checking for a file. */
484 if(type == RKCL_TYPE_FILE)
486 char *pattern = NULL;
487 char *f_value = NULL;
490 pattern = _rkcl_get_pattern(value);
494 /* Getting any variable. */
497 f_value = OSStore_Get(vars, value);
500 merror(INVALID_RKCL_VAR, ARGV0, value);
507 else if(value[0] == '\\')
509 final_file[0] = '\0';
510 final_file[sizeof(final_file) -1] = '\0';
512 snprintf(final_file, sizeof(final_file) -2, "%s%s",
514 f_value = final_file;
518 final_file[0] = '\0';
519 final_file[sizeof(final_file) -1] = '\0';
521 ExpandEnvironmentStrings(value, final_file,
522 sizeof(final_file) -2);
523 f_value = final_file;
528 debug2("%s: DEBUG: Checking file: '%s'.", ARGV0, f_value);
529 if(rk_check_file(f_value, pattern))
531 debug1("%s: DEBUG: found file.", ARGV0);
537 /* Checking for a registry entry */
538 else if(type == RKCL_TYPE_REGISTRY)
541 char *pattern = NULL;
544 /* Looking for additional entries in the registry
545 * and a pattern to match.
547 entry = _rkcl_get_pattern(value);
550 pattern = _rkcl_get_pattern(entry);
555 debug2("%s: DEBUG: Checking registry: '%s'.", ARGV0, value);
556 if(is_registry(value, entry, pattern))
558 debug2("%s: DEBUG: found registry.", ARGV0);
565 /* Checking for a directory. */
566 else if(type == RKCL_TYPE_DIR)
569 char *pattern = NULL;
570 char *f_value = NULL;
574 file = _rkcl_get_pattern(value);
577 pattern = _rkcl_get_pattern(file);
581 /* Getting any variable. */
584 f_value = OSStore_Get(vars, value);
587 merror(INVALID_RKCL_VAR, ARGV0, value);
597 /* Checking for multiple, comma separated directories. */
599 f_value = strchr(dir, ',');
608 debug2("%s: Checking dir: %s", ARGV0, dir);
609 if(rk_check_dir(dir, file, pattern))
611 debug2("%s: DEBUG: Found dir.", ARGV0);
622 f_value = strchr(dir, ',');
636 /* Checking for a process. */
637 else if(type == RKCL_TYPE_PROCESS)
639 debug2("%s: DEBUG: Checking process: '%s'.", ARGV0, value);
640 if(is_process(value, p_list))
642 debug2("%s: DEBUG: found process.", ARGV0);
648 /* Switching the values if ! is present */
662 /** Checking the conditions **/
663 if(condition & RKCL_COND_ANY)
665 debug2("%s: DEBUG: Condition ANY.", ARGV0);
671 /* Condition for ALL */
674 debug2("%s: DEBUG: Condition ALL.", ARGV0);
675 if(found && (g_found != -1))
684 }while(value != NULL);
687 /* Alerting if necessary */
691 char op_msg[OS_SIZE_1024 +1];
692 char **p_alert_msg = rootcheck.alert_msg;
698 snprintf(op_msg, OS_SIZE_1024, "%s %s.%s"
699 " Reference: %s .",msg, name,
700 p_alert_msg[j]?p_alert_msg[j]:"\0",
705 snprintf(op_msg, OS_SIZE_1024, "%s %s.%s",msg,
706 name, p_alert_msg[j]?p_alert_msg[j]:"\0");
709 if((type == RKCL_TYPE_DIR) || (j == 0))
711 notify_rk(ALERT_POLICY_VIOLATION, op_msg);
716 free(p_alert_msg[j]);
717 p_alert_msg[j] = NULL;
732 while(rootcheck.alert_msg[j])
734 free(rootcheck.alert_msg[j]);
735 rootcheck.alert_msg[j] = NULL;
740 /* Checking if this entry is required for the rest of the file. */
741 if(condition & RKCL_COND_REQ)
748 /* Ending if we don't have anything else. */
755 /* Cleaning up name. */
763 /* Getting name already read */
764 name = _rkcl_get_name(nbuf, ref, &condition);
767 merror(INVALID_RKCL_NAME, ARGV0, nbuf);
770 }while(nbuf != NULL);
774 /* Cleaning up the memory */
781 vars = OSStore_Free(vars);