1 /* Copyright (C) 2009 Trend Micro Inc.
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
12 static char *_read_file(const char *high_name, const char *low_name, const char *defines_file) __attribute__((nonnull(3)));
13 static const char *__gethour(const char *str, char *ossec_hour) __attribute__((nonnull));
16 /* Read the file and return a string the matches the following
17 * format: high_name.low_name.
18 * If return is not null, value must be freed
20 static char *_read_file(const char *high_name, const char *low_name, const char *defines_file)
23 char def_file[OS_FLSIZE + 1];
24 char buf[OS_SIZE_1024 + 1];
31 snprintf(def_file, OS_FLSIZE, "%s", defines_file);
33 snprintf(def_file, OS_FLSIZE, "%s%s", DEFAULTDIR, defines_file);
36 snprintf(def_file, OS_FLSIZE, "%s", defines_file);
39 fp = fopen(def_file, "r");
41 if (strcmp(defines_file, OSSEC_LDEFINES) != 0) {
42 merror(FOPEN_ERROR, __local_name, def_file, errno, strerror(errno));
48 if (!high_name || !low_name) {
49 merror(NULL_ERROR, __local_name);
55 buf[OS_SIZE_1024] = '\0';
56 while (fgets(buf, OS_SIZE_1024 , fp) != NULL) {
57 /* Commented or blank lines */
58 if (buf[0] == '#' || buf[0] == ' ' || buf[0] == '\n') {
62 /* Messages not formatted correctly */
63 buf_pt = strchr(buf, '.');
65 merror(FGETS_ERROR, __local_name, def_file, buf);
69 /* Check for the high name */
72 if (strcmp(buf, high_name) != 0) {
79 buf_pt = strchr(buf_pt, '=');
81 merror(FGETS_ERROR, __local_name, def_file, buf);
85 /* Check for the low name */
88 if (strcmp(tmp_buffer, low_name) != 0) {
92 /* Remove newlines or anything that will cause errors */
93 tmp_buffer = strrchr(buf_pt, '\n');
97 tmp_buffer = strrchr(buf_pt, '\r');
102 os_strdup(buf_pt, ret);
111 /* Get an integer definition. This function always return on
112 * success or exits on error.
114 int getDefine_Int(const char *high_name, const char *low_name, int min, int max)
120 /* Try to read from the local define file */
121 value = _read_file(high_name, low_name, OSSEC_LDEFINES);
123 value = _read_file(high_name, low_name, OSSEC_DEFINES);
125 ErrorExit(DEF_NOT_FOUND, __local_name, high_name, low_name);
130 while (*pt != '\0') {
131 if (!isdigit((int)*pt)) {
132 ErrorExit(INV_DEF, __local_name, high_name, low_name, value);
138 if ((ret < min) || (ret > max)) {
139 ErrorExit(INV_DEF, __local_name, high_name, low_name, value);
148 /* Check if IP_address is present at that_IP
149 * Returns 1 on success or 0 on failure
151 int OS_IPFound(const char *ip_address, const os_ip *that_ip)
156 /* If negate is set */
157 char *ip = that_ip->ip;
163 /* The simplest case is the 'any' case.
164 * We just return true
166 if( strcmp(ip, "any") == 0 ) {
170 memset(&temp_ip, 0, sizeof(struct _os_ip));
172 /* Extract IP address */
173 if (OS_IsValidIP(ip_address, &temp_ip) == 0) {
178 /* Check if IP is in thatip & netmask */
179 if (sacmp((struct sockaddr *) &temp_ip.ss,
180 (struct sockaddr *) &that_ip->ss,
181 that_ip->prefixlength)) {
189 /* Check if IP_address is present in the "list_of_ips".
190 * Returns 1 on success or 0 on failure
191 * The list MUST be NULL terminated
193 int OS_IPFoundList(const char *ip_address, os_ip **list_of_ips)
198 memset(&temp_ip, 0, sizeof(struct _os_ip));
200 /* Extract IP address */
201 if (OS_IsValidIP(ip_address, &temp_ip) == 0) {
205 while (*list_of_ips) {
206 os_ip *l_ip = *list_of_ips;
217 /* Simplest case, if the list contains an any
218 * ip, we return true.
220 if( strcmp(ip,"any" ) == 0 ) {
224 /* Checking if ip is in thatip & netmask */
225 if (sacmp((struct sockaddr *) &temp_ip.ss,
226 (struct sockaddr *) &l_ip->ss,
227 l_ip->prefixlength)) {
236 /** int OS_IsValidIP(char *ip_address, os_ip *final_ip)
237 * Validate if an IP address is in the right format
238 * Returns 0 if doesn't match or 1 if it is an IP or 2 an IP with CIDR.
239 * WARNING: On success this function may modify the value of ip_address
241 int OS_IsValidIP(const char *in_address, os_ip *final_ip)
244 int cidr = -1, prefixlength;
245 struct addrinfo hints, *result;
246 char *ip_address = NULL;
253 /* We mess with in_address later and we set 'const'
254 * in the signature, so we need to copy it
257 os_strdup(in_address, ip_address);
260 os_strdup(ip_address, final_ip->ip);
263 if (*ip_address == '!') {
265 os_strdup(in_address+1, ip_address);
268 /* Use IPv6 here, because it doesn't matter
269 * OS_IPFound and OS_IPFoundList will
270 * return true if the os_ip.ip element is 'any'
272 if(strcmp(ip_address, "any") == 0) {
273 //strcpy(ip_address, "::/0");
274 free(ip_address); // Free the old value before writing the new one?
275 os_strdup("::/0", ip_address);
278 /* Getting the cidr/netmask if available */
279 tmp_str = strchr(ip_address,'/');
285 if(strlen(tmp_str) <= 3) {
286 cidr = atoi(tmp_str);
293 /* No cidr available */
294 memset(&hints, 0, sizeof(struct addrinfo));
295 hints.ai_flags = AI_NUMERICHOST;
296 if (getaddrinfo(ip_address, NULL, &hints, &result) != 0) {
301 switch (result->ai_family)
304 if (cidr >=0 && cidr <= 32) {
307 } else if (cidr < 0) {
315 if (cidr >=0 && cidr <= 128) {
318 } else if (cidr < 0) {
332 memcpy(&(final_ip->ss), result->ai_addr, result->ai_addrlen);
333 final_ip->prefixlength = prefixlength;
336 freeaddrinfo(result);
339 return((cidr >= 0) ? 2 : 1);
342 /** int sacmp(struct sockaddr *sa1, struct sockaddr *sa2, int prefixlength)
343 * Compares two sockaddrs up to prefixlength.
344 * Returns 0 if doesn't match or 1 if they do.
346 int sacmp(struct sockaddr *sa1, struct sockaddr *sa2, int prefixlength)
349 int i, realaf1, realaf2;
351 char *addr1, *addr2, modbits;
353 // If we have no prefixlength just return a match
354 // * This handles the "any" case
359 switch (sa1->sa_family)
362 addr1 = (char *) &(((struct sockaddr_in *) sa1)->sin_addr);
366 addr1 = (char *) &(((struct sockaddr_in6 *) sa1)->sin6_addr);
368 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *) addr1))
369 { /* shift the pointer for a mapped address */
370 addr1 += (sizeof (struct in6_addr)) - (sizeof (struct in_addr));
378 switch (sa2->sa_family)
381 addr2 = (char *) &(((struct sockaddr_in *) sa2)->sin_addr);
385 addr2 = (char *) &(((struct sockaddr_in6 *) sa2)->sin6_addr);
387 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *) addr2)) {
388 /* shift the pointer for a mapped address */
389 addr2 += (sizeof (struct in6_addr)) - (sizeof (struct in_addr));
397 if (realaf1 != realaf2) {
401 ip_div = div(prefixlength, 8);
403 for (i=0; i < ip_div.quot; i++) {
404 if (addr1[i] != addr2[i]) {
409 modbits = ((unsigned char) ~0) << (8 - ip_div.rem);
410 if ( (addr1[i] & modbits) != (addr2[i] & modbits) ) {
418 /* Must be a valid string, called after OS_IsValidTime
419 * Returns 1 on success or 0 on failure
421 int OS_IsonTime(const char *time_str, const char *ossec_time)
425 if (*ossec_time == '!') {
430 /* Comparing against min/max value */
431 if ((strncmp(time_str, ossec_time, 5) >= 0) &&
432 (strncmp(time_str, ossec_time + 5, 5) <= 0)) {
439 /* Validate if a time is in an acceptable format for OSSEC.
440 * Returns 0 if doesn't match or a valid string for OSSEC usage in success.
441 * ** On success this function may modify the value of date
442 * Acceptable formats:
443 * hh:mm - hh:mm (24 hour format)
444 * !hh:mm -hh:mm (24 hour format)
445 * hh - hh (24 hour format)
446 * hh:mm am - hh:mm pm (12 hour format)
447 * hh am - hh pm (12 hour format)
449 #define RM_WHITE(x)while(*x == ' ')x++;
451 static const char *__gethour(const char *str, char *ossec_hour)
457 /* Invalid time format */
458 if (!isdigit((int)*str)) {
459 merror(INVALID_TIME, __local_name, str);
465 /* Get a valid hour */
466 if (chour < 0 || chour >= 24) {
467 merror(INVALID_TIME, __local_name, str);
471 /* Go after the hour */
472 while (isdigit((int)*str)) {
479 merror(INVALID_TIME, __local_name, str);
486 if ((!isdigit((int)*str) ||
487 !isdigit((int) * (str + 1))) && isdigit((int) * (str + 2))) {
488 merror(INVALID_TIME, __local_name, str);
499 if ((*str == 'a') || (*str == 'A')) {
501 if ((*str == 'm') || (*str == 'M')) {
502 snprintf(ossec_hour, 6, "%02d:%02d", chour, cmin);
506 } else if ((*str == 'p') || (*str == 'P')) {
508 if ((*str == 'm') || (*str == 'M')) {
513 /* New hour must be valid */
514 if (chour < 0 || chour >= 24) {
515 merror(INVALID_TIME, __local_name, str);
519 snprintf(ossec_hour, 6, "%02d:%02d", chour, cmin);
525 snprintf(ossec_hour, 6, "%02d:%02d", chour, cmin);
530 merror(INVALID_TIME, __local_name, str);
534 char *OS_IsValidTime(const char *time_str)
541 /* Must be not null */
547 memset(first_hour, '\0', 7);
548 memset(second_hour, '\0', 7);
553 /* Check for negative */
554 if (*time_str == '!') {
558 /* We may have spaces after the '!' */
563 time_str = __gethour(time_str, first_hour);
571 if (*time_str != '-') {
580 /* Get second hour */
581 time_str = __gethour(time_str, second_hour);
587 if (*time_str != '\0') {
591 os_calloc(13, sizeof(char), ret);
594 if (strcmp(first_hour, second_hour) > 0) {
595 snprintf(ret, 12, "!%s%s", second_hour, first_hour);
599 /* For the normal times */
600 snprintf(ret, 12, "%c%s%s", ng == 0 ? '.' : '!', first_hour, second_hour);
604 /* Check if the current time is the same or has passed the specified one */
605 int OS_IsAfterTime(const char *time_str, const char *ossec_time)
607 /* Unique times can't have a ! */
608 if (*ossec_time == '!') {
614 /* Compare against min/max value */
615 if (strncmp(time_str, ossec_time, 5) >= 0) {
622 /* Create a unique time, not a range. Must be used with OS_IsAfterTime. */
623 char *OS_IsValidUniqueTime(const char *time_str)
625 char mytime[128 + 1];
627 if (*time_str == '!') {
631 memset(mytime, '\0', 128 + 1);
632 snprintf(mytime, 128, "%s-%s", time_str, time_str);
634 return (OS_IsValidTime(mytime));
637 /* Check if the specified week day is in the range */
638 int OS_IsonDay(int week_day, const char *ossec_day)
643 if (ossec_day[7] == '!') {
647 if (week_day < 0 || week_day > 7) {
651 /* It is on the right day */
652 if (ossec_day[week_day] == 1) {
659 /* Validate if a day is in an acceptable format for OSSEC
660 * Returns 0 if doesn't match or a valid string for OSSEC usage in success.
661 * WARNING: On success this function may modify the value of date
662 * Acceptable formats:
663 * weekdays, weekends, monday, tuesday, thursday,..
667 #define RM_SEP(x)while((*x == ' ') || (*x == ','))x++;
669 #define IS_SEP(x) (*x == ' ' || *x == ',')
671 char *OS_IsValidDay(const char *day_str)
675 char day_ret[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
676 const char *(days[]) = {
677 "sunday", "sun", "monday", "mon", "tuesday", "tue",
678 "wednesday", "wed", "thursday", "thu", "friday",
679 "fri", "saturday", "sat", "weekdays", "weekends", NULL
681 int days_int[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8};
683 /* Must be a valid string */
690 /* Check for negatives */
691 if (*day_str == '!') {
696 while (*day_str != '\0') {
699 if (strncasecmp(day_str, days[i], strlen(days[i])) == 0) {
701 if (days_int[i] == 7) {
709 else if (days_int[i] == 8) {
713 day_ret[days_int[i]] = 1;
721 merror(INVALID_DAY, __local_name, day_str);
725 day_str += strlen(days[i]);
727 if (IS_SEP(day_str)) {
730 } else if (*day_str == '\0') {
733 merror(INVALID_DAY, __local_name, day_str);
739 os_calloc(9, sizeof(char), ret);
746 for (i = 0; i <= 6; i++) {
747 /* Check if some is checked */
748 if (day_ret[i] == 1) {
754 /* At least one day must be checked */
757 merror(INVALID_DAY, __local_name, day_str);