1 /*
2 ** Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 ** Copyright (C) 2002-2013 Sourcefire, Inc.
4 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License Version 2 as
8 ** published by the Free Software Foundation. You may not use, modify or
9 ** distribute this program under any other version of the GNU General
10 ** Public License.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 /* $Id$ */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <sys/types.h>
29 #include <stdlib.h>
30 #include <ctype.h>
31
32 #include "sf_types.h"
33 #include "rules.h"
34 #include "treenodes.h"
35 #include "decode.h"
36 #include "parser.h"
37 #include "plugbase.h"
38 #include "snort_debug.h"
39 #include "plugin_enum.h"
40 #include "util.h"
41
42 #include "snort.h"
43 #include "profiler.h"
44 #ifdef PERF_PROFILING
45 PreprocStats ipIdPerfStats;
46 extern PreprocStats ruleOTNEvalPerfStats;
47 #endif
48
49 #include "sfhashfcn.h"
50 #include "detection_options.h"
51
52 typedef struct _IpIdCheckData
53 {
54 u_long ip_id;
55
56 } IpIdCheckData;
57
58 void IpIdCheckInit(struct _SnortConfig *, char *, OptTreeNode *, int);
59 void ParseIpId(struct _SnortConfig *, char *, OptTreeNode *);
60 int IpIdCheckEq(void *option_data, Packet *p);
61
IpIdCheckHash(void * d)62 uint32_t IpIdCheckHash(void *d)
63 {
64 uint32_t a,b,c;
65 IpIdCheckData *data = (IpIdCheckData *)d;
66
67 a = data->ip_id;
68 b = RULE_OPTION_TYPE_IP_ID;
69 c = 0;
70
71 final(a,b,c);
72
73 return c;
74 }
75
IpIdCheckCompare(void * l,void * r)76 int IpIdCheckCompare(void *l, void *r)
77 {
78 IpIdCheckData *left = (IpIdCheckData *)l;
79 IpIdCheckData *right = (IpIdCheckData *)r;
80
81 if (!left || !right)
82 return DETECTION_OPTION_NOT_EQUAL;
83
84 if (left->ip_id == right->ip_id)
85 {
86 return DETECTION_OPTION_EQUAL;
87 }
88
89 return DETECTION_OPTION_NOT_EQUAL;
90 }
91
92 /****************************************************************************
93 *
94 * Function: SetupIpIdCheck()
95 *
96 * Purpose: Associate the id keyword with IpIdCheckInit
97 *
98 * Arguments: None.
99 *
100 * Returns: void function
101 *
102 ****************************************************************************/
SetupIpIdCheck(void)103 void SetupIpIdCheck(void)
104 {
105 /* map the keyword to an initialization/processing function */
106 RegisterRuleOption("id", IpIdCheckInit, NULL, OPT_TYPE_DETECTION, NULL);
107 #ifdef PERF_PROFILING
108 RegisterPreprocessorProfile("id", &ipIdPerfStats, 3, &ruleOTNEvalPerfStats, NULL);
109 #endif
110
111 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: IpIdCheck Initialized\n"););
112 }
113
114
115 /****************************************************************************
116 *
117 * Function: IpIdCheckInit(struct _SnortConfig *, char *, OptTreeNode *)
118 *
119 * Purpose: Setup the id data struct and link the function into option
120 * function pointer list
121 *
122 * Arguments: data => rule arguments/data
123 * otn => pointer to the current rule option list node
124 *
125 * Returns: void function
126 *
127 ****************************************************************************/
IpIdCheckInit(struct _SnortConfig * sc,char * data,OptTreeNode * otn,int protocol)128 void IpIdCheckInit(struct _SnortConfig *sc, char *data, OptTreeNode *otn, int protocol)
129 {
130 OptFpList *fpl;
131 /* multiple declaration check */
132 if(otn->ds_list[PLUGIN_IP_ID_CHECK])
133 {
134 FatalError("%s(%d): Multiple IP id options in rule\n", file_name,
135 file_line);
136 }
137
138 /* allocate the data structure and attach it to the
139 rule's data struct list */
140 otn->ds_list[PLUGIN_IP_ID_CHECK] = (IpIdCheckData *)
141 SnortAlloc(sizeof(IpIdCheckData));
142
143 /* this is where the keyword arguments are processed and placed into the
144 rule option's data structure */
145 ParseIpId(sc, data, otn);
146
147 /* finally, attach the option's detection function to the rule's
148 detect function pointer list */
149 fpl = AddOptFuncToList(IpIdCheckEq, otn);
150 fpl->type = RULE_OPTION_TYPE_IP_ID;
151 fpl->context = otn->ds_list[PLUGIN_IP_ID_CHECK];
152 }
153
154
155
156 /****************************************************************************
157 *
158 * Function: ParseIpId(struct _SnortConfig *, char *, OptTreeNode *)
159 *
160 * Purpose: Convert the id option argument to data and plug it into the
161 * data structure
162 *
163 * Arguments: data => argument data
164 * otn => pointer to the current rule's OTN
165 *
166 * Returns: void function
167 *
168 ****************************************************************************/
ParseIpId(struct _SnortConfig * sc,char * data,OptTreeNode * otn)169 void ParseIpId(struct _SnortConfig *sc, char *data, OptTreeNode *otn)
170 {
171 IpIdCheckData *ds_ptr; /* data struct pointer */
172 void *ds_ptr_dup;
173 int ip_id;
174 char *endTok;
175
176 /* set the ds pointer to make it easier to reference the option's
177 particular data struct */
178 ds_ptr = otn->ds_list[PLUGIN_IP_ID_CHECK];
179
180 /* get rid of any whitespace */
181 while(isspace((int)*data))
182 {
183 data++;
184 }
185
186 ip_id = SnortStrtolRange(data, &endTok, 10, 0, UINT16_MAX);
187 if ((endTok == data) || (*endTok != '\0'))
188 {
189 FatalError("%s(%d) => Invalid parameter '%s' to id (not a "
190 "number?) \n", file_name, file_line, data);
191 }
192 ds_ptr->ip_id = htons( (u_short) ip_id);
193
194 if (add_detection_option(sc, RULE_OPTION_TYPE_IP_ID, (void *)ds_ptr, &ds_ptr_dup) == DETECTION_OPTION_EQUAL)
195 {
196 free(ds_ptr);
197 ds_ptr = otn->ds_list[PLUGIN_IP_ID_CHECK] = ds_ptr_dup;
198 }
199
200 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"ID set to %ld\n", ds_ptr->ip_id););
201 }
202
203
204 /****************************************************************************
205 *
206 * Function: IpIdCheckEq(char *, OptTreeNode *)
207 *
208 * Purpose: Test the ip header's id field to see if its value is equal to the
209 * value in the rule. This is useful to detect things like "elite"
210 * numbers, oddly repeating numbers, etc.
211 *
212 * Arguments: data => argument data
213 * otn => pointer to the current rule's OTN
214 *
215 * Returns: void function
216 *
217 ****************************************************************************/
IpIdCheckEq(void * option_data,Packet * p)218 int IpIdCheckEq(void *option_data, Packet *p)
219 {
220 IpIdCheckData *ipIdCheckData = (IpIdCheckData *)option_data;
221 int rval = DETECTION_OPTION_NO_MATCH;
222 PROFILE_VARS;
223
224 if(!IPH_IS_VALID(p))
225 return rval; /* if error occured while ip header
226 * was processed, return 0 automagically. */
227
228 PREPROC_PROFILE_START(ipIdPerfStats);
229
230 if(ipIdCheckData->ip_id == GET_IPH_ID(p))
231 {
232 /* call the next function in the function list recursively */
233 rval = DETECTION_OPTION_MATCH;
234 }
235 else
236 {
237 /* you can put debug comments here or not */
238 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "No match for sp_ip_id_check\n"););
239 }
240
241 /* if the test isn't successful, return 0 */
242 PREPROC_PROFILE_END(ipIdPerfStats);
243 return rval;
244 }
245