1 /****************************************************************************
2 * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 * Copyright (C) 2008-2013 Sourcefire, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License Version 2 as
7 * published by the Free Software Foundation. You may not use, modify or
8 * distribute this program under any other version of the GNU General
9 * Public License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 ****************************************************************************
21 *
22 ****************************************************************************/
23
24 #include <errno.h>
25 #include <string.h>
26 #include <stdarg.h>
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "sf_types.h"
33 #include "dce2_roptions.h"
34 #include "dce2_memory.h"
35 #include "dcerpc.h"
36 #include "dce2_utils.h"
37 #include "dce2_session.h"
38 #include "sf_types.h"
39 #include "sf_dynamic_preprocessor.h"
40 #include "stream_api.h"
41 #include "sf_dynamic_engine.h"
42 #include "sf_snort_plugin_api.h"
43 #include "sfhashfcn.h"
44 #include "profiler.h"
45
46 /********************************************************************
47 * Macros
48 ********************************************************************/
49 #define DCE2_RTOKEN__OPT_SEP "," /* Rule option option separator */
50 #define DCE2_RTOKEN__ARG_SEP " \t" /* Rule option argument separator */
51 #define DCE2_RTOKEN__IFACE_SEP "-" /* Rule option interface separator */
52
53 #define DCE2_ROPT__IFACE "dce_iface"
54 #define DCE2_ROPT__OPNUM "dce_opnum"
55 #define DCE2_ROPT__STUB_DATA "dce_stub_data"
56 #define DCE2_ROPT__BYTE_TEST "byte_test" /* Override keyword */
57 #define DCE2_ROPT__BYTE_JUMP "byte_jump" /* Override keyword */
58 #define DCE2_ROPT__BYTE_EXTRACT "byte_extract" /* Override keyword */
59
60 #define DCE2_RARG__LT '<'
61 #define DCE2_RARG__EQ '='
62 #define DCE2_RARG__GT '>'
63 #define DCE2_RARG__NE '!'
64 #define DCE2_RARG__AND '&'
65 #define DCE2_RARG__XOR '^'
66 #define DCE2_RARG__ANY_FRAG "any_frag"
67 #define DCE2_RARG__RELATIVE "relative"
68 #define DCE2_RARG__MULTIPLIER "multiplier"
69 #define DCE2_RARG__ALIGN "align"
70 #define DCE2_RARG__POST_OFFSET "post_offset"
71 #define DCE2_RARG__DCE_OVERRIDE "dce"
72 #define DCE2_RARG__DCE_BYTEORDER "dce"
73
74 #define DCE2_IFACE__MIN_ARGS 1
75 #define DCE2_IFACE__MAX_ARGS 3
76 #define DCE2_IFACE__LEN 36 /* counting the dashes */
77 #define DCE2_IFACE__TIME_LOW_LEN 8
78 #define DCE2_IFACE__TIME_MID_LEN 4
79 #define DCE2_IFACE__TIME_HIGH_LEN 4
80 #define DCE2_IFACE__CLOCK_SEQ_LEN 4
81 #define DCE2_IFACE__NODE_LEN 12
82
83 #define DCE2_BTEST__MIN_ARGS 4
84 #define DCE2_BTEST__MAX_ARGS 6
85
86 #define DCE2_BJUMP__MIN_ARGS 2
87 #define DCE2_BJUMP__MAX_ARGS 7
88
89 #define DCE2_OPNUM__MAX (UINT16_MAX + 1)
90 #define DCE2_OPNUM__MAX_INDEX (DCE2_OPNUM__MAX / 8)
91
92 /********************************************************************
93 * Enumerations
94 ********************************************************************/
95 typedef enum _DCE2_IfOp
96 {
97 DCE2_IF_OP__NONE = 0,
98 DCE2_IF_OP__LT,
99 DCE2_IF_OP__EQ,
100 DCE2_IF_OP__GT,
101 DCE2_IF_OP__NE
102
103 } DCE2_IfOp;
104
105 typedef enum _DCE2_BtOp
106 {
107 DCE2_BT_OP__NONE = 0,
108 DCE2_BT_OP__LT,
109 DCE2_BT_OP__EQ,
110 DCE2_BT_OP__GT,
111 DCE2_BT_OP__AND,
112 DCE2_BT_OP__XOR
113
114 } DCE2_BtOp;
115
116 typedef enum _DCE2_OpnumType
117 {
118 DCE2_OPNUM_TYPE__SINGLE,
119 DCE2_OPNUM_TYPE__MULTIPLE
120
121 } DCE2_OpnumType;
122
123 typedef enum _DCE2_OpnumListState
124 {
125 DCE2_OPNUM_LIST_STATE__START,
126 DCE2_OPNUM_LIST_STATE__OPNUM_START,
127 DCE2_OPNUM_LIST_STATE__OPNUM_LO,
128 DCE2_OPNUM_LIST_STATE__OPNUM_RANGE,
129 DCE2_OPNUM_LIST_STATE__OPNUM_HI,
130 DCE2_OPNUM_LIST_STATE__OPNUM_END,
131 DCE2_OPNUM_LIST_STATE__END
132
133 } DCE2_OpnumListState;
134
135 /********************************************************************
136 * Structures
137 ********************************************************************/
138 typedef struct _DCE2_IfaceData
139 {
140 Uuid iface;
141 uint32_t iface_vers;
142 int iface_vers_maj;
143 int iface_vers_min;
144 DCE2_IfOp operator;
145 int any_frag;
146
147 } DCE2_IfaceData;
148
149 typedef struct _DCE_OpnumData
150 {
151 DCE2_OpnumType type;
152
153 } DCE2_OpnumData;
154
155 typedef struct _DCE_OpnumSingle
156 {
157 DCE2_OpnumData odata;
158 uint16_t opnum;
159
160 } DCE2_OpnumSingle;
161
162 typedef struct _DCE2_OpnumMultiple
163 {
164 DCE2_OpnumData odata;
165 uint8_t *mask;
166 uint16_t mask_size;
167 uint16_t opnum_lo;
168 uint16_t opnum_hi;
169
170 } DCE2_OpnumMultiple;
171
172 typedef struct _DCE2_ByteTestData
173 {
174 int num_bytes;
175 uint32_t value;
176 int invert;
177 DCE2_BtOp operator;
178 int32_t offset; /* can be negative */
179 int relative;
180
181 } DCE2_ByteTestData;
182
183 typedef struct _DCE2_ByteJumpData
184 {
185 int num_bytes;
186 int32_t offset; /* can be negative */
187 int relative;
188 int multiplier;
189 int align;
190 int32_t post_offset; /* can be negative */
191
192 } DCE2_ByteJumpData;
193
194 /********************************************************************
195 * Private function prototypes
196 ********************************************************************/
197 static int DCE2_IfaceInit(struct _SnortConfig *, char *, char *, void **);
198 static int DCE2_OpnumInit(struct _SnortConfig *, char *, char *, void **);
199 static void DCE2_ParseOpnumList(char **, char *, uint8_t *);
200 static inline void DCE2_OpnumSet(uint8_t *, const uint16_t);
201 static inline void DCE2_OpnumSetRange(uint8_t *, uint16_t, uint16_t);
202 static inline int DCE2_OpnumIsSet(const uint8_t *, const uint16_t, const uint16_t, const uint16_t);
203 static int DCE2_StubDataInit(struct _SnortConfig *, char *, char *, void **);
204 static int DCE2_ByteTestInit(struct _SnortConfig *, char *, char *, void **);
205 static int DCE2_ByteJumpInit(struct _SnortConfig *, char *, char *, void **);
206 static void DCE2_ParseIface(char *, DCE2_IfaceData *);
207 static int DCE2_IfaceEval(void *, const uint8_t **, void *);
208 static int DCE2_OpnumEval(void *, const uint8_t **, void *);
209 static int DCE2_StubDataEval(void *, const uint8_t **, void *);
210 static int DCE2_ByteTestEval(void *, const uint8_t **, void *);
211 static int DCE2_ByteJumpEval(void *, const uint8_t **, void *);
212 static void DCE2_IfaceCleanup(void *);
213 static void DCE2_OpnumCleanup(void *);
214 static void DCE2_ByteTestCleanup(void *);
215 static void DCE2_ByteJumpCleanup(void *);
216 static uint32_t DCE2_IfaceHash(void *);
217 static uint32_t DCE2_OpnumHash(void *);
218 static uint32_t DCE2_ByteTestHash(void *);
219 static uint32_t DCE2_ByteJumpHash(void *);
220 static int DCE2_IfaceKeyCompare(void *, void *);
221 static int DCE2_OpnumKeyCompare(void *, void *);
222 static int DCE2_ByteTestKeyCompare(void *, void *);
223 static int DCE2_ByteJumpKeyCompare(void *, void *);
224 static inline int DCE2_RoptDoEval(SFSnortPacket *);
225 static NORETURN void DCE2_RoptError(const char *, ...);
226 static inline void * DCE2_AllocFp(uint32_t);
227 static int DCE2_IfaceAddFastPatterns(void *, int, int, FPContentInfo **);
228
229 /********************************************************************
230 * Function:
231 *
232 * Purpose:
233 *
234 * Arguments:
235 *
236 * Returns:
237 *
238 ********************************************************************/
DCE2_RegRuleOptions(struct _SnortConfig * sc)239 void DCE2_RegRuleOptions(struct _SnortConfig *sc)
240 {
241 _dpd.preprocOptRegister(sc, DCE2_ROPT__IFACE, DCE2_IfaceInit, DCE2_IfaceEval,
242 DCE2_IfaceCleanup, DCE2_IfaceHash, DCE2_IfaceKeyCompare,
243 NULL, DCE2_IfaceAddFastPatterns);
244 _dpd.preprocOptRegister(sc, DCE2_ROPT__OPNUM, DCE2_OpnumInit, DCE2_OpnumEval,
245 DCE2_OpnumCleanup, DCE2_OpnumHash, DCE2_OpnumKeyCompare, NULL, NULL);
246 _dpd.preprocOptRegister(sc, DCE2_ROPT__STUB_DATA, DCE2_StubDataInit,
247 DCE2_StubDataEval, NULL, NULL, NULL, NULL, NULL);
248 _dpd.preprocOptOverrideKeyword(sc, DCE2_ROPT__BYTE_TEST, DCE2_RARG__DCE_OVERRIDE,
249 DCE2_ByteTestInit, DCE2_ByteTestEval, DCE2_ByteTestCleanup,
250 DCE2_ByteTestHash, DCE2_ByteTestKeyCompare, NULL, NULL);
251 _dpd.preprocOptOverrideKeyword(sc, DCE2_ROPT__BYTE_JUMP, DCE2_RARG__DCE_OVERRIDE,
252 DCE2_ByteJumpInit, DCE2_ByteJumpEval, DCE2_ByteJumpCleanup,
253 DCE2_ByteJumpHash, DCE2_ByteJumpKeyCompare, NULL, NULL);
254 _dpd.preprocOptByteOrderKeyword(DCE2_RARG__DCE_BYTEORDER, DCE2_GetByteOrder);
255 }
256
257 /********************************************************************
258 * Function: DCE2_IfaceInit()
259 *
260 * Parses dce_iface rule option.
261 *
262 * XXX Connectionless uses a 32bit version, connection-oriented
263 * a 16bit major version and 16bit minor version. Not likely to
264 * need to support versions greater than 65535, but may need to
265 * support minor version.
266 *
267 * Arguments:
268 * char *
269 * Name of rule option.
270 * char *
271 * Arguments for rule option.
272 * data **
273 * Variable for saving rule option structure.
274 *
275 * Returns:
276 * 1 if successful
277 * 0 if name is not dce_iface
278 * Fatal errors if invalid arguments.
279 *
280 ********************************************************************/
DCE2_IfaceInit(struct _SnortConfig * sc,char * name,char * args,void ** data)281 static int DCE2_IfaceInit(struct _SnortConfig *sc, char *name, char *args, void **data)
282 {
283 char *token, *saveptr = NULL;
284 int iface_vers = 0, any_frag = 0;
285 int tok_num = 0;
286 DCE2_IfaceData *iface_data;
287
288 if (strcasecmp(name, DCE2_ROPT__IFACE) != 0)
289 return 0;
290
291 iface_data = (DCE2_IfaceData *)DCE2_Alloc(sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
292 if (iface_data == NULL)
293 {
294 DCE2_Die("%s(%d) Failed to allocate memory for iface data structure.",
295 __FILE__, __LINE__);
296 }
297
298 iface_data->operator = DCE2_IF_OP__NONE;
299
300 /* Must have arguments */
301 if (DCE2_IsEmptyStr(args))
302 {
303 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
304 DCE2_RoptError("\"%s\" rule option requires arguments.", DCE2_ROPT__IFACE);
305 }
306
307 /* Get argument */
308 token = strtok_r(args, DCE2_RTOKEN__OPT_SEP, &saveptr);
309 if (token == NULL)
310 {
311 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
312 DCE2_Die("%s(%d) strtok_r() returned NULL when string argument "
313 "was not NULL.", __FILE__, __LINE__);
314 }
315
316 do
317 {
318 tok_num++;
319
320 token = DCE2_PruneWhiteSpace(token);
321
322 if (tok_num == 1) /* Iface uuid */
323 {
324 DCE2_ParseIface(token, iface_data);
325 }
326 else if ((tok_num > DCE2_IFACE__MIN_ARGS) && (tok_num <= DCE2_IFACE__MAX_ARGS))
327 {
328 int try_any_frag = 0;
329
330 /* Need at least two bytes */
331 if (strlen(token) < 2)
332 {
333 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
334 DCE2_RoptError("\"%s\" rule option: Invalid argument: %s.",
335 DCE2_ROPT__IFACE, token);
336 }
337
338 switch (*token)
339 {
340 case DCE2_RARG__LT:
341 iface_data->operator = DCE2_IF_OP__LT;
342 break;
343 case DCE2_RARG__EQ:
344 iface_data->operator = DCE2_IF_OP__EQ;
345 break;
346 case DCE2_RARG__GT:
347 iface_data->operator = DCE2_IF_OP__GT;
348 break;
349 case DCE2_RARG__NE:
350 iface_data->operator = DCE2_IF_OP__NE;
351 break;
352 default:
353 try_any_frag = 1;
354 }
355
356 if (!try_any_frag)
357 {
358 char *endptr;
359
360 if (iface_vers)
361 {
362 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
363 DCE2_RoptError("\"%s\" rule option: Cannot configure interface "
364 "version more than once.", DCE2_ROPT__IFACE);
365 }
366
367 token++;
368 iface_data->iface_vers = _dpd.SnortStrtoul(token, &endptr, 10);
369 if ((errno == ERANGE) || (*endptr != '\0'))
370 {
371 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
372 DCE2_RoptError("\"%s\" rule option: Invalid argument: %s.",
373 DCE2_ROPT__IFACE, token);
374 }
375
376 switch (iface_data->operator)
377 {
378 case DCE2_IF_OP__LT:
379 if (iface_data->iface_vers == 0)
380 {
381 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
382 DCE2_RoptError("\"%s\" rule option: Interface version "
383 "cannot be less than zero.", DCE2_ROPT__IFACE);
384 }
385 else if (iface_data->iface_vers > (UINT16_MAX + 1))
386 {
387 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
388 DCE2_RoptError("\"%s\" rule option: Interface version "
389 "cannot be greater than %u.",
390 DCE2_ROPT__IFACE, UINT16_MAX);
391 }
392
393 break;
394
395 case DCE2_IF_OP__EQ:
396 case DCE2_IF_OP__NE:
397 if (iface_data->iface_vers > UINT16_MAX)
398 {
399 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
400 DCE2_RoptError("\"%s\" rule option: Interface version "
401 "cannot be greater than %u.",
402 DCE2_ROPT__IFACE, UINT16_MAX);
403 }
404
405 break;
406
407 case DCE2_IF_OP__GT:
408 if (iface_data->iface_vers >= UINT16_MAX)
409 {
410 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
411 DCE2_RoptError("\"%s\" rule option: Interface version "
412 "cannot be greater than %u.",
413 DCE2_ROPT__IFACE, UINT16_MAX);
414 }
415
416 break;
417
418 default:
419 /* Shouldn't get here */
420 DCE2_Die("%s(%d) Invalid operator: %d",
421 __FILE__, __LINE__, iface_data->operator);
422 break;
423 }
424
425 if (iface_data->iface_vers <= UINT16_MAX)
426 iface_data->iface_vers_maj = (int)iface_data->iface_vers;
427 else
428 iface_data->iface_vers_maj = DCE2_SENTINEL;
429
430 iface_vers = 1;
431 }
432 else
433 {
434 if (any_frag)
435 {
436 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
437 DCE2_RoptError("\"%s\" rule option: Cannot configure "
438 "\"%s\" more than once.",
439 DCE2_ROPT__IFACE, DCE2_RARG__ANY_FRAG);
440 }
441
442 if (strcasecmp(token, DCE2_RARG__ANY_FRAG) == 0)
443 {
444 iface_data->any_frag = 1;
445 }
446 else
447 {
448 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
449 DCE2_RoptError("\"%s\" rule option: Invalid argument: %s.",
450 DCE2_ROPT__IFACE, token);
451 }
452
453 any_frag = 1;
454 }
455 }
456 else
457 {
458 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
459 DCE2_RoptError("\"%s\" rule option: Too many arguments.", DCE2_ROPT__IFACE);
460 }
461
462 } while ((token = strtok_r(NULL, DCE2_RTOKEN__OPT_SEP, &saveptr)) != NULL);
463
464 *data = (void *)iface_data;
465
466 return 1;
467 }
468
469 /********************************************************************
470 * Function:
471 *
472 * Purpose:
473 *
474 * Arguments:
475 *
476 * Returns:
477 *
478 ********************************************************************/
DCE2_ParseIface(char * token,DCE2_IfaceData * iface_data)479 static void DCE2_ParseIface(char *token, DCE2_IfaceData *iface_data)
480 {
481 char *iface, *ifaceptr = NULL;
482 char *if_hex, *if_hexptr = NULL;
483 int num_pieces = 0;
484
485 /* Has to be a uuid in string format, e.g 4b324fc8-1670-01d3-1278-5a47bf6ee188
486 * Check the length */
487 if (strlen(token) != DCE2_IFACE__LEN)
488 {
489 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
490 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
491 }
492
493 /* Detach token */
494 iface = strtok_r(token, DCE2_RTOKEN__ARG_SEP, &ifaceptr);
495 if (iface == NULL)
496 {
497 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
498 DCE2_Die("%s(%d) strtok_r() returned NULL when string argument "
499 "was not NULL.", __FILE__, __LINE__);
500 }
501
502 /* Cut into pieces separated by '-' */
503 if_hex = strtok_r(iface, DCE2_RTOKEN__IFACE_SEP, &if_hexptr);
504 if (if_hex == NULL)
505 {
506 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
507 DCE2_Die("%s(%d) strtok_r() returned NULL when string argument "
508 "was not NULL.", __FILE__, __LINE__);
509 }
510
511 do
512 {
513 char *endptr;
514
515 switch (num_pieces)
516 {
517 case 0:
518 {
519 unsigned long int time_low;
520
521 if (strlen(if_hex) != DCE2_IFACE__TIME_LOW_LEN)
522 {
523 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
524 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
525 }
526
527 time_low = _dpd.SnortStrtoul(if_hex, &endptr, 16);
528 if ((errno == ERANGE) || (*endptr != '\0'))
529 {
530 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
531 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
532 }
533
534 iface_data->iface.time_low = (uint32_t)time_low;
535 }
536
537 break;
538
539 case 1:
540 {
541 unsigned long int time_mid;
542
543 if (strlen(if_hex) != DCE2_IFACE__TIME_MID_LEN)
544 {
545 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
546 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
547 }
548
549 time_mid = _dpd.SnortStrtoul(if_hex, &endptr, 16);
550 if ((errno == ERANGE) || (*endptr != '\0'))
551 {
552 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
553 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
554 }
555
556 /* Length check ensures 16 bit value */
557 iface_data->iface.time_mid = (uint16_t)time_mid;
558 }
559
560 break;
561
562 case 2:
563 {
564 unsigned long int time_high;
565
566 if (strlen(if_hex) != DCE2_IFACE__TIME_HIGH_LEN)
567 {
568 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
569 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
570 }
571
572 time_high = _dpd.SnortStrtoul(if_hex, &endptr, 16);
573 if ((errno == ERANGE) || (*endptr != '\0'))
574 {
575 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
576 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
577 }
578
579 /* Length check ensures 16 bit value */
580 iface_data->iface.time_high_and_version = (uint16_t)time_high;
581 }
582
583 break;
584
585 case 3:
586 {
587 unsigned long int clock_seq_and_reserved, clock_seq_low;
588
589 if (strlen(if_hex) != DCE2_IFACE__CLOCK_SEQ_LEN)
590 {
591 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
592 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
593 }
594
595 /* Work backwards */
596 clock_seq_low = _dpd.SnortStrtoul(&if_hex[2], &endptr, 16);
597 if ((errno == ERANGE) || (*endptr != '\0'))
598 {
599 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
600 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
601 }
602
603 iface_data->iface.clock_seq_low = (uint8_t)clock_seq_low;
604
605 /* Set third byte to null so we can _dpd.SnortStrtoul the first part */
606 if_hex[2] = '\x00';
607
608 clock_seq_and_reserved = _dpd.SnortStrtoul(if_hex, &endptr, 16);
609 if ((errno == ERANGE) || (*endptr != '\0'))
610 {
611 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
612 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
613 }
614
615 iface_data->iface.clock_seq_and_reserved = (uint8_t)clock_seq_and_reserved;
616 }
617
618 break;
619
620 case 4:
621 {
622 int i, j;
623
624 if (strlen(if_hex) != DCE2_IFACE__NODE_LEN)
625 {
626 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
627 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
628 }
629
630 /* Walk back a byte at a time - 2 hex digits */
631 for (i = DCE2_IFACE__NODE_LEN - 2, j = sizeof(iface_data->iface.node) - 1;
632 (i >= 0) && (j >= 0);
633 i -= 2, j--)
634 {
635 /* Only giving _dpd.SnortStrtoul 1 byte */
636 iface_data->iface.node[j] = (uint8_t)_dpd.SnortStrtoul(&if_hex[i], &endptr, 16);
637 if ((errno == ERANGE) || (*endptr != '\0'))
638 {
639 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
640 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
641 }
642
643 if_hex[i] = '\0';
644 }
645 }
646
647 break;
648
649 default:
650 break;
651 }
652
653 num_pieces++;
654
655 } while ((if_hex = strtok_r(NULL, DCE2_RTOKEN__IFACE_SEP, &if_hexptr)) != NULL);
656
657 if (num_pieces != 5)
658 {
659 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
660 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
661 }
662
663 /* Check for more arguments */
664 iface = strtok_r(NULL, DCE2_RTOKEN__ARG_SEP, &ifaceptr);
665 if (iface != NULL)
666 {
667 DCE2_Free((void *)iface_data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
668 DCE2_RoptError("\"%s\" rule option: Invalid uuid.", DCE2_ROPT__IFACE);
669 }
670 }
671
DCE2_AllocFp(uint32_t size)672 static inline void * DCE2_AllocFp(uint32_t size)
673 {
674 void *mem = calloc(1, (size_t)size);
675 if (mem == NULL)
676 {
677 DCE2_Die("%s(%d) Out of memory!", __FILE__, __LINE__);
678 }
679
680 return mem;
681 }
682
DCE2_IfaceAddFastPatterns(void * rule_opt_data,int protocol,int direction,FPContentInfo ** info)683 static int DCE2_IfaceAddFastPatterns(void *rule_opt_data, int protocol,
684 int direction, FPContentInfo **info)
685 {
686 DCE2_IfaceData *iface_data = (DCE2_IfaceData *)rule_opt_data;
687
688 if ((rule_opt_data == NULL) || (info == NULL))
689 return -1;
690
691 if ((protocol != IPPROTO_TCP) && (protocol != IPPROTO_UDP))
692 return -1;
693
694 if (protocol == IPPROTO_TCP)
695 {
696 FPContentInfo *tcp_fp = (FPContentInfo *)DCE2_AllocFp(sizeof(FPContentInfo));
697 char *client_fp = "\x05\x00\x00";
698 char *server_fp = "\x05\x00\x02";
699 char *no_dir_fp = "\x05\x00";
700
701 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS, "Adding fast pattern "
702 "content for TCP rule option.\n"));
703
704 switch (direction)
705 {
706 case FLAG_FROM_CLIENT:
707 tcp_fp->content = (char *)DCE2_AllocFp(3);
708 memcpy(tcp_fp->content, client_fp, 3);
709 tcp_fp->length = 3;
710 break;
711
712 case FLAG_FROM_SERVER:
713 tcp_fp->content = (char *)DCE2_AllocFp(3);
714 memcpy(tcp_fp->content, server_fp, 3);
715 tcp_fp->length = 3;
716 break;
717
718 default:
719 tcp_fp->content = (char *)DCE2_AllocFp(2);
720 memcpy(tcp_fp->content, no_dir_fp, 2);
721 tcp_fp->length = 2;
722 break;
723 }
724
725 *info = tcp_fp;
726 }
727 else
728 {
729 //DCE2_IfaceData *iface_data = (DCE2_IfaceData *)rule_opt_data;
730 FPContentInfo *big_fp = (FPContentInfo *)DCE2_AllocFp(sizeof(FPContentInfo));
731 FPContentInfo *little_fp = (FPContentInfo *)DCE2_AllocFp(sizeof(FPContentInfo));
732 char *big_content = (char *)DCE2_AllocFp(sizeof(Uuid));
733 char *little_content = (char *)DCE2_AllocFp(sizeof(Uuid));
734 uint32_t time32;
735 uint16_t time16;
736 int index = 0;
737
738 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS, "Adding fast pattern "
739 "content for UDP rule option.\n"));
740
741 time32 = DceRpcNtohl(&iface_data->iface.time_low,
742 DCERPC_BO_FLAG__BIG_ENDIAN);
743 memcpy(&big_content[index], &time32, sizeof(uint32_t));
744 time32 = DceRpcNtohl(&iface_data->iface.time_low,
745 DCERPC_BO_FLAG__LITTLE_ENDIAN);
746 memcpy(&little_content[index], &time32, sizeof(uint32_t));
747 index += sizeof(uint32_t);
748
749 time16 = DceRpcNtohs(&iface_data->iface.time_mid,
750 DCERPC_BO_FLAG__BIG_ENDIAN);
751 memcpy(&big_content[index], &time16, sizeof(uint16_t));
752 time16 = DceRpcNtohs(&iface_data->iface.time_mid,
753 DCERPC_BO_FLAG__LITTLE_ENDIAN);
754 memcpy(&little_content[index], &time16, sizeof(uint16_t));
755 index += sizeof(uint16_t);
756
757 time16 = DceRpcNtohs(&iface_data->iface.time_high_and_version,
758 DCERPC_BO_FLAG__BIG_ENDIAN);
759 memcpy(&big_content[index], &time16, sizeof(uint16_t));
760 time16 = DceRpcNtohs(&iface_data->iface.time_high_and_version,
761 DCERPC_BO_FLAG__LITTLE_ENDIAN);
762 memcpy(&little_content[index], &time16, sizeof(uint16_t));
763 index += sizeof(uint16_t);
764
765 big_content[index] = iface_data->iface.clock_seq_and_reserved;
766 little_content[index] = iface_data->iface.clock_seq_and_reserved;
767 index += sizeof(uint8_t);
768
769 big_content[index] = iface_data->iface.clock_seq_low;
770 little_content[index] = iface_data->iface.clock_seq_low;
771 index += sizeof(uint8_t);
772
773 memcpy(&big_content[index], iface_data->iface.node, 6);
774 memcpy(&little_content[index], iface_data->iface.node, 6);
775
776 big_fp->content = big_content;
777 big_fp->length = sizeof(Uuid);
778 little_fp->content = little_content;
779 little_fp->length = sizeof(Uuid);
780
781 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
782 " Iface: %s\n Big endian: %s\n Little endian: %s\n",
783 DCE2_UuidToStr(&iface_data->iface, DCERPC_BO_FLAG__NONE),
784 DCE2_UuidToStr((Uuid *)big_fp->content, DCERPC_BO_FLAG__NONE),
785 DCE2_UuidToStr((Uuid *)little_fp->content, DCERPC_BO_FLAG__NONE)););
786
787 big_fp->next = little_fp;
788 *info = big_fp;
789 }
790
791 return 0;
792 }
793
794 /********************************************************************
795 * Function:
796 *
797 * Purpose:
798 *
799 * Arguments:
800 *
801 * Returns:
802 *
803 ********************************************************************/
DCE2_OpnumInit(struct _SnortConfig * sc,char * name,char * args,void ** data)804 static int DCE2_OpnumInit(struct _SnortConfig *sc, char *name, char *args, void **data)
805 {
806 uint8_t opnum_mask[DCE2_OPNUM__MAX_INDEX]; /* 65536 bits */
807 char *args_end;
808 uint16_t num_opnums = 0;
809 unsigned int i;
810 int opnum_lo = DCE2_SENTINEL;
811 int opnum_hi = 0;
812
813 if (strcasecmp(name, DCE2_ROPT__OPNUM) != 0)
814 return 0;
815
816 /* Must have arguments */
817 if (DCE2_IsEmptyStr(args))
818 {
819 DCE2_RoptError("\"%s\" rule option: No arguments. Must supply "
820 "the value of the opnum.", DCE2_ROPT__OPNUM);
821 }
822
823 /* Include NULL byte for parsing */
824 args_end = args + (strlen(args) + 1);
825 memset(opnum_mask, 0, sizeof(opnum_mask));
826
827 DCE2_ParseOpnumList(&args, args_end, opnum_mask);
828
829 /* Must have at least one bit set or the parsing would have errored */
830 for (i = 0; i < DCE2_OPNUM__MAX; i++)
831 {
832 if (DCE2_OpnumIsSet(opnum_mask, 0, DCE2_OPNUM__MAX - 1, (uint16_t)i))
833 {
834 num_opnums++;
835
836 if (opnum_lo == DCE2_SENTINEL)
837 opnum_lo = (uint16_t)i;
838
839 opnum_hi = (uint16_t)i;
840 }
841 }
842
843 if (num_opnums == 1)
844 {
845 DCE2_OpnumSingle *odata =
846 (DCE2_OpnumSingle *)DCE2_Alloc(sizeof(DCE2_OpnumSingle), DCE2_MEM_TYPE__ROPTION);
847
848 if (odata == NULL)
849 {
850 DCE2_Die("%s(%d) Failed to allocate memory for opnum data.",
851 __FILE__, __LINE__);
852 }
853
854 odata->odata.type = DCE2_OPNUM_TYPE__SINGLE;
855 odata->opnum = (uint16_t)opnum_lo;
856
857 *data = (void *)odata;
858 }
859 else
860 {
861 int opnum_range = opnum_hi - opnum_lo;
862 int mask_size = (opnum_range / 8) + 1;
863 DCE2_OpnumMultiple *odata =
864 (DCE2_OpnumMultiple *)DCE2_Alloc(sizeof(DCE2_OpnumMultiple), DCE2_MEM_TYPE__ROPTION);
865
866 if (odata == NULL)
867 {
868 DCE2_Die("%s(%d) Failed to allocate memory for opnum data.",
869 __FILE__, __LINE__);
870 }
871
872 odata->mask = (uint8_t *)DCE2_Alloc(mask_size, DCE2_MEM_TYPE__ROPTION);
873 if (odata->mask == NULL)
874 {
875 DCE2_Free((void *)odata, sizeof(DCE2_OpnumMultiple), DCE2_MEM_TYPE__ROPTION);
876 DCE2_Die("%s(%d) Failed to allocate memory for opnum data.",
877 __FILE__, __LINE__);
878 }
879
880 odata->odata.type = DCE2_OPNUM_TYPE__MULTIPLE;
881 odata->mask_size = (uint16_t)mask_size;
882 odata->opnum_lo = (uint16_t)opnum_lo;
883 odata->opnum_hi = (uint16_t)opnum_hi;
884
885 /* Set the opnum bits in our reduced size opnum mask */
886 for (i = (unsigned int)opnum_lo; i <= (unsigned int)opnum_hi; i++)
887 {
888 if (DCE2_OpnumIsSet(opnum_mask, 0, DCE2_OPNUM__MAX - 1, (uint16_t)i))
889 DCE2_OpnumSet(odata->mask, (uint16_t)(i - opnum_lo));
890 }
891
892 *data = (void *)odata;
893 }
894
895 return 1;
896 }
897
898 /********************************************************************
899 * Function:
900 *
901 *
902 * Arguments:
903 *
904 * Returns:
905 *
906 ********************************************************************/
DCE2_ParseOpnumList(char ** ptr,char * end,uint8_t * opnum_mask)907 static void DCE2_ParseOpnumList(char **ptr, char *end, uint8_t *opnum_mask)
908 {
909 char *lo_start = NULL;
910 char *hi_start = NULL;
911 DCE2_OpnumListState state = DCE2_OPNUM_LIST_STATE__START;
912 uint16_t lo_opnum = 0, hi_opnum = 0;
913
914 while (*ptr < end)
915 {
916 char c = **ptr;
917
918 if (state == DCE2_OPNUM_LIST_STATE__END)
919 break;
920
921 switch (state)
922 {
923 case DCE2_OPNUM_LIST_STATE__START:
924 if (DCE2_IsOpnumChar(c))
925 {
926 lo_start = *ptr;
927 state = DCE2_OPNUM_LIST_STATE__OPNUM_LO;
928 }
929 else if (!DCE2_IsSpaceChar(c))
930 {
931 DCE2_RoptError("\"%s\" rule option: Invalid opnum list: %s.",
932 DCE2_ROPT__OPNUM, *ptr);
933 }
934
935 break;
936
937 case DCE2_OPNUM_LIST_STATE__OPNUM_LO:
938 if (!DCE2_IsOpnumChar(c))
939 {
940 DCE2_Ret status = DCE2_GetValue(lo_start, *ptr, &lo_opnum,
941 0, DCE2_INT_TYPE__UINT16, 10);
942
943 if (status != DCE2_RET__SUCCESS)
944 {
945 DCE2_RoptError("\"%s\" rule option: Invalid opnum: %.*s",
946 DCE2_ROPT__OPNUM, *ptr - lo_start, lo_start);
947 }
948
949 if (DCE2_IsOpnumRangeChar(c))
950 {
951 state = DCE2_OPNUM_LIST_STATE__OPNUM_RANGE;
952 }
953 else
954 {
955 DCE2_OpnumSet(opnum_mask, lo_opnum);
956 state = DCE2_OPNUM_LIST_STATE__OPNUM_END;
957 continue;
958 }
959 }
960
961 break;
962
963 case DCE2_OPNUM_LIST_STATE__OPNUM_RANGE:
964 if (DCE2_IsOpnumChar(c))
965 {
966 hi_start = *ptr;
967 state = DCE2_OPNUM_LIST_STATE__OPNUM_HI;
968 }
969 else
970 {
971 DCE2_OpnumSetRange(opnum_mask, lo_opnum, UINT16_MAX);
972 state = DCE2_OPNUM_LIST_STATE__OPNUM_END;
973 continue;
974 }
975
976 break;
977
978 case DCE2_OPNUM_LIST_STATE__OPNUM_HI:
979 if (!DCE2_IsOpnumChar(c))
980 {
981 DCE2_Ret status = DCE2_GetValue(hi_start, *ptr, &hi_opnum,
982 0, DCE2_INT_TYPE__UINT16, 10);
983
984 if (status != DCE2_RET__SUCCESS)
985 {
986 DCE2_RoptError("\"%s\" rule option: Invalid opnum: %.*s",
987 DCE2_ROPT__OPNUM, *ptr - hi_start, hi_start);
988 }
989
990 DCE2_OpnumSetRange(opnum_mask, lo_opnum, hi_opnum);
991 state = DCE2_OPNUM_LIST_STATE__OPNUM_END;
992 continue;
993 }
994
995 break;
996
997 case DCE2_OPNUM_LIST_STATE__OPNUM_END:
998 if (DCE2_IsListSepChar(c))
999 {
1000 state = DCE2_OPNUM_LIST_STATE__START;
1001 }
1002 else if (DCE2_IsConfigEndChar(c))
1003 {
1004 state = DCE2_OPNUM_LIST_STATE__END;
1005 continue;
1006 }
1007 else if (!DCE2_IsSpaceChar(c))
1008 {
1009 DCE2_RoptError("\"%s\" rule option: Invalid opnum list: %s.",
1010 DCE2_ROPT__OPNUM, *ptr);
1011 }
1012
1013 break;
1014
1015 default:
1016 DCE2_Die("%s(%d) Invalid opnum list state: %d",
1017 __FILE__, __LINE__, state);
1018 break;
1019 }
1020
1021 (*ptr)++;
1022 }
1023
1024 if (state != DCE2_OPNUM_LIST_STATE__END)
1025 {
1026 DCE2_RoptError("\"%s\" rule option: Invalid opnum list: %s",
1027 DCE2_ROPT__OPNUM, *ptr);
1028 }
1029 }
1030
1031 /********************************************************************
1032 * Function:
1033 *
1034 * Purpose:
1035 *
1036 * Arguments:
1037 *
1038 * Returns:
1039 *
1040 ********************************************************************/
DCE2_OpnumIsSet(const uint8_t * opnum_mask,const uint16_t opnum_lo,const uint16_t opnum_hi,const uint16_t opnum)1041 static inline int DCE2_OpnumIsSet(const uint8_t *opnum_mask, const uint16_t opnum_lo,
1042 const uint16_t opnum_hi, const uint16_t opnum)
1043 {
1044 uint16_t otmp = opnum - opnum_lo;
1045
1046 if ((opnum < opnum_lo) || (opnum > opnum_hi))
1047 return 0;
1048
1049 return opnum_mask[(otmp / 8)] & (1 << (otmp % 8));
1050 }
1051
1052 /********************************************************************
1053 * Function:
1054 *
1055 * Purpose:
1056 *
1057 * Arguments:
1058 *
1059 * Returns:
1060 *
1061 ********************************************************************/
DCE2_OpnumSet(uint8_t * opnum_mask,const uint16_t opnum)1062 static inline void DCE2_OpnumSet(uint8_t *opnum_mask, const uint16_t opnum)
1063 {
1064 opnum_mask[(opnum / 8)] |= (1 << (opnum % 8));
1065 }
1066
1067 /********************************************************************
1068 * Function:
1069 *
1070 * Purpose:
1071 *
1072 * Arguments:
1073 *
1074 * Returns:
1075 *
1076 ********************************************************************/
DCE2_OpnumSetRange(uint8_t * opnum_mask,uint16_t lo_opnum,uint16_t hi_opnum)1077 static inline void DCE2_OpnumSetRange(uint8_t *opnum_mask, uint16_t lo_opnum, uint16_t hi_opnum)
1078 {
1079 uint16_t i;
1080
1081 if (lo_opnum > hi_opnum)
1082 {
1083 uint16_t tmp = lo_opnum;
1084 lo_opnum = hi_opnum;
1085 hi_opnum = tmp;
1086 }
1087
1088 for (i = lo_opnum; i <= hi_opnum; i++)
1089 DCE2_OpnumSet(opnum_mask, i);
1090 }
1091
1092 /********************************************************************
1093 * Function:
1094 *
1095 * Purpose:
1096 *
1097 * Arguments:
1098 *
1099 * Returns:
1100 *
1101 ********************************************************************/
DCE2_StubDataInit(struct _SnortConfig * sc,char * name,char * args,void ** data)1102 static int DCE2_StubDataInit(struct _SnortConfig *sc, char *name, char *args, void **data)
1103 {
1104 if (strcasecmp(name, DCE2_ROPT__STUB_DATA) != 0)
1105 return 0;
1106
1107 /* Must not have arguments */
1108 if (!DCE2_IsEmptyStr(args))
1109 {
1110 DCE2_RoptError("\"%s\" rule option: This option has no arguments.",
1111 DCE2_ROPT__STUB_DATA);
1112 }
1113
1114 /* Set it to something even though we don't need it */
1115 *data = (void *)1;
1116
1117 return 1;
1118 }
1119
1120 /********************************************************************
1121 * Function:
1122 *
1123 * Purpose:
1124 *
1125 * Arguments:
1126 *
1127 * Returns:
1128 *
1129 ********************************************************************/
DCE2_ByteTestInit(struct _SnortConfig * sc,char * name,char * args,void ** data)1130 static int DCE2_ByteTestInit(struct _SnortConfig *sc, char *name, char *args, void **data)
1131 {
1132 char *token, *saveptr = NULL;
1133 int tok_num = 0;
1134 DCE2_ByteTestData *bt_data;
1135
1136 if (strcasecmp(name, DCE2_ROPT__BYTE_TEST) != 0)
1137 return 0;
1138
1139 bt_data = (DCE2_ByteTestData *)DCE2_Alloc(sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1140 if (bt_data == NULL)
1141 {
1142 DCE2_Die("%s(%d) Failed to allocate memory for byte test data structure.",
1143 __FILE__, __LINE__);
1144 }
1145
1146 bt_data->operator = DCE2_BT_OP__NONE;
1147
1148 /* Must have arguments */
1149 if (DCE2_IsEmptyStr(args))
1150 {
1151 DCE2_Free((void *)bt_data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1152 DCE2_RoptError("\"%s\" rule option: No arguments.", DCE2_ROPT__BYTE_TEST);
1153 }
1154
1155 /* Get argument */
1156 token = strtok_r(args, DCE2_RTOKEN__OPT_SEP, &saveptr);
1157 if (token == NULL)
1158 {
1159 DCE2_Free((void *)bt_data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1160 DCE2_Die("%s(%d) strtok_r() returned NULL when string argument "
1161 "was not NULL.", __FILE__, __LINE__);
1162 }
1163
1164 do
1165 {
1166 tok_num++;
1167
1168 token = DCE2_PruneWhiteSpace(token);
1169
1170 if (tok_num == 1) /* Number of bytes to convert */
1171 {
1172 char *endptr;
1173 unsigned long int num_bytes = _dpd.SnortStrtoul(token, &endptr, 10);
1174
1175 if ((errno == ERANGE) || (*endptr != '\0'))
1176 {
1177 DCE2_Free((void *)bt_data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1178 DCE2_RoptError("\"%s\" rule option: Invalid number of bytes to "
1179 "convert: %s. Should be one of 1, 2 or 4.",
1180 DCE2_ROPT__BYTE_TEST, token);
1181 }
1182
1183 if ((num_bytes != 1) && (num_bytes != 2) && (num_bytes != 4))
1184 {
1185 DCE2_Free((void *)bt_data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1186 DCE2_RoptError("\"%s\" rule option: Invalid number of bytes to "
1187 "convert: %s. Should be one of 1, 2 or 4.",
1188 DCE2_ROPT__BYTE_TEST, token);
1189 }
1190
1191 bt_data->num_bytes = num_bytes;
1192 }
1193 else if (tok_num == 2) /* Operator */
1194 {
1195 /* Should only be one byte */
1196 if (strlen(token) > 2)
1197 {
1198 DCE2_Free((void *)bt_data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1199 DCE2_RoptError("\"%s\" rule option: Invalid argument: %s",
1200 DCE2_ROPT__BYTE_TEST, token);
1201 }
1202
1203 /* If two bytes first must be '!' */
1204 if (strlen(token) == 2)
1205 {
1206 if (*token != DCE2_RARG__NE)
1207 {
1208 DCE2_Free((void *)bt_data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1209 DCE2_RoptError("\"%s\" rule option: Invalid argument: %s",
1210 DCE2_ROPT__BYTE_TEST, token);
1211 }
1212 else
1213 {
1214 bt_data->invert = 1;
1215 }
1216
1217 token++;
1218 }
1219
1220 switch (*token)
1221 {
1222 case DCE2_RARG__LT:
1223 bt_data->operator = DCE2_BT_OP__LT;
1224 break;
1225 case DCE2_RARG__EQ:
1226 bt_data->operator = DCE2_BT_OP__EQ;
1227 break;
1228 case DCE2_RARG__GT:
1229 bt_data->operator = DCE2_BT_OP__GT;
1230 break;
1231 case DCE2_RARG__AND:
1232 bt_data->operator = DCE2_BT_OP__AND;
1233 break;
1234 case DCE2_RARG__XOR:
1235 bt_data->operator = DCE2_BT_OP__XOR;
1236 break;
1237 default:
1238 DCE2_Free((void *)bt_data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1239 DCE2_RoptError("\"%s\" rule option: Invalid argument: %s",
1240 DCE2_ROPT__BYTE_TEST, token);
1241 break;
1242 }
1243 }
1244 else if (tok_num == 3) /* Value to compare to */
1245 {
1246 char *endptr;
1247 unsigned long int value = _dpd.SnortStrtoul(token, &endptr, 10);
1248
1249 if ((errno == ERANGE) || (*endptr != '\0') || (value > UINT32_MAX))
1250 {
1251 DCE2_Free((void *)bt_data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1252 DCE2_RoptError("\"%s\" rule option: Invalid compare value: %s. Must be "
1253 "between 0 and %u inclusive.",
1254 DCE2_ROPT__BYTE_TEST, token, UINT32_MAX);
1255 }
1256
1257 bt_data->value = value;
1258 }
1259 else if (tok_num == 4) /* Offset in packet data */
1260 {
1261 char *endptr;
1262 long int offset = _dpd.SnortStrtol(token, &endptr, 10);
1263
1264 if ((errno == ERANGE) || (*endptr != '\0') ||
1265 (offset > (long int)UINT16_MAX) || (offset < (-1 * (long int)UINT16_MAX)))
1266 {
1267 DCE2_Free((void *)bt_data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1268 DCE2_RoptError("\"%s\" rule option: Invalid offset: %s. Must be "
1269 "between -%u and %u inclusive.",
1270 DCE2_ROPT__BYTE_TEST, token, UINT16_MAX, UINT16_MAX);
1271 }
1272
1273 bt_data->offset = offset;
1274 }
1275 else if ((tok_num == 5) || (tok_num == 6))
1276 {
1277 if (strcasecmp(token, DCE2_RARG__RELATIVE) == 0)
1278 {
1279 /* Can't configure it twice */
1280 if (bt_data->relative)
1281 {
1282 DCE2_Free((void *)bt_data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1283 DCE2_RoptError("\"%s\" rule option: Can't configure \"%s\" "
1284 "more than once.",
1285 DCE2_ROPT__BYTE_TEST, DCE2_RARG__RELATIVE);
1286 }
1287
1288 bt_data->relative = 1;
1289 }
1290 else if (strcasecmp(token, DCE2_RARG__DCE_OVERRIDE) != 0)
1291 {
1292 DCE2_Free((void *)bt_data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1293 DCE2_RoptError("\"%s\" rule option: Invalid argument: %s.",
1294 DCE2_ROPT__BYTE_TEST, token);
1295 }
1296 }
1297 else
1298 {
1299 DCE2_Free((void *)bt_data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1300 DCE2_RoptError("\"%s\" rule option: Too many arguments.", DCE2_ROPT__BYTE_TEST);
1301 }
1302
1303 } while ((token = strtok_r(NULL, DCE2_RTOKEN__OPT_SEP, &saveptr)) != NULL);
1304
1305 if (tok_num < DCE2_BTEST__MIN_ARGS)
1306 {
1307 DCE2_Free((void *)bt_data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
1308 DCE2_RoptError("\"%s\" rule option: Not enough arguments.", DCE2_ROPT__BYTE_TEST);
1309 }
1310
1311 *data = (void *)bt_data;
1312
1313 return 1;
1314 }
1315
1316 /********************************************************************
1317 * Function:
1318 *
1319 * Purpose:
1320 *
1321 * Arguments:
1322 *
1323 * Returns:
1324 *
1325 ********************************************************************/
DCE2_ByteJumpInit(struct _SnortConfig * sc,char * name,char * args,void ** data)1326 static int DCE2_ByteJumpInit(struct _SnortConfig *sc, char *name, char *args, void **data)
1327 {
1328 char *token, *saveptr = NULL;
1329 int tok_num = 0;
1330 DCE2_ByteJumpData *bj_data;
1331 int post_offset_configured = 0;
1332
1333 if (strcasecmp(name, DCE2_ROPT__BYTE_JUMP) != 0)
1334 return 0;
1335
1336 bj_data = (DCE2_ByteJumpData *)DCE2_Alloc(sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1337 if (bj_data == NULL)
1338 {
1339 DCE2_Die("%s(%d) Failed to allocate memory for byte jump data structure.",
1340 __FILE__, __LINE__);
1341 }
1342
1343 bj_data->multiplier = DCE2_SENTINEL;
1344
1345 /* Must have arguments */
1346 if (DCE2_IsEmptyStr(args))
1347 {
1348 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1349 DCE2_RoptError("\"%s\" rule option: No arguments.", DCE2_ROPT__BYTE_JUMP);
1350 }
1351
1352 /* Get argument */
1353 token = strtok_r(args, DCE2_RTOKEN__OPT_SEP, &saveptr);
1354 if (token == NULL)
1355 {
1356 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1357 DCE2_Die("%s(%d) strtok_r() returned NULL when string argument "
1358 "was not NULL.", __FILE__, __LINE__);
1359 }
1360
1361 do
1362 {
1363 tok_num++;
1364
1365 token = DCE2_PruneWhiteSpace(token);
1366
1367 if (tok_num == 1) /* Number of bytes to convert */
1368 {
1369 char *endptr;
1370 unsigned long int num_bytes = _dpd.SnortStrtoul(token, &endptr, 10);
1371
1372 if ((errno == ERANGE) || (*endptr != '\0'))
1373 {
1374 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1375 DCE2_RoptError("\"%s\" rule option: Invalid number of bytes to "
1376 "convert: %s. Should be one of 1, 2 or 4.",
1377 DCE2_ROPT__BYTE_JUMP, token);
1378 }
1379
1380 if ((num_bytes != 4) && (num_bytes != 2) && (num_bytes != 1))
1381 {
1382 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1383 DCE2_RoptError("\"%s\" rule option: Invalid number of bytes to "
1384 "convert: %s. Should be one of 1, 2 or 4.",
1385 DCE2_ROPT__BYTE_JUMP, token);
1386 }
1387
1388 bj_data->num_bytes = num_bytes;
1389 }
1390 else if (tok_num == 2) /* Offset in packet data */
1391 {
1392 char *endptr;
1393 long int offset = _dpd.SnortStrtol(token, &endptr, 10);
1394
1395 if ((errno == ERANGE) || (*endptr != '\0') ||
1396 (offset > (long int)UINT16_MAX) || (offset < (-1 * (long int)UINT16_MAX)))
1397 {
1398 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1399 DCE2_RoptError("\"%s\" rule option: Invalid offset: %s. Must be "
1400 "between -%u and %u inclusive.",
1401 DCE2_ROPT__BYTE_JUMP, token, UINT16_MAX, UINT16_MAX);
1402 }
1403
1404 bj_data->offset = offset;
1405 }
1406 else if ((tok_num > DCE2_BJUMP__MIN_ARGS) && (tok_num <= DCE2_BJUMP__MAX_ARGS))
1407 {
1408 char *arg, *argptr;
1409
1410 /* Detach arg to get potenial sub-arg */
1411 arg = strtok_r(token, DCE2_RTOKEN__ARG_SEP, &argptr);
1412 if (arg == NULL)
1413 {
1414 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1415 DCE2_Die("%s(%d) strtok_r() returned NULL when string argument "
1416 "was not NULL.", __FILE__, __LINE__);
1417 }
1418
1419 if (strcasecmp(arg, DCE2_RARG__RELATIVE) == 0)
1420 {
1421 /* Can't configure it twice */
1422 if (bj_data->relative)
1423 {
1424 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1425 DCE2_RoptError("\"%s\" rule option: Can't configure \"%s\" "
1426 "more than once.",
1427 DCE2_ROPT__BYTE_TEST, DCE2_RARG__RELATIVE);
1428 }
1429
1430 bj_data->relative = 1;
1431 }
1432 else if (strcasecmp(arg, DCE2_RARG__ALIGN) == 0)
1433 {
1434 if (bj_data->align)
1435 {
1436 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1437 DCE2_RoptError("\"%s\" rule option: Can't configure \"%s\" "
1438 "more than once.",
1439 DCE2_ROPT__BYTE_TEST, DCE2_RARG__ALIGN);
1440 }
1441
1442 bj_data->align = 1;
1443 }
1444 else if (strcasecmp(arg, DCE2_RARG__MULTIPLIER) == 0)
1445 {
1446 char *endptr;
1447 unsigned long int multiplier;
1448
1449 if (bj_data->multiplier != DCE2_SENTINEL)
1450 {
1451 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1452 DCE2_RoptError("\"%s\" rule option: Can't configure \"%s\" "
1453 "more than once.",
1454 DCE2_ROPT__BYTE_TEST, DCE2_RARG__MULTIPLIER);
1455 }
1456
1457 arg = strtok_r(NULL, DCE2_RTOKEN__ARG_SEP, &argptr);
1458 if (arg == NULL)
1459 {
1460 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1461 DCE2_RoptError("\"%s\" rule option: \"%s\" requires an argument.",
1462 DCE2_ROPT__BYTE_JUMP, DCE2_RARG__MULTIPLIER);
1463 }
1464
1465 multiplier = _dpd.SnortStrtoul(arg, &endptr, 10);
1466 if ((errno == ERANGE) || (*endptr != '\0') ||
1467 (multiplier <= 1) || (multiplier > UINT16_MAX))
1468 {
1469 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1470 DCE2_RoptError("\"%s\" rule option: Invalid multiplier: %s. "
1471 "Must be between 2 and %u inclusive.",
1472 DCE2_ROPT__BYTE_JUMP, arg, UINT16_MAX);
1473 }
1474
1475 bj_data->multiplier = multiplier;
1476 }
1477 else if (strcasecmp(arg, DCE2_RARG__POST_OFFSET) == 0)
1478 {
1479 char *endptr;
1480 long int post_offset;
1481
1482 if (post_offset_configured)
1483 {
1484 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1485 DCE2_RoptError("\"%s\" rule option: Can't configure \"%s\" "
1486 "more than once.",
1487 DCE2_ROPT__BYTE_TEST, DCE2_RARG__POST_OFFSET);
1488 }
1489
1490 arg = strtok_r(NULL, DCE2_RTOKEN__ARG_SEP, &argptr);
1491 if (arg == NULL)
1492 {
1493 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1494 DCE2_RoptError("\"%s\" rule option: \"%s\" requires an argument.",
1495 DCE2_ROPT__BYTE_JUMP, DCE2_RARG__POST_OFFSET);
1496 }
1497
1498 post_offset = _dpd.SnortStrtol(arg, &endptr, 10);
1499 if ((errno == ERANGE) || (*endptr != '\0') ||
1500 (post_offset > (long int)UINT16_MAX) || (post_offset < (-1 * (long int)UINT16_MAX)))
1501 {
1502 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1503 DCE2_RoptError("\"%s\" rule option: Invalid post offset "
1504 "value: %s. Must be between -%u to %u inclusive",
1505 DCE2_ROPT__BYTE_JUMP, arg, UINT16_MAX, UINT16_MAX);
1506 }
1507
1508 bj_data->post_offset = post_offset;
1509 post_offset_configured = 1;
1510 }
1511 else if (strcasecmp(arg, DCE2_RARG__DCE_OVERRIDE) != 0)
1512 {
1513 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1514 DCE2_RoptError("\"%s\" rule option: Invalid argument: %s.",
1515 DCE2_ROPT__BYTE_JUMP, arg);
1516 }
1517 }
1518 else
1519 {
1520 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1521 DCE2_RoptError("\"%s\" rule option: Too many arguments.", DCE2_ROPT__BYTE_JUMP);
1522 }
1523
1524 } while ((token = strtok_r(NULL, DCE2_RTOKEN__OPT_SEP, &saveptr)) != NULL);
1525
1526 if (tok_num < DCE2_BJUMP__MIN_ARGS)
1527 {
1528 DCE2_Free((void *)bj_data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
1529 DCE2_RoptError("\"%s\" rule option: Not enough arguments.", DCE2_ROPT__BYTE_JUMP);
1530 }
1531
1532 *data = (void *)bj_data;
1533
1534 return 1;
1535 }
1536
1537 /********************************************************************
1538 * Function:
1539 *
1540 * Purpose:
1541 *
1542 * Arguments:
1543 *
1544 * Returns:
1545 *
1546 ********************************************************************/
DCE2_IfaceEval(void * pkt,const uint8_t ** cursor,void * data)1547 static int DCE2_IfaceEval(void *pkt, const uint8_t **cursor, void *data)
1548 {
1549 SFSnortPacket *p = (SFSnortPacket *)pkt;
1550 DCE2_SsnData *sd;
1551 DCE2_Roptions *ropts;
1552 DCE2_IfaceData *iface_data;
1553 int ret = RULE_NOMATCH;
1554
1555 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1556 "Evaluating \"%s\" rule option.\n", DCE2_ROPT__IFACE));
1557
1558 if (!DCE2_RoptDoEval(p))
1559 return RULE_NOMATCH;
1560
1561 sd = (DCE2_SsnData *)_dpd.sessionAPI->get_application_data(p->stream_session, PP_DCE2);
1562 if ((sd == NULL) || DCE2_SsnNoInspect(sd))
1563 {
1564 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1565 "No session data - not evaluating.\n"));
1566 return RULE_NOMATCH;
1567 }
1568
1569 ropts = &sd->ropts;
1570
1571 if (ropts->first_frag == DCE2_SENTINEL)
1572 {
1573 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1574 "First frag not set - not evaluating.\n"));
1575 return RULE_NOMATCH;
1576 }
1577
1578 iface_data = (DCE2_IfaceData *)data;
1579 if (iface_data == NULL)
1580 return RULE_NOMATCH;
1581
1582 if (!iface_data->any_frag && !ropts->first_frag)
1583 {
1584 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1585 "Not a first fragment and rule set to only look at "
1586 "first fragment.\n"));
1587
1588 return RULE_NOMATCH;
1589 }
1590
1591 /* Compare the uuid */
1592 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS, "Comparing \"%s\" to \"%s\"\n",
1593 DCE2_UuidToStr(&ropts->iface, DCERPC_BO_FLAG__NONE),
1594 DCE2_UuidToStr(&iface_data->iface, DCERPC_BO_FLAG__NONE)));
1595
1596 if (DCE2_UuidCompare((void *)&ropts->iface, (void *)&iface_data->iface) != 0)
1597 {
1598 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS, "Uuids don't match\n"));
1599 return RULE_NOMATCH;
1600 }
1601
1602 if (iface_data->operator == DCE2_IF_OP__NONE)
1603 {
1604 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1605 "\"%s\" Match\n", DCE2_ROPT__IFACE));
1606 return RULE_MATCH;
1607 }
1608
1609 switch (iface_data->operator)
1610 {
1611 case DCE2_IF_OP__LT:
1612 if (IsTCP(p) && (iface_data->iface_vers_maj != DCE2_SENTINEL))
1613 {
1614 if ((int)ropts->iface_vers_maj < iface_data->iface_vers_maj)
1615 ret = RULE_MATCH;
1616 }
1617 else
1618 {
1619 if (ropts->iface_vers < iface_data->iface_vers)
1620 ret = RULE_MATCH;
1621 }
1622
1623 break;
1624
1625 case DCE2_IF_OP__EQ:
1626 if (IsTCP(p) && (iface_data->iface_vers_maj != DCE2_SENTINEL))
1627 {
1628 if ((int)ropts->iface_vers_maj == iface_data->iface_vers_maj)
1629 ret = RULE_MATCH;
1630 }
1631 else
1632 {
1633 if (ropts->iface_vers == iface_data->iface_vers)
1634 ret = RULE_MATCH;
1635 }
1636
1637 break;
1638
1639 case DCE2_IF_OP__GT:
1640 if (IsTCP(p) && (iface_data->iface_vers_maj != DCE2_SENTINEL))
1641 {
1642 if ((int)ropts->iface_vers_maj > iface_data->iface_vers_maj)
1643 ret = RULE_MATCH;
1644 }
1645 else
1646 {
1647 if (ropts->iface_vers > iface_data->iface_vers)
1648 ret = RULE_MATCH;
1649 }
1650
1651 break;
1652
1653 case DCE2_IF_OP__NE:
1654 if (IsTCP(p) && (iface_data->iface_vers_maj != DCE2_SENTINEL))
1655 {
1656 if ((int)ropts->iface_vers_maj != iface_data->iface_vers_maj)
1657 ret = RULE_MATCH;
1658 }
1659 else
1660 {
1661 if (ropts->iface_vers != iface_data->iface_vers)
1662 ret = RULE_MATCH;
1663 }
1664
1665 break;
1666
1667 default:
1668 break;
1669 }
1670
1671 return ret;
1672 }
1673
1674 /********************************************************************
1675 * Function:
1676 *
1677 * Purpose:
1678 *
1679 * Arguments:
1680 *
1681 * Returns:
1682 *
1683 ********************************************************************/
DCE2_OpnumEval(void * pkt,const uint8_t ** cursor,void * data)1684 static int DCE2_OpnumEval(void *pkt, const uint8_t **cursor, void *data)
1685 {
1686 SFSnortPacket *p = (SFSnortPacket *)pkt;
1687 DCE2_OpnumData *opnum_data = (DCE2_OpnumData *)data;
1688 DCE2_SsnData *sd;
1689 DCE2_Roptions *ropts;
1690
1691 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1692 "Evaluating \"%s\" rule option.\n", DCE2_ROPT__OPNUM));
1693
1694 if (!DCE2_RoptDoEval(p))
1695 return RULE_NOMATCH;
1696
1697 sd = (DCE2_SsnData *)_dpd.sessionAPI->get_application_data(p->stream_session, PP_DCE2);
1698 if ((sd == NULL) || DCE2_SsnNoInspect(sd))
1699 {
1700 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1701 "No session data - not evaluating.\n"));
1702 return RULE_NOMATCH;
1703 }
1704
1705 ropts = &sd->ropts;
1706
1707 if (ropts->opnum == DCE2_SENTINEL)
1708 {
1709 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1710 "Opnum not set - not evaluating.\n"));
1711 return RULE_NOMATCH;
1712 }
1713
1714 switch (opnum_data->type)
1715 {
1716 case DCE2_OPNUM_TYPE__SINGLE:
1717 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1718 "Rule opnum: %u, ropts opnum: %u\n",
1719 ((DCE2_OpnumSingle *)opnum_data)->opnum, ropts->opnum));
1720
1721 if (ropts->opnum == ((DCE2_OpnumSingle *)opnum_data)->opnum)
1722 {
1723 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1724 "\"%s\" Match\n", DCE2_ROPT__OPNUM));
1725 return RULE_MATCH;
1726 }
1727
1728 break;
1729
1730 case DCE2_OPNUM_TYPE__MULTIPLE:
1731 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1732 "Multiple opnums: ropts opnum: %u\n", ropts->opnum));
1733
1734 {
1735 DCE2_OpnumMultiple *omult = (DCE2_OpnumMultiple *)opnum_data;
1736
1737 if (DCE2_OpnumIsSet(omult->mask, omult->opnum_lo,
1738 omult->opnum_hi, (uint16_t)ropts->opnum))
1739 {
1740 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1741 "\"%s\" Match\n", DCE2_ROPT__OPNUM));
1742 return RULE_MATCH;
1743 }
1744 }
1745
1746 break;
1747
1748 default:
1749 DCE2_Log(DCE2_LOG_TYPE__ERROR,
1750 "%s(%d) Invalid opnum type: %d",
1751 __FILE__, __LINE__, opnum_data->type);
1752 break;
1753 }
1754
1755 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1756 "\"%s\" Fail\n", DCE2_ROPT__OPNUM));
1757
1758 return RULE_NOMATCH;
1759 }
1760
1761 /********************************************************************
1762 * Function:
1763 *
1764 * Purpose:
1765 *
1766 * Arguments:
1767 *
1768 * Returns:
1769 *
1770 ********************************************************************/
DCE2_StubDataEval(void * pkt,const uint8_t ** cursor,void * data)1771 static int DCE2_StubDataEval(void *pkt, const uint8_t **cursor, void *data)
1772 {
1773 SFSnortPacket *p = (SFSnortPacket *)pkt;
1774 DCE2_SsnData *sd;
1775 DCE2_Roptions *ropts;
1776
1777 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1778 "Evaluating \"%s\" rule option.\n", DCE2_ROPT__STUB_DATA));
1779
1780 if (!DCE2_RoptDoEval(p))
1781 return RULE_NOMATCH;
1782
1783 sd = (DCE2_SsnData *)_dpd.sessionAPI->get_application_data(p->stream_session, PP_DCE2);
1784 if ((sd == NULL) || DCE2_SsnNoInspect(sd))
1785 {
1786 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1787 "No session data - not evaluating.\n"));
1788 return RULE_NOMATCH;
1789 }
1790
1791 ropts = &sd->ropts;
1792
1793 if (ropts->stub_data != NULL)
1794 {
1795 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1796 "Setting cursor to stub data: %p.\n", ropts->stub_data));
1797 *cursor = ropts->stub_data;
1798 _dpd.SetAltDetect((uint8_t *)ropts->stub_data, (uint16_t)(p->payload_size - (ropts->stub_data - p->payload)));
1799 return RULE_MATCH;
1800 }
1801
1802 return RULE_NOMATCH;
1803 }
1804
1805 /********************************************************************
1806 * Function:
1807 *
1808 * Purpose:
1809 *
1810 * Arguments:
1811 *
1812 * Returns:
1813 *
1814 ********************************************************************/
DCE2_ByteTestEval(void * pkt,const uint8_t ** cursor,void * data)1815 static int DCE2_ByteTestEval(void *pkt, const uint8_t **cursor, void *data)
1816 {
1817 SFSnortPacket *p = (SFSnortPacket *)pkt;
1818 DCE2_SsnData *sd;
1819 DCE2_Roptions *ropts;
1820 DCE2_ByteTestData *bt_data;
1821 const uint8_t *start_ptr;
1822 uint16_t dsize;
1823 const uint8_t *bt_ptr;
1824 uint32_t pkt_value;
1825 DceRpcBoFlag byte_order;
1826 int ret = RULE_NOMATCH;
1827
1828 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1829 "Evaluating \"%s\" rule option.\n", DCE2_ROPT__BYTE_TEST));
1830
1831 if (*cursor == NULL)
1832 {
1833 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1834 "Cursor is NULL - not evaluating.\n"));
1835 return RULE_NOMATCH;
1836 }
1837
1838 if (!DCE2_RoptDoEval(p))
1839 return RULE_NOMATCH;
1840
1841 sd = (DCE2_SsnData *)_dpd.sessionAPI->get_application_data(p->stream_session, PP_DCE2);
1842 if ((sd == NULL) || DCE2_SsnNoInspect(sd))
1843 {
1844 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1845 "No session data - not evaluating.\n"));
1846 return RULE_NOMATCH;
1847 }
1848
1849 ropts = &sd->ropts;
1850
1851 if ((ropts->data_byte_order == DCE2_SENTINEL) ||
1852 (ropts->hdr_byte_order == DCE2_SENTINEL))
1853 {
1854 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1855 "Data byte order or header byte order not set "
1856 "in rule options - not evaluating.\n"));
1857 return RULE_NOMATCH;
1858 }
1859
1860 bt_data = (DCE2_ByteTestData *)data;
1861 if (bt_data == NULL)
1862 return RULE_NOMATCH;
1863
1864 if (_dpd.Is_DetectFlag(SF_FLAG_ALT_DETECT))
1865 {
1866 _dpd.GetAltDetect((uint8_t **)&start_ptr, &dsize);
1867 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
1868 "Using Alternative Detect buffer!\n"););
1869 }
1870 else
1871 {
1872 start_ptr = p->payload;
1873 dsize = p->payload_size;
1874 }
1875
1876 /* Make sure we don't read past the end of the payload or before
1877 * beginning of payload */
1878 if (bt_data->relative)
1879 {
1880 if ((bt_data->offset < 0) && (*cursor + bt_data->offset) < start_ptr)
1881 {
1882 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1883 "Offset is negative and puts cursor before beginning "
1884 "of payload - not evaluating.\n"));
1885 return RULE_NOMATCH;
1886 }
1887
1888 if ((*cursor + bt_data->offset + bt_data->num_bytes) > (start_ptr + dsize))
1889 {
1890 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1891 "Offset plus number of bytes to read puts cursor past "
1892 "end of payload - not evaluating.\n"));
1893 return RULE_NOMATCH;
1894 }
1895
1896 bt_ptr = *cursor + bt_data->offset;
1897 }
1898 else
1899 {
1900 if (bt_data->offset < 0)
1901 {
1902 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1903 "Offset is negative but is not relative - "
1904 "not evaluating.\n"));
1905 return RULE_NOMATCH;
1906 }
1907 else if ((start_ptr + bt_data->offset + bt_data->num_bytes) > (start_ptr + dsize))
1908 {
1909 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1910 "Offset plus number of bytes to read puts cursor past "
1911 "end of payload - not evaluating.\n"));
1912 return RULE_NOMATCH;
1913 }
1914
1915 bt_ptr = start_ptr + bt_data->offset;
1916 }
1917
1918 /* Determine which byte order to use */
1919 if (ropts->stub_data == NULL)
1920 {
1921 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1922 "Stub data is NULL. Setting byte order to that "
1923 "of the header.\n"));
1924 byte_order = (DceRpcBoFlag)ropts->hdr_byte_order;
1925 }
1926 else if (bt_ptr < ropts->stub_data)
1927 {
1928 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1929 "Reading data in the header. Setting byte order "
1930 "to that of the header.\n"));
1931 byte_order = (DceRpcBoFlag)ropts->hdr_byte_order;
1932 }
1933 else
1934 {
1935 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1936 "Reading data in the stub. Setting byte order "
1937 "to that of the stub data.\n"));
1938 byte_order = (DceRpcBoFlag)ropts->data_byte_order;
1939 }
1940
1941 /* Get the value */
1942 switch (bt_data->num_bytes)
1943 {
1944 case 1:
1945 pkt_value = *((uint8_t *)bt_ptr);
1946 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1947 "Got 1 byte: %u.\n", pkt_value));
1948 break;
1949 case 2:
1950 pkt_value = DceRpcNtohs((uint16_t *)bt_ptr, byte_order);
1951 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1952 "Got 2 bytes: %u.\n", pkt_value));
1953 break;
1954 case 4:
1955 pkt_value = DceRpcNtohl((uint32_t *)bt_ptr, byte_order);
1956 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1957 "Got 4 bytes: %u.\n", pkt_value));
1958 break;
1959 default:
1960 return RULE_NOMATCH;
1961 }
1962
1963 /* Invert the return value. */
1964 if (bt_data->invert)
1965 {
1966 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS, "Applying not flag.\n"));
1967 ret = RULE_MATCH;
1968 }
1969
1970 switch (bt_data->operator)
1971 {
1972 case DCE2_BT_OP__LT:
1973 if (pkt_value < bt_data->value)
1974 {
1975 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1976 "Packet value (%u) < Option value (%u).\n",
1977 pkt_value, bt_data->value));
1978 if (ret == RULE_MATCH)
1979 ret = RULE_NOMATCH;
1980 else
1981 ret = RULE_MATCH;
1982 }
1983
1984 break;
1985
1986 case DCE2_BT_OP__EQ:
1987 if (pkt_value == bt_data->value)
1988 {
1989 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
1990 "Packet value (%u) == Option value (%u).\n",
1991 pkt_value, bt_data->value));
1992 if (ret == RULE_MATCH)
1993 ret = RULE_NOMATCH;
1994 else
1995 ret = RULE_MATCH;
1996 }
1997
1998 break;
1999
2000 case DCE2_BT_OP__GT:
2001 if (pkt_value > bt_data->value)
2002 {
2003 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2004 "Packet value (%u) > Option value (%u).\n",
2005 pkt_value, bt_data->value));
2006 if (ret == RULE_MATCH)
2007 ret = RULE_NOMATCH;
2008 else
2009 ret = RULE_MATCH;
2010 }
2011
2012 break;
2013
2014 case DCE2_BT_OP__AND:
2015 if (pkt_value & bt_data->value)
2016 {
2017 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2018 "Packet value (%08x) & Option value (%08x).\n",
2019 pkt_value, bt_data->value));
2020 if (ret == RULE_MATCH)
2021 ret = RULE_NOMATCH;
2022 else
2023 ret = RULE_MATCH;
2024 }
2025
2026 break;
2027
2028 case DCE2_BT_OP__XOR:
2029 if (pkt_value ^ bt_data->value)
2030 {
2031 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2032 "Packet value (%08x) ^ Option value (%08x).\n",
2033 pkt_value, bt_data->value));
2034 if (ret == RULE_MATCH)
2035 ret = RULE_NOMATCH;
2036 else
2037 ret = RULE_MATCH;
2038 }
2039
2040 break;
2041
2042 default:
2043 return RULE_NOMATCH;
2044 }
2045
2046 #ifdef DEBUG_MSGS
2047 if (ret == RULE_MATCH)
2048 {
2049 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2050 "\"%s\" Match.\n", DCE2_ROPT__BYTE_TEST));
2051 }
2052 else
2053 {
2054 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2055 "\"%s\" Fail.\n", DCE2_ROPT__BYTE_TEST));
2056 }
2057 #endif
2058
2059 return ret;
2060 }
2061
2062 /********************************************************************
2063 * Function:
2064 *
2065 * Purpose:
2066 *
2067 * Arguments:
2068 *
2069 * Returns:
2070 *
2071 ********************************************************************/
DCE2_ByteJumpEval(void * pkt,const uint8_t ** cursor,void * data)2072 static int DCE2_ByteJumpEval(void *pkt, const uint8_t **cursor, void *data)
2073 {
2074 SFSnortPacket *p = (SFSnortPacket *)pkt;
2075 DCE2_SsnData *sd;
2076 DCE2_Roptions *ropts;
2077 DCE2_ByteJumpData *bj_data;
2078 const uint8_t *start_ptr;
2079 uint16_t dsize;
2080 const uint8_t *bj_ptr;
2081 uint32_t jmp_value;
2082 DceRpcBoFlag byte_order;
2083
2084 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2085 "Evaluating \"%s\" rule option.\n", DCE2_ROPT__BYTE_JUMP));
2086
2087 if (*cursor == NULL)
2088 {
2089 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2090 "Cursor is NULL - not evaluating.\n"));
2091 return RULE_NOMATCH;
2092 }
2093
2094 if (!DCE2_RoptDoEval(p))
2095 return RULE_NOMATCH;
2096
2097 sd = (DCE2_SsnData *)_dpd.sessionAPI->get_application_data(p->stream_session, PP_DCE2);
2098 if ((sd == NULL) || DCE2_SsnNoInspect(sd))
2099 {
2100 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2101 "No session data - not evaluating.\n"));
2102 return RULE_NOMATCH;
2103 }
2104
2105 ropts = &sd->ropts;
2106
2107 if ((ropts->data_byte_order == DCE2_SENTINEL) ||
2108 (ropts->hdr_byte_order == DCE2_SENTINEL))
2109 {
2110 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2111 "Data byte order or header byte order not set "
2112 "in rule options - not evaluating.\n"));
2113 return RULE_NOMATCH;
2114 }
2115
2116 bj_data = (DCE2_ByteJumpData *)data;
2117 if (bj_data == NULL)
2118 return RULE_NOMATCH;
2119
2120 if (_dpd.Is_DetectFlag(SF_FLAG_ALT_DETECT))
2121 {
2122 _dpd.GetAltDetect((uint8_t **)&start_ptr, &dsize);
2123 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
2124 "Using Alternative Detect buffer!\n"););
2125 }
2126 else
2127 {
2128 start_ptr = p->payload;
2129 dsize = p->payload_size;
2130 }
2131
2132 /* Make sure we don't read past the end of the payload or before
2133 * beginning of payload */
2134 if (bj_data->relative)
2135 {
2136 if ((bj_data->offset < 0) && (*cursor + bj_data->offset) < start_ptr)
2137 {
2138 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2139 "Offset is negative and puts cursor before beginning "
2140 "of payload - not evaluating.\n"));
2141 return RULE_NOMATCH;
2142 }
2143
2144 if ((*cursor + bj_data->offset + bj_data->num_bytes) > (start_ptr + dsize))
2145 {
2146 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2147 "Offset plus number of bytes to read puts cursor past "
2148 "end of payload - not evaluating.\n"));
2149 return RULE_NOMATCH;
2150 }
2151
2152 bj_ptr = *cursor + bj_data->offset;
2153 }
2154 else
2155 {
2156 if (bj_data->offset < 0)
2157 {
2158 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2159 "Offset is negative but is not relative - "
2160 "not evaluating.\n"));
2161 return RULE_NOMATCH;
2162 }
2163 else if ((start_ptr + bj_data->offset + bj_data->num_bytes) > (start_ptr + dsize))
2164 {
2165 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2166 "Offset plus number of bytes to read puts cursor past "
2167 "end of payload - not evaluating.\n"));
2168 return RULE_NOMATCH;
2169 }
2170
2171 bj_ptr = start_ptr + bj_data->offset;
2172 }
2173
2174 /* Determine which byte order to use */
2175 if (ropts->stub_data == NULL)
2176 {
2177 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS, "Stub data is NULL. "
2178 "Setting byte order to that of the header.\n"));
2179 byte_order = (DceRpcBoFlag)ropts->hdr_byte_order;
2180 }
2181 else if (bj_ptr < ropts->stub_data)
2182 {
2183 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2184 "Reading data in the header. Setting byte order "
2185 "to that of the header.\n"));
2186 byte_order = (DceRpcBoFlag)ropts->hdr_byte_order;
2187 }
2188 else
2189 {
2190 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2191 "Reading data in the stub. Setting byte order "
2192 "to that of the stub data.\n"));
2193 byte_order = (DceRpcBoFlag)ropts->data_byte_order;
2194 }
2195
2196 /* Get the value */
2197 switch (bj_data->num_bytes)
2198 {
2199 case 1:
2200 jmp_value = *((uint8_t *)bj_ptr);
2201 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2202 "Got 1 byte: %u.\n", jmp_value));
2203 break;
2204 case 2:
2205 jmp_value = DceRpcNtohs((uint16_t *)bj_ptr, byte_order);
2206 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2207 "Got 2 bytes: %u.\n", jmp_value));
2208 break;
2209 case 4:
2210 jmp_value = DceRpcNtohl((uint32_t *)bj_ptr, byte_order);
2211 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2212 "Got 4 bytes: %u.\n", jmp_value));
2213 break;
2214 default:
2215 return 0;
2216 }
2217
2218 if (bj_data->multiplier != DCE2_SENTINEL)
2219 {
2220 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2221 "Applying multiplier: %u * %u = %u.\n",
2222 jmp_value, bj_data->multiplier,
2223 jmp_value * bj_data->multiplier));
2224
2225 jmp_value *= bj_data->multiplier;
2226 }
2227
2228 if (bj_data->align && (jmp_value & 3))
2229 {
2230 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2231 "Aligning to 4 byte boundary: %u => %u.\n",
2232 jmp_value, jmp_value + (4 - (jmp_value & 3))));
2233
2234 jmp_value += (4 - (jmp_value & 3));
2235 }
2236
2237 bj_ptr += bj_data->num_bytes + jmp_value + bj_data->post_offset;
2238 if ((bj_ptr < start_ptr) || (bj_ptr >= (start_ptr + dsize)))
2239 {
2240 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2241 "\"%s\" Fail. Jump puts us past end of payload.\n",
2242 DCE2_ROPT__BYTE_JUMP));
2243 return RULE_NOMATCH;
2244 }
2245
2246 *cursor = bj_ptr;
2247
2248 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2249 "\"%s\" Match.\n", DCE2_ROPT__BYTE_JUMP));
2250
2251 return RULE_MATCH;
2252 }
2253
2254 /********************************************************************
2255 * Function:
2256 *
2257 * Purpose:
2258 *
2259 * Arguments:
2260 *
2261 * Returns:
2262 *
2263 ********************************************************************/
DCE2_RoptDoEval(SFSnortPacket * p)2264 static inline int DCE2_RoptDoEval(SFSnortPacket *p)
2265 {
2266 if ((p->payload_size == 0) ||
2267 (p->stream_session == NULL) ||
2268 (!IsTCP(p) && !IsUDP(p)))
2269 {
2270
2271 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS, "No payload or no "
2272 "session pointer or not TCP or UDP - not evaluating.\n"));
2273 return 0;
2274 }
2275
2276 return 1;
2277 }
2278
2279 /********************************************************************
2280 * Function:
2281 *
2282 * Purpose:
2283 *
2284 * Arguments:
2285 *
2286 * Returns:
2287 *
2288 ********************************************************************/
DCE2_IfaceCleanup(void * data)2289 static void DCE2_IfaceCleanup(void *data)
2290 {
2291 if (data == NULL)
2292 return;
2293
2294 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MEMORY,
2295 "Cleaning Iface data: %u bytes.\n", sizeof(DCE2_IfaceData)));
2296
2297 DCE2_Free(data, sizeof(DCE2_IfaceData), DCE2_MEM_TYPE__ROPTION);
2298 }
2299
2300 /********************************************************************
2301 * Function:
2302 *
2303 * Purpose:
2304 *
2305 * Arguments:
2306 *
2307 * Returns:
2308 *
2309 ********************************************************************/
DCE2_OpnumCleanup(void * data)2310 static void DCE2_OpnumCleanup(void *data)
2311 {
2312 DCE2_OpnumData *odata = (DCE2_OpnumData *)data;
2313
2314 if (data == NULL)
2315 return;
2316
2317 switch (odata->type)
2318 {
2319 case DCE2_OPNUM_TYPE__SINGLE:
2320 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MEMORY,
2321 "Cleaning Single opnum data: %u bytes.\n",
2322 sizeof(DCE2_OpnumSingle)));
2323
2324 DCE2_Free((void *)odata, sizeof(DCE2_OpnumSingle), DCE2_MEM_TYPE__ROPTION);
2325
2326 break;
2327
2328 case DCE2_OPNUM_TYPE__MULTIPLE:
2329 {
2330 DCE2_OpnumMultiple *omult = (DCE2_OpnumMultiple *)odata;
2331
2332 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MEMORY,
2333 "Cleaning Multiple opnum data: %u bytes.\n",
2334 sizeof(DCE2_OpnumMultiple) + omult->mask_size));
2335
2336 if (omult->mask != NULL)
2337 DCE2_Free((void *)omult->mask, omult->mask_size, DCE2_MEM_TYPE__ROPTION);
2338
2339 DCE2_Free((void *)omult, sizeof(DCE2_OpnumMultiple), DCE2_MEM_TYPE__ROPTION);
2340 }
2341
2342 break;
2343
2344 default:
2345 break;
2346 }
2347 }
2348
2349 /********************************************************************
2350 * Function:
2351 *
2352 * Purpose:
2353 *
2354 * Arguments:
2355 *
2356 * Returns:
2357 *
2358 ********************************************************************/
DCE2_ByteTestCleanup(void * data)2359 static void DCE2_ByteTestCleanup(void *data)
2360 {
2361 if (data == NULL)
2362 return;
2363
2364 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MEMORY,
2365 "Cleaning ByteTest data: %u bytes.\n",
2366 sizeof(DCE2_ByteTestData)));
2367
2368 DCE2_Free(data, sizeof(DCE2_ByteTestData), DCE2_MEM_TYPE__ROPTION);
2369 }
2370
2371 /********************************************************************
2372 * Function:
2373 *
2374 * Purpose:
2375 *
2376 * Arguments:
2377 *
2378 * Returns:
2379 *
2380 ********************************************************************/
DCE2_ByteJumpCleanup(void * data)2381 static void DCE2_ByteJumpCleanup(void *data)
2382 {
2383 if (data == NULL)
2384 return;
2385
2386 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__MEMORY,
2387 "Cleaning ByteJump data: %u bytes.\n",
2388 sizeof(DCE2_ByteJumpData)));
2389
2390 DCE2_Free(data, sizeof(DCE2_ByteJumpData), DCE2_MEM_TYPE__ROPTION);
2391 }
2392
2393 /********************************************************************
2394 * Function:
2395 *
2396 * Purpose:
2397 *
2398 * Arguments:
2399 *
2400 * Returns:
2401 *
2402 ********************************************************************/
DCE2_IfaceHash(void * data)2403 static uint32_t DCE2_IfaceHash(void *data)
2404 {
2405 uint32_t a, b, c;
2406 DCE2_IfaceData *iface_data = (DCE2_IfaceData *)data;
2407
2408 if (iface_data == NULL)
2409 return 0;
2410
2411 a = iface_data->iface.time_low;
2412 b = (iface_data->iface.time_mid << 16) | (iface_data->iface.time_high_and_version);
2413 c = (iface_data->iface.clock_seq_and_reserved << 24) |
2414 (iface_data->iface.clock_seq_low << 16) |
2415 (iface_data->iface.node[0] << 8) |
2416 (iface_data->iface.node[1]);
2417
2418 mix(a, b, c);
2419
2420 a += (iface_data->iface.node[2] << 24) |
2421 (iface_data->iface.node[3] << 16) |
2422 (iface_data->iface.node[4] << 8) |
2423 (iface_data->iface.node[5]);
2424 b += iface_data->iface_vers;
2425 c += iface_data->iface_vers_maj;
2426
2427 mix(a, b, c);
2428
2429 a += iface_data->iface_vers_min;
2430 b += iface_data->operator;
2431 c += iface_data->any_frag;
2432
2433 final(a, b, c);
2434
2435 return c;
2436 }
2437
2438 /********************************************************************
2439 * Function:
2440 *
2441 * Purpose:
2442 *
2443 * Arguments:
2444 *
2445 * Returns:
2446 *
2447 ********************************************************************/
DCE2_OpnumHash(void * data)2448 static uint32_t DCE2_OpnumHash(void *data)
2449 {
2450 uint32_t a = 0, b = 0, c = 0;
2451 DCE2_OpnumData *odata = (DCE2_OpnumData *)data;
2452
2453 if (odata == NULL)
2454 return 0;
2455
2456 switch (odata->type)
2457 {
2458 case DCE2_OPNUM_TYPE__SINGLE:
2459 {
2460 DCE2_OpnumSingle *osingle = (DCE2_OpnumSingle *)odata;
2461
2462 a = odata->type;
2463 b = osingle->opnum;
2464 c = 10;
2465
2466 final(a, b, c);
2467 }
2468
2469 break;
2470
2471 case DCE2_OPNUM_TYPE__MULTIPLE:
2472 {
2473 DCE2_OpnumMultiple *omult = (DCE2_OpnumMultiple *)odata;
2474 unsigned int i;
2475
2476 a = odata->type;
2477 b = omult->mask_size;
2478 c = 0;
2479
2480 /* Don't care about potential wrapping if it exists */
2481 for (i = 0; i < omult->mask_size; i++)
2482 c += omult->mask[i];
2483
2484 mix(a, b, c);
2485
2486 a = omult->opnum_lo;
2487 b = omult->opnum_hi;
2488 c = 10;
2489
2490 final(a, b, c);
2491 }
2492
2493 break;
2494
2495 default:
2496 DCE2_Die("%s(%d) Invalid opnum type: %d",
2497 __FILE__, __LINE__, odata->type);
2498 break;
2499 }
2500
2501 return c;
2502 }
2503
2504 /********************************************************************
2505 * Function:
2506 *
2507 * Purpose:
2508 *
2509 * Arguments:
2510 *
2511 * Returns:
2512 *
2513 ********************************************************************/
DCE2_ByteTestHash(void * data)2514 static uint32_t DCE2_ByteTestHash(void *data)
2515 {
2516 uint32_t a, b, c;
2517 DCE2_ByteTestData *bt_data = (DCE2_ByteTestData *)data;
2518
2519 if (bt_data == NULL)
2520 return 0;
2521
2522 a = bt_data->num_bytes;
2523 b = bt_data->value;
2524 c = bt_data->invert;
2525
2526 mix(a, b, c);
2527
2528 a += bt_data->operator;
2529 b += bt_data->offset;
2530 c += bt_data->relative;
2531
2532 final(a, b, c);
2533
2534 return c;
2535 }
2536
2537 /********************************************************************
2538 * Function:
2539 *
2540 * Purpose:
2541 *
2542 * Arguments:
2543 *
2544 * Returns:
2545 *
2546 ********************************************************************/
DCE2_ByteJumpHash(void * data)2547 static uint32_t DCE2_ByteJumpHash(void *data)
2548 {
2549 uint32_t a, b, c;
2550 DCE2_ByteJumpData *bj_data = (DCE2_ByteJumpData *)data;
2551
2552 if (bj_data == NULL)
2553 return 0;
2554
2555 a = bj_data->num_bytes;
2556 b = bj_data->offset;
2557 c = bj_data->relative;
2558
2559 mix(a, b, c);
2560
2561 a += bj_data->multiplier;
2562 b += bj_data->align;
2563
2564 final(a, b, c);
2565
2566 return c;
2567 }
2568
2569 /********************************************************************
2570 * Function:
2571 *
2572 * Purpose:
2573 *
2574 * Arguments:
2575 *
2576 * Returns:
2577 *
2578 ********************************************************************/
DCE2_IfaceKeyCompare(void * l,void * r)2579 static int DCE2_IfaceKeyCompare(void *l, void *r)
2580 {
2581 DCE2_IfaceData *left = (DCE2_IfaceData *)l;
2582 DCE2_IfaceData *right = (DCE2_IfaceData *)r;
2583
2584 if ((left == NULL) || (right == NULL))
2585 return PREPROC_OPT_NOT_EQUAL;
2586
2587 if ((DCE2_UuidCompare(&left->iface, &right->iface) == 0) &&
2588 (left->iface_vers == right->iface_vers) &&
2589 (left->iface_vers_maj == right->iface_vers_maj) &&
2590 (left->iface_vers_min == right->iface_vers_min) &&
2591 (left->operator == right->operator) &&
2592 (left->any_frag == right->any_frag))
2593 {
2594 return PREPROC_OPT_EQUAL;
2595 }
2596
2597 return PREPROC_OPT_NOT_EQUAL;
2598 }
2599
2600 /********************************************************************
2601 * Function:
2602 *
2603 * Purpose:
2604 *
2605 * Arguments:
2606 *
2607 * Returns:
2608 *
2609 ********************************************************************/
DCE2_OpnumKeyCompare(void * l,void * r)2610 static int DCE2_OpnumKeyCompare(void *l, void *r)
2611 {
2612 DCE2_OpnumData *left = (DCE2_OpnumData *)l;
2613 DCE2_OpnumData *right = (DCE2_OpnumData *)r;
2614
2615 if ((left == NULL) || (right == NULL))
2616 return PREPROC_OPT_NOT_EQUAL;
2617
2618 if (left->type != right->type)
2619 return PREPROC_OPT_NOT_EQUAL;
2620
2621 switch (left->type)
2622 {
2623 case DCE2_OPNUM_TYPE__SINGLE:
2624 {
2625 DCE2_OpnumSingle *lsingle = (DCE2_OpnumSingle *)left;
2626 DCE2_OpnumSingle *rsingle = (DCE2_OpnumSingle *)right;
2627
2628 if (lsingle->opnum != rsingle->opnum)
2629 return PREPROC_OPT_NOT_EQUAL;
2630
2631 }
2632
2633 break;
2634
2635 case DCE2_OPNUM_TYPE__MULTIPLE:
2636 {
2637 unsigned int i;
2638 DCE2_OpnumMultiple *lmult = (DCE2_OpnumMultiple *)left;
2639 DCE2_OpnumMultiple *rmult = (DCE2_OpnumMultiple *)right;
2640
2641 if ((lmult->mask_size != rmult->mask_size) ||
2642 (lmult->opnum_lo != rmult->opnum_lo) ||
2643 (lmult->opnum_hi != rmult->opnum_hi))
2644 {
2645 return PREPROC_OPT_NOT_EQUAL;
2646 }
2647
2648 for (i = 0; i < lmult->mask_size; i++)
2649 {
2650 if (lmult->mask[i] != rmult->mask[i])
2651 return PREPROC_OPT_NOT_EQUAL;
2652 }
2653 }
2654
2655 break;
2656
2657 default:
2658 DCE2_Die("%s(%d) Invalid opnum type: %d",
2659 __FILE__, __LINE__, left->type);
2660 break;
2661 }
2662
2663 return PREPROC_OPT_EQUAL;
2664 }
2665
2666 /********************************************************************
2667 * Function:
2668 *
2669 * Purpose:
2670 *
2671 * Arguments:
2672 *
2673 * Returns:
2674 *
2675 ********************************************************************/
DCE2_ByteTestKeyCompare(void * l,void * r)2676 static int DCE2_ByteTestKeyCompare(void *l, void *r)
2677 {
2678 DCE2_ByteTestData *left = (DCE2_ByteTestData *)l;
2679 DCE2_ByteTestData *right = (DCE2_ByteTestData *)r;
2680
2681 if ((left == NULL) || (right == NULL))
2682 return PREPROC_OPT_NOT_EQUAL;
2683
2684 if ((left->num_bytes == right->num_bytes) &&
2685 (left->value == right->value) &&
2686 (left->invert == right->invert) &&
2687 (left->operator == right->operator) &&
2688 (left->offset == right->offset) &&
2689 (left->relative == right->relative))
2690 {
2691 return PREPROC_OPT_EQUAL;
2692 }
2693
2694 return PREPROC_OPT_NOT_EQUAL;
2695 }
2696
2697 /********************************************************************
2698 * Function:
2699 *
2700 * Purpose:
2701 *
2702 * Arguments:
2703 *
2704 * Returns:
2705 *
2706 ********************************************************************/
DCE2_ByteJumpKeyCompare(void * l,void * r)2707 static int DCE2_ByteJumpKeyCompare(void *l, void *r)
2708 {
2709 DCE2_ByteJumpData *left = (DCE2_ByteJumpData *)l;
2710 DCE2_ByteJumpData *right = (DCE2_ByteJumpData *)r;
2711
2712 if ((left == NULL) || (right == NULL))
2713 return PREPROC_OPT_NOT_EQUAL;
2714
2715 if ((left->num_bytes == right->num_bytes) &&
2716 (left->offset == right->offset) &&
2717 (left->relative == right->relative) &&
2718 (left->multiplier == right->multiplier) &&
2719 (left->align == right->align))
2720 {
2721 return PREPROC_OPT_EQUAL;
2722 }
2723
2724 return PREPROC_OPT_NOT_EQUAL;
2725 }
2726
2727 /********************************************************************
2728 * Function:
2729 *
2730 * Purpose:
2731 *
2732 * Arguments:
2733 *
2734 * Returns:
2735 *
2736 ********************************************************************/
DCE2_PrintRoptions(DCE2_Roptions * ropts)2737 void DCE2_PrintRoptions(DCE2_Roptions *ropts)
2738 {
2739 printf(" First frag: %s\n", ropts->first_frag == 1 ? "yes" : (ropts->first_frag == 0 ? "no" : "unset"));
2740 if (ropts->first_frag == DCE2_SENTINEL)
2741 {
2742 printf(" Iface: unset\n");
2743 printf(" Iface version: unset\n");
2744 }
2745 else
2746 {
2747 printf(" Iface: %s\n", DCE2_UuidToStr(&ropts->iface, DCERPC_BO_FLAG__NONE));
2748 printf(" Iface version: %u\n", ropts->iface_vers_maj);
2749 }
2750 if (ropts->opnum == DCE2_SENTINEL) printf(" Opnum: unset\n");
2751 else printf(" Opnum: %u\n", ropts->opnum);
2752 printf(" Header byte order: %s\n",
2753 ropts->hdr_byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN ? "little endian" :
2754 (ropts->hdr_byte_order == DCERPC_BO_FLAG__BIG_ENDIAN ? "big endian" : "unset"));
2755 printf(" Data byte order: %s\n",
2756 ropts->data_byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN ? "little endian" :
2757 (ropts->data_byte_order == DCERPC_BO_FLAG__BIG_ENDIAN ? "big endian" : "unset"));
2758 if (ropts->stub_data != NULL) printf(" Stub data: %p\n", ropts->stub_data);
2759 else printf(" Stub data: NULL\n");
2760 }
2761
2762 /********************************************************************
2763 * Function: DCE2_RoptError()
2764 *
2765 * Prints rule option error and dies.
2766 *
2767 * Arguments:
2768 * const char *
2769 * Format string
2770 * ...
2771 * Arguments to format string
2772 *
2773 * Returns: None
2774 *
2775 ********************************************************************/
DCE2_RoptError(const char * format,...)2776 static NORETURN void DCE2_RoptError(const char *format, ...)
2777 {
2778 char buf[1024];
2779 va_list ap;
2780
2781 va_start(ap, format);
2782 vsnprintf(buf, sizeof(buf), format, ap);
2783 va_end(ap);
2784
2785 buf[sizeof(buf) - 1] = '\0';
2786
2787 DCE2_Die("%s(%d): %s Please consult documentation.",
2788 *_dpd.config_file, *_dpd.config_line, buf);
2789 }
2790
2791
2792 /**********************************
2793 * Function: DCE2_GetByteOrder()
2794 *
2795 * Gets the byte order needed for a byte_test, byte_jump, or byte_extract.
2796 *
2797 * Arguments:
2798 * Packet *
2799 * packet being evaluated
2800 * int32_t
2801 * offset into the packet payload where the rule will be evaluated.
2802 * calling function is responsible for checking that the offset is in-bounds.
2803 *
2804 * Returns:
2805 * DCE2_SENTINEL (-1) if byte order not set, or otherwise not evaluating
2806 * BIG (0) if byte order is big-endian
2807 * LITTLE (1) if byte order is little-endian
2808 *
2809 **********************************/
2810 #define BIG 0
2811 #define LITTLE 1
DCE2_GetByteOrder(void * data,int32_t offset)2812 int DCE2_GetByteOrder(void *data, int32_t offset)
2813 {
2814 DCE2_SsnData *sd;
2815 DCE2_Roptions *ropts;
2816 DceRpcBoFlag byte_order;
2817 const uint8_t *data_ptr;
2818 SFSnortPacket *p = (SFSnortPacket *)data;
2819
2820 if (p == NULL)
2821 return -1;
2822
2823 sd = (DCE2_SsnData *)_dpd.sessionAPI->get_application_data(p->stream_session, PP_DCE2);
2824 if ((sd == NULL) || DCE2_SsnNoInspect(sd))
2825 {
2826 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2827 "No session data - not evaluating.\n"));
2828 return -1;
2829 }
2830
2831 ropts = &sd->ropts;
2832
2833 if ((ropts->data_byte_order == DCE2_SENTINEL) ||
2834 (ropts->hdr_byte_order == DCE2_SENTINEL))
2835 {
2836 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2837 "Data byte order or header byte order not set "
2838 "in rule options - not evaluating.\n"));
2839 return -1;
2840 }
2841
2842 /* Determine which byte order to use */
2843 data_ptr = p->payload + offset;
2844
2845 if (ropts->stub_data == NULL)
2846 {
2847 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS, "Stub data is NULL. "
2848 "Setting byte order to that of the header.\n"));
2849 byte_order = (DceRpcBoFlag)ropts->hdr_byte_order;
2850 }
2851 else if (data_ptr < ropts->stub_data)
2852 {
2853 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2854 "Reading data in the header. Setting byte order "
2855 "to that of the header.\n"));
2856 byte_order = (DceRpcBoFlag)ropts->hdr_byte_order;
2857 }
2858 else
2859 {
2860 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__ROPTIONS,
2861 "Reading data in the stub. Setting byte order "
2862 "to that of the stub data.\n"));
2863 byte_order = (DceRpcBoFlag)ropts->data_byte_order;
2864 }
2865
2866 /* Return ints, since this enum doesn't exist back in Snort-land. */
2867 if (byte_order == DCERPC_BO_FLAG__BIG_ENDIAN)
2868 return BIG;
2869 if (byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN)
2870 return LITTLE;
2871
2872 return -1;
2873 }
2874