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