new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / analysisd / decoders / decoders_list.c
1 /* Copyright (C) 2009 Trend Micro Inc.
2  * All rights 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 <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "headers/debug_op.h"
15 #include "decoder.h"
16 #include "error_messages/error_messages.h"
17
18 /* We have two internal lists. One with the program_name
19  * and one without. This is going to improve greatly the
20  * performance of our decoder matching.
21  */
22 static OSDecoderNode *osdecodernode_forpname;
23 static OSDecoderNode *osdecodernode_nopname;
24
25 static OSDecoderNode *_OS_AddOSDecoder(OSDecoderNode *s_node, OSDecoderInfo *pi);
26
27 /* Create the Event List */
28 void OS_CreateOSDecoderList()
29 {
30     osdecodernode_forpname = NULL;
31     osdecodernode_nopname = NULL;
32
33     return;
34 }
35
36 /* Get first osdecoder */
37 OSDecoderNode *OS_GetFirstOSDecoder(const char *p_name)
38 {
39     /* If program name is set, we return the forpname list */
40     if (p_name) {
41         return (osdecodernode_forpname);
42     }
43
44     return (osdecodernode_nopname);
45 }
46
47 /* Add an osdecoder to the list */
48 static OSDecoderNode *_OS_AddOSDecoder(OSDecoderNode *s_node, OSDecoderInfo *pi)
49 {
50     OSDecoderNode *tmp_node = s_node;
51     OSDecoderNode *new_node;
52     int rm_f = 0;
53
54     if (tmp_node) {
55         new_node = (OSDecoderNode *)calloc(1, sizeof(OSDecoderNode));
56         if (new_node == NULL) {
57             merror(MEM_ERROR, ARGV0, errno, strerror(errno));
58             return (NULL);
59         }
60
61         /* Going to the last node */
62         do {
63             /* Check for common names */
64             if ((strcmp(tmp_node->osdecoder->name, pi->name) == 0) &&
65                     (pi->parent != NULL)) {
66                 if ((tmp_node->osdecoder->prematch ||
67                         tmp_node->osdecoder->regex ||
68                         tmp_node->osdecoder->prematch_pcre2 ||
69                         tmp_node->osdecoder->pcre2) && pi->regex_offset) {
70                     rm_f = 1;
71                 }
72
73                 /* Multi-regexes patterns cannot have prematch */
74                 if (pi->prematch || pi->prematch_pcre2) {
75                     merror(PDUP_INV, ARGV0, pi->name);
76                     goto error;
77                 }
78
79                 /* Multi-regex patterns cannot have fts set */
80                 if (pi->fts) {
81                     merror(PDUPFTS_INV, ARGV0, pi->name);
82                     goto error;
83                 }
84
85                 if (tmp_node->osdecoder->regex && pi->regex) {
86                     tmp_node->osdecoder->get_next = 1;
87                 } else if (tmp_node->osdecoder->pcre2 && pi->pcre2) {
88                     tmp_node->osdecoder->get_next = 1;
89                 } else {
90                     merror(DUP_INV, ARGV0, pi->name);
91                     goto error;
92                 }
93             }
94
95         } while (tmp_node->next && (tmp_node = tmp_node->next));
96
97         /* Must have a prematch set */
98         if (!rm_f && (pi->regex_offset & AFTER_PREVREGEX)) {
99             merror(INV_OFFSET, ARGV0, pi->name);
100             goto error;
101         }
102
103         tmp_node->next = new_node;
104
105         new_node->next = NULL;
106         new_node->osdecoder = pi;
107         new_node->child = NULL;
108     }
109
110     else {
111         /* Must not have a previous regex set */
112         if (pi->regex_offset & AFTER_PREVREGEX) {
113             merror(INV_OFFSET, ARGV0, pi->name);
114             return (NULL);
115         }
116
117         tmp_node = (OSDecoderNode *)calloc(1, sizeof(OSDecoderNode));
118
119         if (tmp_node == NULL) {
120             ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
121         }
122
123         tmp_node->child = NULL;
124         tmp_node->next = NULL;
125         tmp_node->osdecoder = pi;
126
127         s_node = tmp_node;
128     }
129
130     return (s_node);
131
132 error:
133     if (new_node) {
134         free(new_node);
135     }
136     return (NULL);
137 }
138
139 int OS_AddOSDecoder(OSDecoderInfo *pi)
140 {
141     int added = 0;
142     OSDecoderNode *osdecodernode;
143
144     /* We can actually have two lists. One with program
145      * name and the other without.
146      */
147     if (pi->program_name || pi->program_name_pcre2) {
148         osdecodernode = osdecodernode_forpname;
149     } else {
150         osdecodernode = osdecodernode_nopname;
151     }
152
153     /* Search for parent on both lists */
154     if (pi->parent) {
155         OSDecoderNode *tmp_node = osdecodernode_forpname;
156
157         /* List with p_name */
158         while (tmp_node) {
159             if (strcmp(tmp_node->osdecoder->name, pi->parent) == 0) {
160                 tmp_node->child = _OS_AddOSDecoder(tmp_node->child, pi);
161                 if (!tmp_node->child) {
162                     merror(DEC_PLUGIN_ERR, ARGV0);
163                     return (0);
164                 }
165                 added = 1;
166             }
167             tmp_node = tmp_node->next;
168         }
169
170         /* List without p name */
171         tmp_node = osdecodernode_nopname;
172         while (tmp_node) {
173             if (strcmp(tmp_node->osdecoder->name, pi->parent) == 0) {
174                 tmp_node->child = _OS_AddOSDecoder(tmp_node->child, pi);
175                 if (!tmp_node->child) {
176                     merror(DEC_PLUGIN_ERR, ARGV0);
177                     return (0);
178                 }
179                 added = 1;
180             }
181             tmp_node = tmp_node->next;
182         }
183
184         /* OSDecoder was added correctly */
185         if (added == 1) {
186             return (1);
187         }
188
189         merror(PPLUGIN_INV, ARGV0, pi->parent);
190         return (0);
191     } else {
192         osdecodernode = _OS_AddOSDecoder(osdecodernode, pi);
193         if (!osdecodernode) {
194             merror(DEC_PLUGIN_ERR, ARGV0);
195             return (0);
196         }
197
198         /* Update global decoder pointers */
199         if (pi->program_name || pi->program_name_pcre2) {
200             osdecodernode_forpname = osdecodernode;
201         } else {
202             osdecodernode_nopname = osdecodernode;
203         }
204     }
205     return (1);
206 }
207