1 /*****
2 *
3 * Copyright (C) 2004-2015 CS-SI. All Rights Reserved.
4 * Author: Nicolas Delon <nicolas.delon@prelude-ids.com>
5 * Author: Yoann Vandoorselaere <yoann@prelude-ids.com>
6 *
7 * This file is part of the Prelude library.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 *****/
24 
25 #include "config.h"
26 #include "libmissing.h"
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <sys/types.h>
33 #include <regex.h>
34 #include <stdarg.h>
35 #include <errno.h>
36 
37 #include "common.h"
38 #include "prelude-log.h"
39 #include "prelude-error.h"
40 #include "prelude-inttypes.h"
41 
42 #include "idmef.h"
43 #include "idmef-criterion-value.h"
44 
45 
46 
47 
48 struct match_cb {
49         unsigned int nmatch;
50         unsigned int match;
51         idmef_criterion_value_t *cv;
52         idmef_criterion_operator_t operator;
53 };
54 
55 
56 struct regex_value {
57         regex_t regex;
58         char *regex_string;
59 };
60 
61 
62 
63 struct idmef_criterion_value {
64 
65         void *value;
66         prelude_bool_t value_need_free;
67         idmef_criterion_value_type_t type;
68 
69         int (*clone)(const idmef_criterion_value_t *cv, idmef_criterion_value_t *dst);
70         int (*print)(const idmef_criterion_value_t *cv, prelude_io_t *fd);
71         int (*to_string)(const idmef_criterion_value_t *cv, prelude_string_t *out);
72         int (*match)(const idmef_criterion_value_t *cv, idmef_criterion_operator_t operator, idmef_value_t *value);
73         void (*destroy)(idmef_criterion_value_t *cv);
74 };
75 
76 
77 
78 /*
79  * time stuff
80  */
btime_parse_simple(const char * integer,int * out)81 static int btime_parse_simple(const char *integer, int *out)
82 {
83         *out = atoi(integer);
84         return 0;
85 }
86 
87 
88 
89 
btime_parse_year(const char * integer,int * out)90 static int btime_parse_year(const char *integer, int *out)
91 {
92         *out = atoi(integer) - 1900;
93         return 0;
94 }
95 
96 
97 
btime_parse_month(const char * value,int * out)98 static int btime_parse_month(const char *value, int *out)
99 {
100         int i;
101         const char *months[] = {
102                 "january",
103                 "february",
104                 "march",
105                 "april",
106                 "may",
107                 "june",
108                 "july",
109                 "august",
110                 "september",
111                 "october",
112                 "november",
113                 "december"
114         };
115 
116         if ( isdigit((int) *value) ) {
117                 *out = atoi(value) - 1;
118                 return 0;
119         }
120 
121         for ( i = 0; i < (int) (sizeof(months) / sizeof(*months)); i++ ) {
122                 if ( strcasecmp(value, months[i]) == 0 ) {
123                         *out = i; /* Numbered 0 to 11 */
124                         return 0;
125                 }
126         }
127 
128         return -1;
129 }
130 
131 
btime_parse_wday(const char * value,int * out)132 static int btime_parse_wday(const char *value, int *out)
133 {
134         int i;
135         const char *days[] = {
136                 "sunday",
137                 "monday",
138                 "tuesday",
139                 /* happy days ! ;) */
140                 "wednesday",
141                 "thursday",
142                 "friday",
143                 "saturday",
144         };
145 
146         if ( isdigit((int) *value) ) {
147                 *out = atoi(value) - 1;
148                 return 0;
149         }
150 
151         for ( i = 0; i < (int) (sizeof(days) / sizeof(*days)); i++ ) {
152 
153                 if ( strcasecmp(value, days[i]) == 0 ) {
154                         *out = i; /* Numbered 0 (sunday) to 6 */
155                         return 0;
156                 }
157         }
158 
159         return -1;
160 }
161 
162 
163 
integer_compare(time_t matched,time_t wanted,idmef_criterion_operator_t op)164 static int integer_compare(time_t matched, time_t wanted, idmef_criterion_operator_t op)
165 {
166         if ( op & IDMEF_CRITERION_OPERATOR_EQUAL && matched == wanted )
167                 return 1;
168 
169         if ( op & IDMEF_CRITERION_OPERATOR_LESSER && matched < wanted)
170                 return 1;
171 
172         if ( op & IDMEF_CRITERION_OPERATOR_GREATER && matched > wanted )
173                 return 1;
174 
175         return 0;
176 }
177 
178 
179 
do_btime_match(const idmef_criterion_value_t * cv,idmef_criterion_operator_t op,idmef_value_t * value)180 static int do_btime_match(const idmef_criterion_value_t *cv, idmef_criterion_operator_t op, idmef_value_t *value)
181 {
182         int ret;
183         time_t sec;
184         struct tm lt, *comp = cv->value;
185         prelude_bool_t need_full_compare = FALSE;
186 
187         if ( idmef_value_get_type(value) != IDMEF_VALUE_TYPE_TIME )
188                 return -1;
189 
190         sec = idmef_time_get_sec(idmef_value_get_time(value));
191         if ( ! gmtime_r(&sec, &lt) )
192                 return prelude_error_from_errno(errno);
193 
194         /*
195          * Apply mask
196          */
197         if ( comp->tm_sec < 0 ) lt.tm_sec = -1;
198         else need_full_compare = TRUE;
199 
200         if ( comp->tm_min < 0 ) lt.tm_min = -1;
201         else need_full_compare = TRUE;
202 
203         if ( comp->tm_mon < 0 ) lt.tm_mon = -1;
204         else need_full_compare = TRUE;
205 
206         if ( comp->tm_hour < 0 ) lt.tm_hour = -1;
207         else need_full_compare = TRUE;
208 
209         if ( comp->tm_mday < 0 ) lt.tm_mday = -1;
210         else need_full_compare = TRUE;
211 
212         if ( comp->tm_year < 0 ) lt.tm_year = -1;
213         else need_full_compare = TRUE;
214 
215         if ( comp->tm_wday < 0 ) lt.tm_wday = -1;
216         if ( comp->tm_yday < 0 ) lt.tm_yday = -1;
217 
218         /*
219          * The timegm() function ignores values supplied in the tm_wday
220          * and tm_yday fields, match them manually:
221          */
222         if ( comp->tm_wday >= 0 ) {
223                 ret = integer_compare(lt.tm_wday, comp->tm_wday, (need_full_compare) ? op | IDMEF_CRITERION_OPERATOR_EQUAL : op);
224                 if ( ret != 1 )
225                         return ret;
226         }
227 
228         if ( comp->tm_yday >= 0 ) {
229                 ret = integer_compare(lt.tm_yday, comp->tm_yday, (need_full_compare) ? op | IDMEF_CRITERION_OPERATOR_EQUAL : op);
230                 if ( ret != 1 )
231                         return ret;
232         }
233 
234         if ( ! need_full_compare )
235                 return 1;
236 
237         return integer_compare(timegm(&lt), timegm(comp), op);
238 }
239 
240 
241 
btime_match(const idmef_criterion_value_t * cv,idmef_criterion_operator_t operator,idmef_value_t * value)242 static int btime_match(const idmef_criterion_value_t *cv, idmef_criterion_operator_t operator, idmef_value_t *value)
243 {
244         int ret;
245 
246         ret = do_btime_match(cv, operator, value);
247         if ( ret < 0 )
248                 return ret;
249 
250         if ( operator & IDMEF_CRITERION_OPERATOR_NOT )
251                 return (ret == 1) ? 0 : 1;
252         else
253                 return (ret == 1) ? 1 : 0;
254 }
255 
256 
257 
btime_to_string(const idmef_criterion_value_t * cv,prelude_string_t * out)258 static int btime_to_string(const idmef_criterion_value_t *cv, prelude_string_t *out)
259 {
260         struct tm *lt = cv->value;
261 
262         if ( lt->tm_year != -1 )
263                 prelude_string_sprintf(out, "year:%d ", lt->tm_year + 1900);
264 
265         if ( lt->tm_yday != -1 )
266                 prelude_string_sprintf(out, "yday:%d ", lt->tm_yday);
267 
268         if ( lt->tm_mon != -1 )
269                 prelude_string_sprintf(out, "month:%d ", lt->tm_mon);
270 
271         if ( lt->tm_mday != -1 )
272                 prelude_string_sprintf(out, "mday:%d ", lt->tm_mday);
273 
274         if ( lt->tm_wday != -1 )
275                 prelude_string_sprintf(out, "wday:%d ", lt->tm_wday);
276 
277         if ( lt->tm_hour != -1 )
278                 prelude_string_sprintf(out, "hour:%d ", lt->tm_hour);
279 
280         if ( lt->tm_min != -1 )
281                 prelude_string_sprintf(out, "min:%d ", lt->tm_min);
282 
283         if ( lt->tm_sec != -1 )
284                 prelude_string_sprintf(out, "sec:%d ", lt->tm_sec);
285 
286         return 0;
287 }
288 
289 
btime_print(const idmef_criterion_value_t * cv,prelude_io_t * fd)290 static int btime_print(const idmef_criterion_value_t *cv, prelude_io_t *fd)
291 {
292         int ret;
293         prelude_string_t *out;
294 
295         ret = prelude_string_new(&out);
296         if ( ret < 0 )
297                 return ret;
298 
299         ret = btime_to_string(cv, out);
300         if ( ret < 0 ) {
301                 prelude_string_destroy(out);
302                 return ret;
303         }
304 
305         ret = prelude_io_write(fd, prelude_string_get_string(out), prelude_string_get_len(out));
306         prelude_string_destroy(out);
307 
308         return ret;
309 }
310 
311 
312 
btime_clone(const idmef_criterion_value_t * src,idmef_criterion_value_t * dst)313 static int btime_clone(const idmef_criterion_value_t *src, idmef_criterion_value_t *dst)
314 {
315         /*
316          * The API does not allow to change the value of an existing
317          * idmef_criterion_value_t object, so we can simply regerence the source.
318          */
319         dst->value_need_free = FALSE;
320         dst->value = src->value;
321         return 0;
322 }
323 
324 
325 
btime_destroy(idmef_criterion_value_t * cv)326 static void btime_destroy(idmef_criterion_value_t *cv)
327 {
328         if ( cv->value_need_free )
329                 free(cv->value);
330 }
331 
332 
333 
334 
335 /*
336  * regex stuff
337  */
regex_match(const idmef_criterion_value_t * cv,idmef_criterion_operator_t operator,idmef_value_t * value)338 static int regex_match(const idmef_criterion_value_t *cv, idmef_criterion_operator_t operator, idmef_value_t *value)
339 {
340         int ret;
341         const char *str = NULL;
342         idmef_class_id_t class;
343         struct regex_value *rv = cv->value;
344 
345         if ( idmef_value_get_type(value) == IDMEF_VALUE_TYPE_STRING )
346                 str = prelude_string_get_string(idmef_value_get_string(value));
347 
348         else if ( idmef_value_get_type(value) == IDMEF_VALUE_TYPE_ENUM ) {
349                 class = idmef_value_get_class(value);
350                 str = idmef_class_enum_to_string(class, idmef_value_get_enum(value));
351         }
352 
353         else if ( idmef_value_get_type(value) == IDMEF_VALUE_TYPE_DATA ) {
354                 idmef_data_t *data;
355 
356                 data = idmef_value_get_data(value);
357                 if ( idmef_data_get_type(data) == IDMEF_DATA_TYPE_CHAR_STRING )
358                         str = idmef_data_get_data(data);
359         }
360 
361         if ( ! str )
362                 return 0;
363 
364         ret = regexec(&rv->regex, str, 0, NULL, 0);
365         if ( operator & IDMEF_CRITERION_OPERATOR_NOT )
366                 return (ret == REG_NOMATCH) ? 1 : 0;
367         else
368                 return (ret != REG_NOMATCH) ? 1 : 0;
369 }
370 
371 
372 
regex_print(const idmef_criterion_value_t * cv,prelude_io_t * fd)373 static int regex_print(const idmef_criterion_value_t *cv, prelude_io_t *fd)
374 {
375         struct regex_value *rv = cv->value;
376         prelude_io_write(fd, rv->regex_string, strlen(rv->regex_string));
377         return 0;
378 }
379 
380 
381 
regex_to_string(const idmef_criterion_value_t * cv,prelude_string_t * out)382 static int regex_to_string(const idmef_criterion_value_t *cv, prelude_string_t *out)
383 {
384         struct regex_value *rv = cv->value;
385         return prelude_string_cat(out, rv->regex_string);
386 }
387 
388 
389 
regex_clone(const idmef_criterion_value_t * src,idmef_criterion_value_t * dst)390 static int regex_clone(const idmef_criterion_value_t *src, idmef_criterion_value_t *dst)
391 {
392         /*
393          * The API does not allow to change the value of an existing
394          * idmef_criterion_value_t object, so we can simply regerence the source.
395          */
396         dst->value_need_free = FALSE;
397         dst->value = src->value;
398         return 0;
399 }
400 
401 
402 
regex_destroy(idmef_criterion_value_t * cv)403 static void regex_destroy(idmef_criterion_value_t *cv)
404 {
405         struct regex_value *rv;
406 
407         if ( ! cv->value_need_free )
408                 return;
409 
410         rv = cv->value;
411 
412         free(rv->regex_string);
413         regfree(&rv->regex);
414         free(rv);
415 }
416 
417 
418 
419 
420 /*
421  * value stuff
422  */
value_match(const idmef_criterion_value_t * cv,idmef_criterion_operator_t operator,idmef_value_t * value)423 static int value_match(const idmef_criterion_value_t *cv, idmef_criterion_operator_t operator, idmef_value_t *value)
424 {
425         return idmef_value_match(value, cv->value, operator);
426 }
427 
428 
429 
value_print(const idmef_criterion_value_t * cv,prelude_io_t * fd)430 static int value_print(const idmef_criterion_value_t *cv, prelude_io_t *fd)
431 {
432         return idmef_value_print(cv->value, fd);
433 }
434 
435 
436 
value_to_string(const idmef_criterion_value_t * cv,prelude_string_t * out)437 static int value_to_string(const idmef_criterion_value_t *cv, prelude_string_t *out)
438 {
439         return idmef_value_to_string(cv->value, out);
440 }
441 
442 
443 
value_clone(const idmef_criterion_value_t * cv,idmef_criterion_value_t * dst)444 static int value_clone(const idmef_criterion_value_t *cv, idmef_criterion_value_t *dst)
445 {
446         int ret;
447         idmef_value_t *res;
448 
449         ret = idmef_value_clone(cv->value, &res);
450         dst->value = res;
451 
452         return ret;
453 }
454 
455 
456 
value_destroy(idmef_criterion_value_t * cv)457 static void value_destroy(idmef_criterion_value_t *cv)
458 {
459         idmef_value_destroy(cv->value);
460 }
461 
462 
463 
464 /*
465  *
466  */
do_match_cb(idmef_value_t * value,void * extra)467 static int do_match_cb(idmef_value_t *value, void *extra)
468 {
469         int ret;
470         struct match_cb *mcb = extra;
471         idmef_criterion_value_t *cv = mcb->cv;
472         idmef_criterion_operator_t operator = mcb->operator;
473 
474         if ( idmef_value_is_list(value) )
475                 return idmef_value_iterate(value, do_match_cb, mcb);
476 
477         ret = cv->match(cv, operator, value);
478         if ( ret < 0 )
479                 return ret;
480 
481         if ( ret > 0 )
482                 mcb->match++;
483         else
484                 mcb->nmatch++;
485 
486         return 0;
487 }
488 
489 
idmef_criterion_value_destroy(idmef_criterion_value_t * value)490 void idmef_criterion_value_destroy(idmef_criterion_value_t *value)
491 {
492         value->destroy(value);
493         free(value);
494 }
495 
496 
497 
idmef_criterion_value_clone(const idmef_criterion_value_t * src,idmef_criterion_value_t ** dst)498 int idmef_criterion_value_clone(const idmef_criterion_value_t *src, idmef_criterion_value_t **dst)
499 {
500         int ret;
501 
502         ret = idmef_criterion_value_new(dst);
503         if ( ret < 0 )
504                 return ret;
505 
506         (*dst)->type = src->type;
507         (*dst)->clone = src->clone;
508         (*dst)->print = src->print;
509         (*dst)->to_string = src->to_string;
510         (*dst)->match = src->match;
511         (*dst)->destroy = src->destroy;
512 
513         ret = src->clone(src, *dst);
514         if ( ret < 0 ) {
515                 free(*dst);
516                 return ret;
517         }
518 
519         return 0;
520 }
521 
522 
523 
idmef_criterion_value_print(idmef_criterion_value_t * cv,prelude_io_t * fd)524 int idmef_criterion_value_print(idmef_criterion_value_t *cv, prelude_io_t *fd)
525 {
526         return cv->print(cv, fd);
527 }
528 
529 
530 
idmef_criterion_value_to_string(idmef_criterion_value_t * cv,prelude_string_t * out)531 int idmef_criterion_value_to_string(idmef_criterion_value_t *cv, prelude_string_t *out)
532 {
533         return cv->to_string(cv, out);
534 }
535 
536 
537 
idmef_criterion_value_match(idmef_criterion_value_t * cv,idmef_value_t * value,idmef_criterion_operator_t op)538 int idmef_criterion_value_match(idmef_criterion_value_t *cv, idmef_value_t *value,
539                                 idmef_criterion_operator_t op)
540 {
541         int ret;
542         struct match_cb mcb;
543 
544         mcb.cv = cv;
545         mcb.operator = op;
546         mcb.match = mcb.nmatch = 0;
547 
548         ret = idmef_value_iterate(value, do_match_cb, &mcb);
549         if ( ret < 0 )
550                 return ret;
551 
552         /*
553          * When comparing a path to a value using a negative operator, if the
554          * excluded value was found at least once, return a negative match.
555          *
556          * This is required since the 'match' value might also be positive
557          * in case the path contain a list of value.
558          */
559         if ( op & IDMEF_CRITERION_OPERATOR_NOT && mcb.nmatch > 0 )
560                 return 0;
561 
562         return mcb.match;
563 }
564 
565 
566 
idmef_criterion_value_new(idmef_criterion_value_t ** cv)567 int idmef_criterion_value_new(idmef_criterion_value_t **cv)
568 {
569         *cv = calloc(1, sizeof(**cv));
570         if ( ! *cv )
571                 return prelude_error_from_errno(errno);
572 
573         (*cv)->value_need_free = TRUE;
574 
575         return 0;
576 }
577 
578 
579 
btime_parse_gmtoff(const char * param,int * out)580 static int btime_parse_gmtoff(const char *param, int *out)
581 {
582         *out = atoi(param) * 60 * 60;
583         return 0;
584 }
585 
586 
btime_parse(struct tm * lt,const char * time)587 static int btime_parse(struct tm *lt, const char *time)
588 {
589         int ret;
590         size_t i;
591         long gmt_offset;
592         char *end = NULL;
593         struct {
594                 const char *field;
595                 size_t len;
596                 void *ptr;
597                 int (*func)(const char *param, int *output);
598         } tbl[] = {
599                 { "month", 5, &lt->tm_mon, btime_parse_month  },
600                 { "wday", 4, &lt->tm_wday, btime_parse_wday   },
601                 { "year", 4, &lt->tm_year, btime_parse_year   },
602                 { "mday", 4, &lt->tm_mday, btime_parse_simple },
603                 { "yday", 4, &lt->tm_yday, btime_parse_simple },
604                 { "hour", 4, &lt->tm_hour, btime_parse_simple },
605                 { "min", 3, &lt->tm_min, btime_parse_simple   },
606                 { "sec", 3, &lt->tm_sec, btime_parse_simple   },
607                 { "gmtoff", 6, &gmt_offset, btime_parse_gmtoff }
608         };
609 
610         ret = prelude_get_gmt_offset(&gmt_offset);
611         if ( ret < 0 )
612                 return ret;
613 
614         do {
615                 for ( i = 0; i < sizeof(tbl) / sizeof(*tbl); i++ ) {
616 
617                         if ( strncmp(time, tbl[i].field, tbl[i].len) != 0 )
618                                 continue;
619 
620                         if ( time[tbl[i].len] != ':' )
621                                 continue;
622 
623                         time += tbl[i].len + 1;
624 
625                         end = strchr(time, ' ');
626                         if ( end ) {
627                                 *end++ = 0;
628                                 while ( *end == ' ' ) end++;
629                         }
630 
631                         ret = tbl[i].func(time, tbl[i].ptr);
632                         if ( ret < 0 )
633                                 return -1;
634 
635                         time = end + 1;
636                         break;
637                 }
638 
639                 if ( i == sizeof(tbl) / sizeof(*tbl) )
640                         return -1;
641 
642                 time = end;
643         } while ( time );
644 
645         if ( lt->tm_hour != -1 )
646                 lt->tm_hour -= (gmt_offset / (60 * 60));
647 
648         return 0;
649 }
650 
651 
652 
653 
idmef_criterion_value_new_broken_down_time(idmef_criterion_value_t ** cv,const char * time,idmef_criterion_operator_t op)654 int idmef_criterion_value_new_broken_down_time(idmef_criterion_value_t **cv, const char *time, idmef_criterion_operator_t op)
655 {
656         int ret;
657         struct tm *lt;
658 
659         ret = idmef_criterion_value_new(cv);
660         if ( ret < 0 )
661                 return ret;
662 
663         lt = malloc(sizeof(struct tm));
664         if ( ! lt ) {
665                 free(*cv);
666                 return prelude_error_from_errno(errno);
667         }
668 
669         memset(lt, -1, sizeof(*lt));
670 
671         ret = btime_parse(lt, time);
672         if ( ret < 0 ) {
673                 free(lt);
674                 free(*cv);
675                 return ret;
676         }
677 
678         (*cv)->value = lt;
679         (*cv)->match = btime_match;
680         (*cv)->clone = btime_clone;
681         (*cv)->print = btime_print;
682         (*cv)->destroy = btime_destroy;
683         (*cv)->to_string = btime_to_string;
684         (*cv)->type = IDMEF_CRITERION_VALUE_TYPE_BROKEN_DOWN_TIME;
685 
686         return 0;
687 }
688 
689 
690 
691 
idmef_criterion_value_new_regex(idmef_criterion_value_t ** cv,const char * regex,idmef_criterion_operator_t op)692 int idmef_criterion_value_new_regex(idmef_criterion_value_t **cv, const char *regex, idmef_criterion_operator_t op)
693 {
694         int ret;
695         struct regex_value *rv;
696         int flags = REG_EXTENDED|REG_NOSUB;
697 
698         ret = idmef_criterion_value_new(cv);
699         if ( ret < 0 )
700                 return ret;
701 
702         rv = (*cv)->value = malloc(sizeof(*rv));
703         if ( ! rv ) {
704                 free(*cv);
705                 return prelude_error_from_errno(errno);
706         }
707 
708         rv->regex_string = strdup(regex);
709         if ( ! rv->regex_string ) {
710                 free(rv);
711                 free(*cv);
712                 return prelude_error_from_errno(errno);
713         }
714 
715         if ( op & IDMEF_CRITERION_OPERATOR_NOCASE )
716                 flags |= REG_ICASE;
717 
718         ret = regcomp(&rv->regex, rv->regex_string, flags);
719         if ( ret != 0 ) {
720                 char errbuf[1024];
721 
722                 regerror(ret, &rv->regex, errbuf, sizeof(errbuf));
723 
724                 free(rv->regex_string);
725                 free(rv);
726                 free(*cv);
727 
728                 return prelude_error_verbose(PRELUDE_ERROR_IDMEF_CRITERION_INVALID_REGEX,
729                                              "error compiling regex: %s", errbuf);
730         }
731 
732         (*cv)->match = regex_match;
733         (*cv)->clone = regex_clone;
734         (*cv)->print = regex_print;
735         (*cv)->destroy = regex_destroy;
736         (*cv)->to_string = regex_to_string;
737         (*cv)->type = IDMEF_CRITERION_VALUE_TYPE_REGEX;
738 
739         return 0;
740 }
741 
742 
743 
idmef_criterion_value_new_value(idmef_criterion_value_t ** cv,idmef_value_t * value,idmef_criterion_operator_t op)744 int idmef_criterion_value_new_value(idmef_criterion_value_t **cv,
745                                     idmef_value_t *value, idmef_criterion_operator_t op)
746 {
747         int ret;
748 
749         ret = idmef_value_check_operator(value, op);
750         if ( ret < 0 )
751                 return ret;
752 
753         ret = idmef_criterion_value_new(cv);
754         if ( ret < 0 )
755                 return ret;
756 
757         (*cv)->value = value;
758         (*cv)->match = value_match;
759         (*cv)->clone = value_clone;
760         (*cv)->print = value_print;
761         (*cv)->destroy = value_destroy;
762         (*cv)->to_string = value_to_string;
763         (*cv)->type = IDMEF_CRITERION_VALUE_TYPE_VALUE;
764 
765         return 0;
766 }
767 
768 
769 
770 
idmef_criterion_value_new_from_string(idmef_criterion_value_t ** cv,idmef_path_t * path,const char * value,idmef_criterion_operator_t operator)771 int idmef_criterion_value_new_from_string(idmef_criterion_value_t **cv,
772                                           idmef_path_t *path, const char *value,
773                                           idmef_criterion_operator_t operator)
774 {
775         int ret;
776         idmef_value_t *val;
777         idmef_value_type_id_t tid;
778 
779         tid = idmef_path_get_value_type(path, -1);
780 
781         if ( tid == IDMEF_VALUE_TYPE_TIME ) {
782                 ret = idmef_criterion_value_new_broken_down_time(cv, value, operator);
783                 if ( ret == 0 )
784                         return ret;
785         }
786 
787         else if ( operator & IDMEF_CRITERION_OPERATOR_REGEX &&
788                   (tid == IDMEF_VALUE_TYPE_STRING || tid == IDMEF_VALUE_TYPE_ENUM || tid == IDMEF_VALUE_TYPE_DATA) )
789                 return idmef_criterion_value_new_regex(cv, value, operator);
790 
791         /*
792          * It's more understandable for the user if we check the operator
793          * prior to checking the value.
794          */
795         ret = idmef_value_type_check_operator(tid, operator);
796         if ( ret < 0 )
797                 return ret;
798 
799         if ( tid == IDMEF_VALUE_TYPE_ENUM && operator & IDMEF_CRITERION_OPERATOR_SUBSTR )
800                 ret = idmef_value_new_from_string(&val, IDMEF_VALUE_TYPE_STRING, value);
801         else
802                 ret = idmef_value_new_from_path(&val, path, value);
803 
804         if ( ret < 0 )
805                 return ret;
806 
807         ret = idmef_criterion_value_new_value(cv, val, operator);
808         if ( ret < 0 ) {
809                 idmef_value_destroy(val);
810                 return ret;
811         }
812 
813         return 0;
814 }
815 
816 
817 
idmef_criterion_value_get_value(idmef_criterion_value_t * cv)818 const idmef_value_t *idmef_criterion_value_get_value(idmef_criterion_value_t *cv)
819 {
820         return cv->type == IDMEF_CRITERION_VALUE_TYPE_VALUE ? cv->value : NULL;
821 }
822 
823 
824 
idmef_criterion_value_get_broken_down_time(idmef_criterion_value_t * cv)825 const struct tm *idmef_criterion_value_get_broken_down_time(idmef_criterion_value_t *cv)
826 {
827         return cv->type == IDMEF_CRITERION_VALUE_TYPE_BROKEN_DOWN_TIME ? cv->value : NULL;
828 }
829 
830 
831 
idmef_criterion_value_get_regex(idmef_criterion_value_t * cv)832 const char *idmef_criterion_value_get_regex(idmef_criterion_value_t *cv)
833 {
834         return cv->type == IDMEF_CRITERION_VALUE_TYPE_REGEX ? ((struct regex_value *)cv->value)->regex_string : NULL;
835 }
836 
837 
idmef_criterion_value_get_type(idmef_criterion_value_t * cv)838 idmef_criterion_value_type_t idmef_criterion_value_get_type(idmef_criterion_value_t *cv)
839 {
840         return cv->type;
841 }
842