1 /* @(#) $Id: common_rcl.c,v 1.17 2009/06/24 18:53:07 dcid Exp $ */
3 /* Copyright (C) 2009 Trend Micro Inc.
6 * This program is a free software; you can redistribute it
7 * and/or modify it under the terms of the GNU General Public
8 * License (version 3) as published by the FSF - Free Software
11 * License details at the LICENSE file included with OSSEC or
12 * online at: http://www.ossec.net/main/license/
17 #include "rootcheck.h"
21 #define RKCL_TYPE_FILE 1
22 #define RKCL_TYPE_REGISTRY 2
23 #define RKCL_TYPE_PROCESS 3
24 #define RKCL_TYPE_DIR 4
26 #define RKCL_COND_ALL 0x001
27 #define RKCL_COND_ANY 0x002
28 #define RKCL_COND_REQ 0x004
29 #define RKCL_COND_INV 0x010
33 /** char *_rkcl_getrootdir()
35 char *_rkcl_getrootdir(char *root_dir, int dir_size)
38 char final_file[2048 +1];
42 final_file[2048] = '\0';
44 ExpandEnvironmentStrings("%WINDIR%", final_file, 2047);
46 tmp = strchr(final_file, '\\');
50 strncpy(root_dir, final_file, dir_size);
63 /** char *_rkcl_getfp: Get next available buffer in file.
65 char *_rkcl_getfp(FILE *fp, char *buf)
67 while(fgets(buf, OS_SIZE_1024, fp) != NULL)
71 /* Removing end of line */
72 nbuf = strchr(buf, '\n');
78 /* Assigning buf to be used */
82 /* Excluding commented lines or blanked ones */
85 if(*nbuf == ' ' || *nbuf == '\t')
101 /* Going to next line if empty */
115 /** int _rkcl_is_name
117 int _rkcl_is_name(char *buf)
119 if(*buf == '[' && buf[strlen(buf) -1] == ']')
128 /** int _rkcl_get_vars(vars, nbuf)
130 int _rkcl_get_vars(OSStore *vars, char *nbuf)
136 /* If not a variable, return 0 */
143 /* Removing ; from the end. */
144 tmp = strchr(nbuf, ';');
156 tmp = strchr(nbuf, '=');
168 /* Dumping the variable options. */
169 os_strdup(nbuf, var_name);
170 os_strdup(tmp, var_value);
173 /* Adding entry to the storage */
174 OSStore_Put(vars, var_name, var_value);
180 /** int _rkcl_get_name
182 char *_rkcl_get_name(char *buf, char *ref, int *condition)
189 /* Checking if name is valid */
190 if(!_rkcl_is_name(buf))
197 tmp_location = strchr(buf, ']');
202 *tmp_location = '\0';
205 /* Getting condition */
207 if(*tmp_location != ' ' && tmp_location[1] != '[')
213 tmp_location2 = strchr(tmp_location, ']');
218 *tmp_location2 = '\0';
222 /* Getting condition */
223 if(strcmp(tmp_location, "all") == 0)
225 *condition |= RKCL_COND_ALL;
227 else if(strcmp(tmp_location,"any") == 0)
229 *condition |= RKCL_COND_ANY;
231 else if(strcmp(tmp_location,"any required") == 0)
233 *condition |= RKCL_COND_ANY;
234 *condition |= RKCL_COND_REQ;
236 else if(strcmp(tmp_location, "all required") == 0)
238 *condition |= RKCL_COND_ALL;
239 *condition |= RKCL_COND_REQ;
243 *condition = RKCL_COND_INV;
248 /* Getting reference */
249 if(*tmp_location2 != ' ' && tmp_location2[1] != '[')
255 tmp_location = strchr(tmp_location2, ']');
260 *tmp_location = '\0';
262 /* Copying reference */
263 strncpy(ref, tmp_location2, 255);
270 /** char *_rkcl_get_pattern(char *value)
272 char *_rkcl_get_pattern(char *value)
274 while(*value != '\0')
276 if((*value == ' ') && (value[1] == '-') &&
277 (value[2] == '>') && (value[3] == ' '))
292 /** char *_rkcl_get_value
294 char *_rkcl_get_value(char *buf, int *type)
299 /* Zeroing type before using it --make sure return is valid
304 value = strchr(buf, ':');
313 tmp_str = strchr(value, ';');
321 /* Getting types - removing negate flag (using later) */
327 if(strcmp(buf, "f") == 0)
329 *type = RKCL_TYPE_FILE;
331 else if(strcmp(buf, "r") == 0)
333 *type = RKCL_TYPE_REGISTRY;
335 else if(strcmp(buf, "p") == 0)
337 *type = RKCL_TYPE_PROCESS;
339 else if(strcmp(buf, "d") == 0)
341 *type = RKCL_TYPE_DIR;
353 /** int rkcl_get_entry:
355 int rkcl_get_entry(FILE *fp, char *msg, void *p_list_p)
357 int type = 0, condition = 0, root_dir_len = 0;
359 char buf[OS_SIZE_1024 +2];
360 char root_dir[OS_SIZE_1024 +2];
361 char final_file[2048 +1];
368 OSList *p_list = (OSList *)p_list_p;
371 /* Cleaning up vars */
372 memset(buf, '\0', sizeof(buf));
373 memset(root_dir, '\0', sizeof(root_dir));
374 memset(final_file, '\0', sizeof(final_file));
375 memset(ref, '\0', sizeof(ref));
378 root_dir_len = sizeof(root_dir) -1;
382 /* Getting Windows rootdir */
383 _rkcl_getrootdir(root_dir, root_dir_len);
384 if(root_dir[0] == '\0')
386 merror(INVALID_ROOTDIR, ARGV0);
391 /* Getting variables */
392 vars = OSStore_Create();
395 /* We first read all variables -- they must be defined at the top. */
399 nbuf = _rkcl_getfp(fp, buf);
405 rc_code = _rkcl_get_vars(vars, nbuf);
410 else if(rc_code == -1)
412 merror(INVALID_RKCL_VAR, ARGV0, nbuf);
418 /* Getting first name */
419 name = _rkcl_get_name(nbuf, ref, &condition);
420 if(name == NULL || condition == RKCL_COND_INV)
422 merror(INVALID_RKCL_NAME, ARGV0, nbuf);
428 /* Getting the real entries. */
434 /* Getting entry name */
437 merror(INVALID_RKCL_NAME, ARGV0, "NULL");
441 debug2("%s: DEBUG: Checking entry: '%s'.", ARGV0, name);
444 /* Getting each value */
451 nbuf = _rkcl_getfp(fp, buf);
458 /* We first try to get the name, looking for new entries */
459 if(_rkcl_is_name(nbuf))
465 /* Getting value to look for */
466 value = _rkcl_get_value(nbuf, &type);
469 merror(INVALID_RKCL_VALUE, ARGV0, nbuf);
474 /* Getting negate value */
482 /* Checking for a file. */
483 if(type == RKCL_TYPE_FILE)
485 char *pattern = NULL;
486 char *f_value = NULL;
489 pattern = _rkcl_get_pattern(value);
493 /* Getting any variable. */
496 f_value = OSStore_Get(vars, value);
499 merror(INVALID_RKCL_VAR, ARGV0, value);
506 else if(value[0] == '\\')
508 final_file[0] = '\0';
509 final_file[sizeof(final_file) -1] = '\0';
511 snprintf(final_file, sizeof(final_file) -2, "%s%s",
513 f_value = final_file;
517 final_file[0] = '\0';
518 final_file[sizeof(final_file) -1] = '\0';
520 ExpandEnvironmentStrings(value, final_file,
521 sizeof(final_file) -2);
522 f_value = final_file;
527 debug2("%s: DEBUG: Checking file: '%s'.", ARGV0, f_value);
528 if(rk_check_file(f_value, pattern))
530 debug1("%s: DEBUG: found file.", ARGV0);
536 /* Checking for a registry entry */
537 else if(type == RKCL_TYPE_REGISTRY)
540 char *pattern = NULL;
543 /* Looking for additional entries in the registry
544 * and a pattern to match.
546 entry = _rkcl_get_pattern(value);
549 pattern = _rkcl_get_pattern(entry);
554 debug2("%s: DEBUG: Checking registry: '%s'.", ARGV0, value);
555 if(is_registry(value, entry, pattern))
557 debug2("%s: DEBUG: found registry.", ARGV0);
564 /* Checking for a directory. */
565 else if(type == RKCL_TYPE_DIR)
568 char *pattern = NULL;
569 char *f_value = NULL;
573 file = _rkcl_get_pattern(value);
576 pattern = _rkcl_get_pattern(file);
580 /* Getting any variable. */
583 f_value = OSStore_Get(vars, value);
586 merror(INVALID_RKCL_VAR, ARGV0, value);
596 /* Checking for multiple, comma separated directories. */
598 f_value = strchr(dir, ',');
607 debug2("%s: Checking dir: %s", ARGV0, dir);
608 if(rk_check_dir(dir, file, pattern))
610 debug2("%s: DEBUG: Found dir.", ARGV0);
621 f_value = strchr(dir, ',');
635 /* Checking for a process. */
636 else if(type == RKCL_TYPE_PROCESS)
638 debug2("%s: DEBUG: Checking process: '%s'.", ARGV0, value);
639 if(is_process(value, p_list))
641 debug2("%s: DEBUG: found process.", ARGV0);
647 /* Switching the values if ! is present */
661 /** Checking the conditions **/
662 if(condition & RKCL_COND_ANY)
664 debug2("%s: DEBUG: Condition ANY.", ARGV0);
670 /* Condition for ALL */
673 debug2("%s: DEBUG: Condition ALL.", ARGV0);
674 if(found && (g_found != -1))
683 }while(value != NULL);
686 /* Alerting if necessary */
690 char op_msg[OS_SIZE_1024 +1];
691 char **p_alert_msg = rootcheck.alert_msg;
697 snprintf(op_msg, OS_SIZE_1024, "%s %s.%s"
698 " Reference: %s .",msg, name,
699 p_alert_msg[j]?p_alert_msg[j]:"\0",
704 snprintf(op_msg, OS_SIZE_1024, "%s %s.%s",msg,
705 name, p_alert_msg[j]?p_alert_msg[j]:"\0");
708 if((type == RKCL_TYPE_DIR) || (j == 0))
710 notify_rk(ALERT_POLICY_VIOLATION, op_msg);
715 free(p_alert_msg[j]);
716 p_alert_msg[j] = NULL;
731 while(rootcheck.alert_msg[j])
733 free(rootcheck.alert_msg[j]);
734 rootcheck.alert_msg[j] = NULL;
739 /* Checking if this entry is required for the rest of the file. */
740 if(condition & RKCL_COND_REQ)
747 /* Ending if we don't have anything else. */
754 /* Cleaning up name. */
762 /* Getting name already read */
763 name = _rkcl_get_name(nbuf, ref, &condition);
766 merror(INVALID_RKCL_NAME, ARGV0, nbuf);
769 }while(nbuf != NULL);
773 /* Cleaning up the memory */
780 vars = OSStore_Free(vars);