suricata
detect-asn1.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file detect-asn1.c
20  *
21  * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
22  *
23  * Implements "asn1" keyword
24  */
25 
26 #include "suricata-common.h"
27 #include "debug.h"
28 #include "decode.h"
29 
30 #include "detect.h"
31 #include "detect-parse.h"
32 
33 #include "flow.h"
34 #include "detect-asn1.h"
35 
36 #include "util-unittest.h"
37 #include "util-unittest-helper.h"
38 #include "util-byte.h"
39 #include "util-debug.h"
40 #include "util-decode-asn1.h"
41 
42 /* delimiters for functions/arguments */
43 const char *ASN_DELIM = " \t,\n";
44 
45 static int DetectAsn1Match(DetectEngineThreadCtx *, Packet *,
46  const Signature *, const SigMatchCtx *);
47 static int DetectAsn1Setup (DetectEngineCtx *, Signature *, const char *);
48 static void DetectAsn1RegisterTests(void);
49 static void DetectAsn1Free(DetectEngineCtx *, void *);
50 
51 /**
52  * \brief Registration function for asn1
53  */
55 {
57  sigmatch_table[DETECT_ASN1].Match = DetectAsn1Match;
58  sigmatch_table[DETECT_ASN1].Setup = DetectAsn1Setup;
59  sigmatch_table[DETECT_ASN1].Free = DetectAsn1Free;
60  sigmatch_table[DETECT_ASN1].RegisterTests = DetectAsn1RegisterTests;
61 
62  return;
63 }
64 
65 /**
66  * \brief The main checks are done here
67  * This function implements the detection of the following options:
68  * - oversize_length
69  * - bitstring_overflow
70  * - double_overflow
71  * We can add more checks here easily since we have all the data of the
72  * node avaliable. If we need all the tree, we can just pass the
73  * ASN1 ctx as argument and perform the checks here
74  * \param node pointer to the Asn1Node to inspect
75  * \param ad pointer to the parsed options of the asn1 keyword (which hold the
76  * checks that we want to perform, and the lenght of oversize check
77  * \retval 1 if any of the options match, 0 if not
78  */
79 static uint8_t DetectAsn1Checks(Asn1Node *node, const DetectAsn1Data *ad)
80 {
81 
82  /* oversize_length will check if a node has a length greater than
83  * the user supplied length */
84  if (ad->flags & ASN1_OVERSIZE_LEN) {
85  if (node->len.len > ad->oversize_length
86  || node->data.len > ad->oversize_length)
87  return 1;
88  }
89 
90  /* 8.6 */
91  /* bitstring_overflow check a malformed option where the number of bits
92  * to ignore is greater than the length decoded (in bits) */
93  if (ad->flags & ASN1_BITSTRING_OVF) {
94  if (node->id.class_tag == ASN1_BER_CLASS_UNIV &&
97  {
98  if (node->len.len > 0 && node->data.ptr != NULL
99  && (node->len.len) * 8 < (uint8_t) *node->data.ptr)
100  {
101  return 1;
102  }
103  }
104  }
105 
106  /* double_overflow checks a known issue that affect the MSASN1 library
107  * when decoding double/real types. If the endoding is ASCII,
108  * and the buffer is greater than 256, the array is overflown
109  */
110  if (ad->flags & ASN1_DOUBLE_OVF) {
111  if (node->id.class_tag == ASN1_BER_CLASS_UNIV &&
112  node->id.tag_num == ASN1_UNITAG_REAL &&
114  {
115  if (node->len.len > 0 && node->data.ptr != NULL
116  && !((uint8_t) *node->data.ptr & 0xC0)
117  && (node->len.len > 256 || node->data.len > 256))
118  {
119  return 1;
120  }
121  }
122  }
123 
124  /* Good to know :) */
125  return 0;
126 }
127 
128 /**
129  * \brief This function will decode the asn1 data and inspect the resulting
130  * nodes to detect if any of the specified checks match this data
131  *
132  * \param t pointer to thread vars
133  * \param det_ctx pointer to the pattern matcher thread
134  * \param p pointer to the current packet
135  * \param m pointer to the sigmatch that we will cast into DetectAsn1Data
136  *
137  * \retval 0 no match
138  * \retval 1 match
139  */
140 static int DetectAsn1Match(DetectEngineThreadCtx *det_ctx, Packet *p,
141  const Signature *s, const SigMatchCtx *ctx)
142 {
143  uint8_t ret = 0;
144 
145  if (p->payload_len == 0) {
146  /* No error, parser done, no data in bounds to decode */
147  return 0;
148  }
149 
150  const DetectAsn1Data *ad = (const DetectAsn1Data *)ctx;
151  uint16_t offset;
152  if (ad->flags & ASN1_ABSOLUTE_OFFSET) {
153  offset = ad->absolute_offset;
154  } else if (ad->flags & ASN1_RELATIVE_OFFSET) {
155  // relative offset in regards to the last content match
156 
157  // This range check is done when relative_offset
158  BUG_ON(ad->relative_offset > UINT16_MAX || ad->relative_offset < -UINT16_MAX);
159 
160  int64_t tmp_offset = det_ctx->buffer_offset + ad->relative_offset;
161 
162  // check for under/overflow before downcasting
163  if (tmp_offset < 0 || tmp_offset > UINT16_MAX) {
164  return 0;
165  }
166 
167  offset = (uint16_t)tmp_offset;
168  } else {
169  offset = 0;
170  }
171 
172  if (offset >= p->payload_len) {
173  return 0;
174  }
175 
176  Asn1Ctx *ac = SCAsn1CtxNew();
177  if (ac == NULL)
178  return 0;
179 
181  SCAsn1Decode(ac, ac->cur_frame);
182 
183  /* Ok, now we have all the data. Let's check the nodes */
184 
185  if (ac->cur_frame > 0 || (ac->asn1_stack[0] != NULL && ac->asn1_stack[0]->id.ptr != NULL)) {
186  /* We spect at least one node */
187  uint16_t n_iter = 0;
188  ret = 0;
189 
190  for (; n_iter <= ac->cur_frame; n_iter++) {
191  Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
192 
193  if (node == NULL || node->id.ptr == NULL)
194  continue; /* Should not happen */
195 
196  ret = DetectAsn1Checks(node, ad);
197  /* Got a match? */
198  if (ret == 1)
199  break;
200  }
201  }
202 
203  SCAsn1CtxDestroy(ac);
204  return ret;
205 }
206 
207 /**
208  * \brief This function is used to parse asn1 options passed via asn1: keyword
209  *
210  * \param asn1str Pointer to the user provided asn1 options
211  *
212  * \retval fd pointer to DetectAsn1Data on success
213  * \retval NULL on failure
214  */
215 static DetectAsn1Data *DetectAsn1Parse(const char *instr)
216 {
217  DetectAsn1Data *fd = NULL;
218  char *tok = NULL;
219  uint32_t ov_len = 0;
220  uint16_t abs_off = 0;
221  int32_t rel_off = 0;
222  uint8_t flags = 0;
223  char *saveptr = NULL;
224 
225  char *asn1str = SCStrdup(instr);
226  if (asn1str == NULL)
227  return NULL;
228 
229  tok = strtok_r(asn1str, ASN_DELIM, &saveptr);
230  if (tok == NULL) {
231  SCLogError(SC_ERR_INVALID_VALUE, "Malformed asn1 argument: %s",
232  asn1str);
233  SCFree(asn1str);
234  return NULL;
235  }
236 
237  while (tok != NULL) {
238  if (strcasecmp("bitstring_overflow", tok) == 0) {
239  /* No arg here, just set the flag */
241  } else if (strcasecmp("double_overflow", tok) == 0) {
242  /* No arg here, just set the flag */
244  } else if (strcasecmp("oversize_length", tok) == 0) {
246  /* get the param */
247  tok = strtok_r(NULL, ASN_DELIM, &saveptr);
248  if ( tok == NULL ||
249  StringParseUint32(&ov_len, 10, 0, tok) <= 0)
250  {
251  SCLogError(SC_ERR_INVALID_VALUE, "Malformed value for "
252  "oversize_length: %s", tok);
253  goto error;
254  }
255  } else if (strcasecmp("absolute_offset", tok) == 0) {
257  /* get the param */
258  tok = strtok_r(NULL, ASN_DELIM, &saveptr);
259  if (tok == NULL ||
260  StringParseUint16(&abs_off, 10, 0, tok) <= 0)
261  {
262  SCLogError(SC_ERR_INVALID_VALUE, "Malformed value for "
263  "absolute_offset: %s", tok);
264  goto error;
265  }
266  } else if (strcasecmp("relative_offset",tok) == 0) {
268  /* get the param */
269  tok = strtok_r(NULL, ASN_DELIM, &saveptr);
270 
271  // Range check on uint16_t max as uint16_t is the type of the buffer
272  // the offset is relative to
273  if (tok == NULL ||
274  StringParseI32RangeCheck(&rel_off, 10, 0, tok, -UINT16_MAX, UINT16_MAX) <= 0)
275  {
276  SCLogError(SC_ERR_INVALID_VALUE, "Malformed value for "
277  "relative_offset: %s", tok);
278  goto error;
279  }
280  } else {
281  SCLogError(SC_ERR_INVALID_VALUE, "Malformed asn1 argument: %s",
282  asn1str);
283  goto error;
284  }
285  tok = strtok_r(NULL, ASN_DELIM, &saveptr);
286  }
287 
288  fd = SCMalloc(sizeof(DetectAsn1Data));
289  if (unlikely(fd == NULL)) {
290  goto error;
291  }
292  memset(fd, 0x00, sizeof(DetectAsn1Data));
293 
294  fd->flags = flags;
295  fd->oversize_length = ov_len; /* Length argument if needed */
296  fd->absolute_offset = abs_off; /* Length argument if needed */
297  fd->relative_offset = rel_off; /* Length argument if needed */
298  SCFree(asn1str);
299  return fd;
300 
301 error:
302  SCFree(asn1str);
303  return NULL;
304 }
305 
306 /**
307  * \brief this function is used to add the parsed asn1 data into
308  * the current signature
309  *
310  * \param de_ctx pointer to the Detection Engine Context
311  * \param s pointer to the Current Signature
312  * \param asn1str pointer to the user provided asn1 options
313  *
314  * \retval 0 on Success
315  * \retval -1 on Failure
316  */
317 static int DetectAsn1Setup(DetectEngineCtx *de_ctx, Signature *s, const char *asn1str)
318 {
319  DetectAsn1Data *ad = NULL;
320  SigMatch *sm = NULL;
321 
322  ad = DetectAsn1Parse(asn1str);
323  if (ad == NULL) goto error;
324 
325  /* Okay so far so good, lets get this into a SigMatch
326  * and put it in the Signature. */
327  sm = SigMatchAlloc();
328  if (sm == NULL)
329  goto error;
330 
331  sm->type = DETECT_ASN1;
332  sm->ctx = (SigMatchCtx *)ad;
333 
335 
336  return 0;
337 
338 error:
339  if (ad != NULL)
340  DetectAsn1Free(de_ctx, ad);
341  if (sm != NULL)
342  SCFree(sm);
343  return -1;
344 
345 }
346 
347 /**
348  * \brief this function will free memory associated with DetectAsn1Data
349  *
350  * \param ad pointer to DetectAsn1Data
351  */
352 static void DetectAsn1Free(DetectEngineCtx *de_ctx, void *ptr)
353 {
354  DetectAsn1Data *ad = (DetectAsn1Data *)ptr;
355  SCFree(ad);
356 }
357 
358 #ifdef UNITTESTS
359 
360 /**
361  * \test DetectAsn1TestParse01 check that we parse oversize_length correctly
362  */
363 static int DetectAsn1TestParse01(void)
364 {
365  int result = 0;
366  char str[] = "oversize_length 1024";
367  DetectAsn1Data *ad = NULL;
368 
369  ad = DetectAsn1Parse(str);
370  if (ad != NULL) {
371  if (ad->oversize_length == 1024 && (ad->flags & ASN1_OVERSIZE_LEN)) {
372  result = 1;
373  }
374  DetectAsn1Free(NULL, ad);
375  }
376 
377  return result;
378 }
379 
380 /**
381  * \test DetectAsn1TestParse02 check that we parse absolute_offset correctly
382  */
383 static int DetectAsn1TestParse02(void)
384 {
385  int result = 0;
386  DetectAsn1Data *ad = NULL;
387  char str[] = "absolute_offset 1024";
388 
389  ad = DetectAsn1Parse(str);
390  if (ad != NULL && ad->absolute_offset == 1024
391  && (ad->flags & ASN1_ABSOLUTE_OFFSET)) {
392  DetectAsn1Free(NULL, ad);
393  result = 1;
394  }
395 
396  return result;
397 }
398 
399 /**
400  * \test DetectAsn1TestParse03 check that we parse relative_offset correctly
401  */
402 static int DetectAsn1TestParse03(void)
403 {
404  int result = 0;
405  char str[] = "relative_offset 1024";
406  DetectAsn1Data *ad = NULL;
407 
408  ad = DetectAsn1Parse(str);
409  if (ad != NULL && ad->relative_offset == 1024
410  && (ad->flags & ASN1_RELATIVE_OFFSET)) {
411  DetectAsn1Free(NULL, ad);
412  result = 1;
413  }
414 
415  return result;
416 }
417 
418 /**
419  * \test DetectAsn1TestParse04 check that we parse bitstring_overflow correctly
420  */
421 static int DetectAsn1TestParse04(void)
422 {
423  int result = 0;
424  char str[] = "bitstring_overflow";
425  DetectAsn1Data *ad = NULL;
426 
427  ad = DetectAsn1Parse(str);
428  if (ad != NULL && (ad->flags & ASN1_BITSTRING_OVF)) {
429  DetectAsn1Free(NULL, ad);
430  result = 1;
431  }
432 
433  return result;
434 }
435 
436 /**
437  * \test DetectAsn1TestParse05 check that we parse double_overflow correctly
438  */
439 static int DetectAsn1TestParse05(void)
440 {
441  int result = 0;
442  char str[] = "double_overflow";
443  DetectAsn1Data *ad = NULL;
444 
445  ad = DetectAsn1Parse(str);
446  if (ad != NULL && (ad->flags & ASN1_DOUBLE_OVF)) {
447  DetectAsn1Free(NULL, ad);
448  result = 1;
449  }
450 
451  return result;
452 }
453 
454 /**
455  * \test DetectAsn1TestParse06 check that we fail if a needed arg is not given
456  */
457 static int DetectAsn1TestParse06(void)
458 {
459  int result = 1;
460  char str[] = "absolute_offset";
461  DetectAsn1Data *ad = NULL;
462 
463  ad = DetectAsn1Parse(str);
464  if (ad != NULL) {
465  DetectAsn1Free(NULL, ad);
466  result = 0;
467  }
468 
469  return result;
470 }
471 
472 /**
473  * \test DetectAsn1TestParse07 check that we fail if a needed arg is not given
474  */
475 static int DetectAsn1TestParse07(void)
476 {
477  int result = 1;
478  char str[] = "relative_offset";
479  DetectAsn1Data *ad = NULL;
480 
481  ad = DetectAsn1Parse(str);
482  if (ad != NULL) {
483  DetectAsn1Free(NULL, ad);
484  result = 0;
485  }
486 
487  return result;
488 }
489 
490 /**
491  * \test DetectAsn1TestParse08 check that we fail if a needed arg is not given
492  */
493 static int DetectAsn1TestParse08(void)
494 {
495  int result = 1;
496  char str[] = "oversize_length";
497  DetectAsn1Data *ad = NULL;
498 
499  ad = DetectAsn1Parse(str);
500  if (ad != NULL) {
501  DetectAsn1Free(NULL, ad);
502  result = 0;
503  }
504 
505  return result;
506 }
507 
508 
509 
510 /**
511  * \test DetectAsn1TestParse09 test that we break on invalid options
512  */
513 static int DetectAsn1TestParse09(void)
514 {
515  int result = 1;
516  DetectAsn1Data *fd = NULL;
517  char str[] = "oversize_length 1024, lalala 360";
518 
519  fd = DetectAsn1Parse(str);
520  if (fd != NULL) {
521  result = 0;
522  DetectAsn1Free(NULL, fd);
523  }
524 
525  return result;
526 }
527 
528 /**
529  * \test DetectAsn1TestParse10 test that we break with a empty string
530  */
531 static int DetectAsn1TestParse10(void)
532 {
533  int result = 1;
534  DetectAsn1Data *fd = NULL;
535  char str[] = "";
536 
537  fd = DetectAsn1Parse(str);
538  if (fd != NULL) {
539  result = 0;
540  DetectAsn1Free(NULL, fd);
541  }
542 
543  return result;
544 }
545 
546 /**
547  * \test DetectAsn1TestParse11 check for combinations of keywords
548  */
549 static int DetectAsn1TestParse11(void)
550 {
551  int result = 0;
552  char str[] = "oversize_length 1024, relative_offset 10";
553  DetectAsn1Data *ad = NULL;
554 
555  ad = DetectAsn1Parse(str);
556  if (ad != NULL && ad->oversize_length == 1024
557  && (ad->flags & ASN1_OVERSIZE_LEN)
558  && ad->relative_offset == 10
559  && (ad->flags & ASN1_RELATIVE_OFFSET))
560  {
561  DetectAsn1Free(NULL, ad);
562  result = 1;
563  }
564 
565  return result;
566 }
567 
568 /**
569  * \test DetectAsn1TestParse12 check for combinations of keywords
570  */
571 static int DetectAsn1TestParse12(void)
572 {
573  int result = 0;
574  char str[] = "oversize_length 1024 absolute_offset 10";
575  DetectAsn1Data *ad = NULL;
576 
577  ad = DetectAsn1Parse(str);
578  if (ad != NULL && ad->oversize_length == 1024
579  && (ad->flags & ASN1_OVERSIZE_LEN)
580  && ad->absolute_offset == 10
581  && (ad->flags & ASN1_ABSOLUTE_OFFSET))
582  {
583  DetectAsn1Free(NULL, ad);
584  result = 1;
585  }
586 
587  return result;
588 }
589 
590 /**
591  * \test DetectAsn1TestParse13 check for combinations of keywords
592  */
593 static int DetectAsn1TestParse13(void)
594 {
595  int result = 0;
596  char str[] = "oversize_length 1024 absolute_offset 10, bitstring_overflow";
597  DetectAsn1Data *ad = NULL;
598 
599  ad = DetectAsn1Parse(str);
600  if (ad != NULL && ad->oversize_length == 1024
601  && (ad->flags & ASN1_OVERSIZE_LEN)
602  && (ad->flags & ASN1_BITSTRING_OVF)
603  && ad->absolute_offset == 10
604  && (ad->flags & ASN1_ABSOLUTE_OFFSET))
605  {
606  DetectAsn1Free(NULL, ad);
607  result = 1;
608  }
609 
610  return result;
611 }
612 
613 /**
614  * \test DetectAsn1TestParse14 check for combinations of keywords
615  */
616 static int DetectAsn1TestParse14(void)
617 {
618  int result = 0;
619  char str[] = "double_overflow, oversize_length 1024 absolute_offset 10,"
620  " bitstring_overflow";
621  DetectAsn1Data *ad = NULL;
622 
623  ad = DetectAsn1Parse(str);
624  if (ad != NULL && ad->oversize_length == 1024
625  && (ad->flags & ASN1_OVERSIZE_LEN)
626  && (ad->flags & ASN1_BITSTRING_OVF)
627  && (ad->flags & ASN1_DOUBLE_OVF)
628  && ad->absolute_offset == 10
629  && (ad->flags & ASN1_ABSOLUTE_OFFSET))
630  {
631  DetectAsn1Free(NULL, ad);
632  result = 1;
633  }
634 
635  return result;
636 }
637 
638 /**
639  * \test DetectAsn1TestParse15 check for combinations of keywords
640  */
641 static int DetectAsn1TestParse15(void)
642 {
643  int result = 0;
644  char str[] = "double_overflow, oversize_length 1024 relative_offset 10,"
645  " bitstring_overflow";
646  DetectAsn1Data *ad = NULL;
647 
648  ad = DetectAsn1Parse(str);
649  if (ad != NULL && ad->oversize_length == 1024
650  && (ad->flags & ASN1_OVERSIZE_LEN)
651  && (ad->flags & ASN1_BITSTRING_OVF)
652  && (ad->flags & ASN1_DOUBLE_OVF)
653  && ad->relative_offset == 10
654  && (ad->flags & ASN1_RELATIVE_OFFSET))
655  {
656  DetectAsn1Free(NULL, ad);
657  result = 1;
658  }
659 
660  return result;
661 }
662 
663 /**
664  * \test DetectAsn1Test01 Ensure that the checks work when they should
665  */
666 static int DetectAsn1Test01(void)
667 {
668  /* Match if any of the nodes after offset 0 has greater length than 10 */
669  char str[] = "oversize_length 132 absolute_offset 0";
670 
671  DetectAsn1Data *ad = DetectAsn1Parse(str);
672  FAIL_IF_NULL(ad);
673  FAIL_IF_NOT(ad->oversize_length == 132);
675  FAIL_IF_NOT(ad->absolute_offset == 0);
677 
678  // Example from the specification X.690-0207 Appendix A.3
679  char buf[] = "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01"
680  "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
681  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
682  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
683  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
684  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111"
685  "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05"
686  "Jones""\xA0\x0A\x43\x08""19590717";
687 
688  Asn1Ctx *ac = SCAsn1CtxNew();
689  FAIL_IF_NULL(ac);
690 
691  uint16_t len = strlen((char *)buf)-1;
692 
693  SCAsn1CtxInit(ac, (uint8_t *)buf, len);
694  SCAsn1Decode(ac, ac->cur_frame);
695 
696  /* The first node has length 133, so it should match the oversize */
697  FAIL_IF_NOT(ac->cur_frame > 0);
698 
699  /* We spect at least one node */
700  uint16_t n_iter = 0;
701  int result = 0;
702  for (; n_iter <= ac->cur_frame; n_iter++) {
703  Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
704 
705  if (node == NULL || node->id.ptr == NULL)
706  continue; /* Should not happen */
707 
708  result = DetectAsn1Checks(node, ad);
709  /* Got a match? */
710  if (result == 1)
711  break;
712  }
713  FAIL_IF(result != 1);
714 
715  SCAsn1CtxDestroy(ac);
716  DetectAsn1Free(NULL, ad);
717 
718  PASS;
719 }
720 
721 /**
722  * \test DetectAsn1Test02 Ensure that the checks work when they should
723  */
724 static int DetectAsn1Test02(void)
725 {
726  int result = 0;
727  /* Match if any of the nodes has the bitstring overflow condition */
728  char str[] = "oversize_length 133, absolute_offset 0";
729  DetectAsn1Data *ad = NULL;
730 
731  ad = DetectAsn1Parse(str);
732  if (ad != NULL && ad->oversize_length == 133
733  && (ad->flags & ASN1_OVERSIZE_LEN)
734  && ad->absolute_offset == 0
735  && (ad->flags & ASN1_ABSOLUTE_OFFSET))
736  {
737  // Example from the specification X.690-0207 Appendix A.3
738  uint8_t *buf = (uint8_t*) "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01"
739  "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
740  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
741  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
742  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
743  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111"
744  "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05"
745  "Jones""\xA0\x0A\x43\x08""19590717";
746 
747  Asn1Ctx *ac = SCAsn1CtxNew();
748  if (ac == NULL)
749  return 0;
750 
751  uint16_t len = strlen((char *)buf)-1;
752 
753  SCAsn1CtxInit(ac, buf, len);
754 
755  SCAsn1Decode(ac, ac->cur_frame);
756 
757  /* The first node has length 133, so it should match the oversize */
758  if (ac->cur_frame > 0) {
759  /* We spect at least one node */
760  uint16_t n_iter = 0;
761 
762  for (; n_iter <= ac->cur_frame; n_iter++) {
763  Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
764 
765  if (node == NULL || node->id.ptr == NULL)
766  continue; /* Should not happen */
767 
768  result |= DetectAsn1Checks(node, ad);
769  }
770  }
771 
772  /* Got a match? We don't have nodes greater than 133, it should not */
773  if (result == 1) {
774  printf("Error, oversize_length should not match"
775  " any of the nodes: ");
776  result = 0;
777  } else {
778  result = 1;
779  }
780 
781  SCAsn1CtxDestroy(ac);
782  DetectAsn1Free(NULL, ad);
783 
784  }
785 
786  return result;
787 }
788 
789 /**
790  * \test DetectAsn1Test03 Ensure that the checks work when they should
791  */
792 static int DetectAsn1Test03(void)
793 {
794  int result = 0;
795  /* Match if any of the nodes after offset 0 has a bitstring overflow */
796  char str[] = "bitstring_overflow, absolute_offset 0";
797  DetectAsn1Data *ad = NULL;
798 
799  ad = DetectAsn1Parse(str);
800  if (ad != NULL && (ad->flags & ASN1_BITSTRING_OVF)
801  && ad->absolute_offset == 0
802  && (ad->flags & ASN1_ABSOLUTE_OFFSET))
803  {
804  /* Let's say tagnum bitstring, primitive, and as universal tag,
805  * and then length = 1 octet, but the next octet specify to ignore
806  * the last 256 bits... (let's match!) */
807  uint8_t *buf = (uint8_t*) "\x03\x01\xFF";
808 
809  Asn1Ctx *ac = SCAsn1CtxNew();
810  if (ac == NULL)
811  return 0;
812 
813  uint16_t len = 3;
814 
815  SCAsn1CtxInit(ac, buf, len);
816 
817  SCAsn1Decode(ac, ac->cur_frame);
818 
819  if (ac->cur_frame > 0 || ac->asn1_stack[0]->id.ptr != NULL) {
820  /* We spect at least one node */
821  uint16_t n_iter = 0;
822 
823  for (; n_iter <= ac->cur_frame; n_iter++) {
824  Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
825 
826  if (node == NULL || node->id.ptr == NULL)
827  continue; /* Should not happen */
828 
829  result = DetectAsn1Checks(node, ad);
830  /* Got a match? */
831  if (result == 1)
832  break;
833  }
834  }
835 
836  SCAsn1CtxDestroy(ac);
837  DetectAsn1Free(NULL, ad);
838 
839  }
840 
841  if (result == 0) {
842  printf("Error, bitstring_overflow should match the first node: ");
843  }
844 
845  return result;
846 }
847 
848 /**
849  * \test DetectAsn1Test04 Ensure that the checks work when they should
850  */
851 static int DetectAsn1Test04(void)
852 {
853  int result = 0;
854  /* Match if any of the nodes after offset 0 has a bitstring overflow */
855  char str[] = "bitstring_overflow, absolute_offset 0";
856  DetectAsn1Data *ad = NULL;
857 
858  ad = DetectAsn1Parse(str);
859  if (ad != NULL && (ad->flags & ASN1_BITSTRING_OVF)
860  && ad->absolute_offset == 0
861  && (ad->flags & ASN1_ABSOLUTE_OFFSET))
862  {
863  /* Let's say tagnum bitstring, primitive, and as universal tag,
864  * and then length = 1 octet, but the next octet specify to ignore
865  * the last 7 bits... (should not match) */
866  uint8_t *buf = (uint8_t*) "\x03\x01\x07";
867 
868  Asn1Ctx *ac = SCAsn1CtxNew();
869  if (ac == NULL)
870  return 0;
871 
872  uint16_t len = 3;
873 
874  SCAsn1CtxInit(ac, buf, len);
875 
876  SCAsn1Decode(ac, ac->cur_frame);
877 
878  if (ac->cur_frame > 0 || ac->asn1_stack[0]->id.ptr != NULL) {
879  /* We spect at least one node */
880  uint16_t n_iter = 0;
881 
882  for (; n_iter <= ac->cur_frame; n_iter++) {
883  Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
884 
885  if (node == NULL || node->id.ptr == NULL)
886  continue; /* Should not happen */
887 
888  result = DetectAsn1Checks(node, ad);
889  /* Got a match? */
890  if (result == 1)
891  break;
892  }
893  }
894 
895  SCAsn1CtxDestroy(ac);
896  DetectAsn1Free(NULL, ad);
897 
898  }
899 
900  if (result == 1) {
901  printf("Error, bitstring_overflog should not match any node: ");
902  result = 0;
903  } else {
904  result = 1;
905  }
906 
907  return result;
908 }
909 
910 /**
911  * \test DetectAsn1Test05 Ensure that the checks work when they should
912  */
913 static int DetectAsn1Test05(void)
914 {
915  int result = 0;
916  /* Match if any of the nodes after offset 0 has a double overflow */
917  char str[] = "double_overflow, absolute_offset 0";
918  DetectAsn1Data *ad = NULL;
919 
920  ad = DetectAsn1Parse(str);
921  if (ad != NULL && (ad->flags & ASN1_DOUBLE_OVF)
922  && ad->absolute_offset == 0
923  && (ad->flags & ASN1_ABSOLUTE_OFFSET))
924  {
925  /* Let's say tag num 9 (type Real), and encoded as ASCII, with length
926  * 257, then we must match */
927  uint8_t buf[261];
928  /* universal class, primitive type, tag_num = 9 (Data type Real) */
929  buf[0] = '\x09';
930  /* length, definite form, 2 octets */
931  buf[1] = '\x82';
932  /* length is the sum of the following octets (257): */
933  buf[2] = '\xFE';
934  buf[3] = '\x03';
935 
936  /* Fill the content of the number */
937  uint16_t i = 4;
938  for (; i < 257;i++)
939  buf[i] = '\x05';
940 
941  Asn1Ctx *ac = SCAsn1CtxNew();
942  if (ac == NULL)
943  return 0;
944 
945  uint16_t len = 261;
946 
947  SCAsn1CtxInit(ac, buf, len);
948 
949  SCAsn1Decode(ac, ac->cur_frame);
950 
951  if (ac->cur_frame > 0 || ac->asn1_stack[0]->id.ptr != NULL) {
952  /* We spect at least one node */
953  uint16_t n_iter = 0;
954 
955  for (; n_iter <= ac->cur_frame; n_iter++) {
956  Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
957 
958  if (node == NULL || node->id.ptr == NULL)
959  continue; /* Should not happen */
960 
961  result = DetectAsn1Checks(node, ad);
962  /* Got a match? */
963  if (result == 1)
964  break;
965  }
966  }
967 
968  SCAsn1CtxDestroy(ac);
969  DetectAsn1Free(NULL, ad);
970 
971  }
972 
973  if (result == 0) {
974  printf("Error, double_overflow should match the first node: ");
975  }
976 
977  return result;
978 }
979 
980 /**
981  * \test DetectAsn1Test06 Ensure that the checks work when they should
982  */
983 static int DetectAsn1Test06(void)
984 {
985  int result = 0;
986  /* Match if any of the nodes after offset 0 has a double overflow */
987  char str[] = "double_overflow, absolute_offset 0";
988  DetectAsn1Data *ad = NULL;
989 
990  ad = DetectAsn1Parse(str);
991  if (ad != NULL && (ad->flags & ASN1_DOUBLE_OVF)
992  && ad->absolute_offset == 0
993  && (ad->flags & ASN1_ABSOLUTE_OFFSET))
994  {
995  /* Let's say tag num 9 (type Real), and encoded as ASCII, with length
996  * 256, which fit in the buffer, so it should not match */
997  uint8_t buf[260];
998  /* universal class, primitive type, tag_num = 9 (Data type Real) */
999  buf[0] = '\x09';
1000  /* length, definite form, 2 octets */
1001  buf[1] = '\x82';
1002  /* length is the sum of the following octets (256): */
1003  buf[2] = '\xFE';
1004  buf[3] = '\x02';
1005 
1006  /* Fill the content of the number */
1007  uint16_t i = 4;
1008  for (; i < 256;i++)
1009  buf[i] = '\x05';
1010 
1011  Asn1Ctx *ac = SCAsn1CtxNew();
1012  if (ac == NULL)
1013  return 0;
1014 
1015  uint16_t len = 260;
1016 
1017  SCAsn1CtxInit(ac, buf, len);
1018 
1019  SCAsn1Decode(ac, ac->cur_frame);
1020 
1021  if (ac->cur_frame > 0 || ac->asn1_stack[0]->id.ptr != NULL) {
1022  /* We spect at least one node */
1023  uint16_t n_iter = 0;
1024 
1025  for (; n_iter <= ac->cur_frame; n_iter++) {
1026  Asn1Node *node = ASN1CTX_GET_NODE(ac, n_iter);
1027 
1028  if (node == NULL || node->id.ptr == NULL)
1029  continue; /* Should not happen */
1030 
1031  result = DetectAsn1Checks(node, ad);
1032  /* Got a match? */
1033  if (result == 1)
1034  break;
1035  }
1036  }
1037 
1038  SCAsn1CtxDestroy(ac);
1039  DetectAsn1Free(NULL, ad);
1040 
1041  }
1042 
1043  if (result == 1) {
1044  printf("Error, double_overflow should not match any node: ");
1045  result = 0 ;
1046  } else {
1047  result = 1;
1048  }
1049 
1050  return result;
1051 }
1052 
1053 /**
1054  * \test DetectAsn1TestReal01 Ensure that all works together
1055  */
1056 static int DetectAsn1TestReal01(void)
1057 {
1058  int result = 0;
1059  uint8_t *buf = (uint8_t *) "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01"
1060  "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1061  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1062  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1063  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1064  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111"
1065  "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05"
1066  "Jones""\xA0\x0A\x43\x08""19590717"
1067  "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01""P"
1068  "\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1069  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1070  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1071  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1072  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111""\x31\x1F"
1073  "\x61\x11\x1A\x05""Pablo""\x1A\x01""B""\x1A\x05""Jones"
1074  "\xA0\x0A\x43\x08""19590717";
1075 
1076  uint16_t buflen = strlen((char *)buf) - 1;
1077 
1078  /* Check the start with AA (this is to test the relative_offset keyword) */
1079  uint8_t *buf2 = (uint8_t *) "AA\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01"
1080  "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1081  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1082  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1083  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1084  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111"
1085  "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05"
1086  "Jones""\xA0\x0A\x43\x08""19590717"
1087  "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01""P"
1088  "\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1089  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1090  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1091  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1092  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111""\x31\x1F"
1093  "\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05""Jones"
1094  "\xA0\x0A\x43\x08""19590717";
1095 
1096  uint16_t buflen2 = strlen((char *)buf2) - 1;
1097 
1098  Packet *p[2];
1099 
1100  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1101  p[1] = UTHBuildPacket((uint8_t *)buf2, buflen2, IPPROTO_TCP);
1102 
1103  if (p[0] == NULL || p[1] == NULL)
1104  goto end;
1105 
1106  const char *sigs[3];
1107  sigs[0]= "alert ip any any -> any any (msg:\"Testing id 1\"; "
1108  "content:\"Pablo\"; asn1:absolute_offset 0, "
1109  "oversize_length 130; sid:1;)";
1110  sigs[1]= "alert ip any any -> any any (msg:\"Testing id 2\"; "
1111  "content:\"AA\"; asn1:relative_offset 0, "
1112  "oversize_length 130; sid:2;)";
1113  sigs[2]= "alert ip any any -> any any (msg:\"Testing id 3\"; "
1114  "content:\"lalala\"; asn1: oversize_length 2000; sid:3;)";
1115 
1116  uint32_t sid[3] = {1, 2, 3};
1117 
1118  uint32_t results[2][3] = {
1119  /* packet 0 match sid 1 */
1120  {1, 0, 0},
1121  /* packet 1 match sid 2 */
1122  {0, 1, 0}};
1123  /* None of the packets should match sid 3 */
1124 
1125  result = UTHGenericTest(p, 2, sigs, sid, (uint32_t *) results, 3);
1126 
1127  UTHFreePackets(p, 2);
1128 end:
1129  return result;
1130 }
1131 
1132 /**
1133  * \test DetectAsn1TestReal02 Ensure that all works together
1134  */
1135 static int DetectAsn1TestReal02(void)
1136 {
1137  int result = 0;
1138  uint8_t *buf = (uint8_t *) "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01"
1139  "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1140  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1141  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1142  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1143  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111"
1144  "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05"
1145  "Jones""\xA0\x0A\x43\x08""19590717"
1146  "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01""P"
1147  "\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1148  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1149  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1150  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1151  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111""\x31\x1F"
1152  "\x61\x11\x1A\x05""Pablo""\x1A\x01""B""\x1A\x05""Jones"
1153  "\xA0\x0A\x43\x08""19590717";
1154 
1155  uint16_t buflen = strlen((char *)buf) - 1;
1156 
1157  /* Check the start with AA (this is to test the relative_offset keyword) */
1158  uint8_t *buf2 = (uint8_t *) "AA\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01"
1159  "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1160  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1161  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1162  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1163  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111"
1164  "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05"
1165  "Jones""\xA0\x0A\x43\x08""19590717"
1166  "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01""P"
1167  "\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1168  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1169  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1170  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1171  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111""\x31\x1F"
1172  "\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05""Jones"
1173  "\xA0\x0A\x43\x08""19590717";
1174 
1175  uint16_t buflen2 = strlen((char *)buf2) - 1;
1176 
1177  Packet *p[2];
1178 
1179  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1180  p[1] = UTHBuildPacket((uint8_t *)buf2, buflen2, IPPROTO_TCP);
1181 
1182  if (p[0] == NULL || p[1] == NULL)
1183  goto end;
1184 
1185  const char *sigs[3];
1186  sigs[0]= "alert ip any any -> any any (msg:\"Testing id 1\"; "
1187  "content:\"Pablo\"; asn1:absolute_offset 0, "
1188  "oversize_length 140; sid:1;)";
1189  sigs[1]= "alert ip any any -> any any (msg:\"Testing id 2\"; "
1190  "content:\"AA\"; asn1:relative_offset 0, "
1191  "oversize_length 140; sid:2;)";
1192  sigs[2]= "alert ip any any -> any any (msg:\"Testing id 3\"; "
1193  "content:\"lalala\"; asn1: oversize_length 2000; sid:3;)";
1194 
1195  uint32_t sid[3] = {1, 2, 3};
1196 
1197  uint32_t results[2][3] = {
1198  {0, 0, 0},
1199  {0, 0, 0}};
1200  /* None of the packets should match */
1201 
1202  result = UTHGenericTest(p, 2, sigs, sid, (uint32_t *) results, 3);
1203 
1204  UTHFreePackets(p, 2);
1205 end:
1206  return result;
1207 }
1208 
1209 /**
1210  * \test DetectAsn1TestReal03 Ensure that all works together
1211  */
1212 static int DetectAsn1TestReal03(void)
1213 {
1214  int result = 0;
1215  uint8_t buf[261] = "";
1216  /* universal class, primitive type, tag_num = 9 (Data type Real) */
1217  buf[0] = '\x09';
1218  /* length, definite form, 2 octets */
1219  buf[1] = '\x82';
1220  /* length is the sum of the following octets (257): */
1221  buf[2] = '\xFE';
1222  buf[3] = '\x03';
1223 
1224  /* Fill the content of the number */
1225  uint16_t i = 4;
1226  for (; i < 257;i++)
1227  buf[i] = '\x05';
1228 
1229  uint16_t buflen = 261;
1230 
1231  /* Check the start with AA (this is to test the relative_offset keyword) */
1232  uint8_t *buf2 = (uint8_t *) "AA\x03\x01\xFF";
1233 
1234  uint16_t buflen2 = 5;
1235 
1236  Packet *p[2] = { NULL, NULL };
1237 
1238  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1239  p[1] = UTHBuildPacket((uint8_t *)buf2, buflen2, IPPROTO_TCP);
1240 
1241  if (p[0] == NULL || p[1] == NULL)
1242  goto end;
1243 
1244  const char *sigs[3];
1245  /* This should match the first packet */
1246  sigs[0]= "alert ip any any -> any any (msg:\"Testing id 1\"; "
1247  "asn1:absolute_offset 0, double_overflow; sid:1;)";
1248  /* This should match the second packet */
1249  sigs[1]= "alert ip any any -> any any (msg:\"Testing id 2\"; "
1250  "asn1:relative_offset 2, bitstring_overflow,"
1251  "oversize_length 140; sid:2;)";
1252  /* This should match no packet */
1253  sigs[2]= "alert ip any any -> any any (msg:\"Testing id 3\"; "
1254  "asn1: oversize_length 2000; sid:3;)";
1255 
1256  uint32_t sid[3] = {1, 2, 3};
1257 
1258  uint32_t results[2][3] = {{1, 0, 0},
1259  {0, 1, 0}};
1260 
1261  result = UTHGenericTest(p, 2, sigs, sid, (uint32_t *) results, 3);
1262 
1263  UTHFreePackets(p, 2);
1264 end:
1265  return result;
1266 }
1267 
1268 /**
1269  * \test DetectAsn1TestReal04 like the real test 02, but modified the
1270  * relative offset to check negative offset values, in this case
1271  * start decoding from -11 bytes respect the content match "John"
1272  */
1273 static int DetectAsn1TestReal04(void)
1274 {
1275  int result = 0;
1276  uint8_t *buf = (uint8_t *) "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01"
1277  "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1278  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1279  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1280  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1281  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111"
1282  "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05"
1283  "Jones""\xA0\x0A\x43\x08""19590717"
1284  "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01""P"
1285  "\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1286  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1287  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1288  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1289  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111""\x31\x1F"
1290  "\x61\x11\x1A\x05""Pablo""\x1A\x01""B""\x1A\x05""Jones"
1291  "\xA0\x0A\x43\x08""19590717";
1292 
1293  uint16_t buflen = strlen((char *)buf) - 1;
1294 
1295  /* Check the start with AA (this is to test the relative_offset keyword) */
1296  uint8_t *buf2 = (uint8_t *) "AA\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01"
1297  "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1298  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1299  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1300  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1301  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111"
1302  "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05"
1303  "Jones""\xA0\x0A\x43\x08""19590717"
1304  "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01""P"
1305  "\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1306  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1307  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1308  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1309  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111""\x31\x1F"
1310  "\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05""Jones"
1311  "\xA0\x0A\x43\x08""19590717";
1312 
1313  uint16_t buflen2 = strlen((char *)buf2) - 1;
1314 
1315  Packet *p[2];
1316 
1317  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1318  p[1] = UTHBuildPacket((uint8_t *)buf2, buflen2, IPPROTO_TCP);
1319 
1320  if (p[0] == NULL || p[1] == NULL)
1321  goto end;
1322 
1323  const char *sigs[3];
1324  sigs[0]= "alert ip any any -> any any (msg:\"Testing id 1\"; "
1325  "content:\"Pablo\"; asn1:absolute_offset 0, "
1326  "oversize_length 140; sid:1;)";
1327  sigs[1]= "alert ip any any -> any any (msg:\"Testing id 2\"; "
1328  "content:\"John\"; asn1:relative_offset -11, "
1329  "oversize_length 140; sid:2;)";
1330  sigs[2]= "alert ip any any -> any any (msg:\"Testing id 3\"; "
1331  "content:\"lalala\"; asn1: oversize_length 2000; sid:3;)";
1332 
1333  uint32_t sid[3] = {1, 2, 3};
1334 
1335  uint32_t results[2][3] = {
1336  {0, 0, 0},
1337  {0, 0, 0}};
1338  /* None of the packets should match */
1339 
1340  result = UTHGenericTest(p, 2, sigs, sid, (uint32_t *) results, 3);
1341 
1342  UTHFreePackets(p, 2);
1343 end:
1344  return result;
1345 }
1346 
1347 /**
1348  * \test DetectAsn1TestReal05 like the real test 04, but modified the
1349  * relative offset to check offset values which could read past the bounds
1350  * of the buffer
1351  */
1352 static int DetectAsn1TestReal05(void)
1353 {
1354  int result = 0;
1355  /* Check the start with AA (this is to test the relative_offset keyword) */
1356  uint8_t *buf = (uint8_t *) "AA\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01"
1357  "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1358  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1359  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1360  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1361  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111"
1362  "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05"
1363  "Jones""\xA0\x0A\x43\x08""19590717"
1364  "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01""P"
1365  "\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
1366  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
1367  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
1368  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
1369  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111""\x31\x1F"
1370  "\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05""Jones"
1371  "\xA0\x0A\x43\x08""19590717";
1372 
1373  uint16_t buflen = strlen((char *)buf) - 1;
1374 
1375  Packet *p[1];
1376 
1377  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1378 
1379  if (p[0] == NULL)
1380  goto end;
1381 
1382  const char *sigs[3];
1383  sigs[0]= "alert ip any any -> any any (msg:\"Testing id 1\"; "
1384  "content:\"John\"; asn1:relative_offset -100, "
1385  "oversize_length 132; sid:1;)";
1386  sigs[1]= "alert ip any any -> any any (msg:\"Testing id 2\"; "
1387  "content:\"John\"; asn1:relative_offset -11, "
1388  "oversize_length 132; sid:2;)";
1389  sigs[2]= "alert ip any any -> any any (msg:\"Testing id 3\"; "
1390  "content:\"John\"; asn1: relative_offset 5000, "
1391  "oversize_length 132; sid:3;)";
1392 
1393  uint32_t sid[3] = {1, 2, 3};
1394 
1395  // The second signature should match
1396  uint32_t results[1][3] = {{0, 1, 0}};
1397 
1398  result = UTHGenericTest(p, 1, sigs, sid, (uint32_t *) results, 3);
1399 
1400  UTHFreePackets(p, 1);
1401 end:
1402  return result;
1403 }
1404 
1405 #endif /* UNITTESTS */
1406 
1407 /**
1408  * \brief this function registers unit tests for DetectAsn1
1409  */
1410 static void DetectAsn1RegisterTests(void)
1411 {
1412 #ifdef UNITTESTS
1413  UtRegisterTest("DetectAsn1TestParse01", DetectAsn1TestParse01);
1414  UtRegisterTest("DetectAsn1TestParse02", DetectAsn1TestParse02);
1415  UtRegisterTest("DetectAsn1TestParse03", DetectAsn1TestParse03);
1416 
1417  UtRegisterTest("DetectAsn1TestParse04", DetectAsn1TestParse04);
1418  UtRegisterTest("DetectAsn1TestParse05", DetectAsn1TestParse05);
1419  UtRegisterTest("DetectAsn1TestParse06", DetectAsn1TestParse06);
1420 
1421  UtRegisterTest("DetectAsn1TestParse07", DetectAsn1TestParse07);
1422  UtRegisterTest("DetectAsn1TestParse08", DetectAsn1TestParse08);
1423  UtRegisterTest("DetectAsn1TestParse09", DetectAsn1TestParse09);
1424 
1425  UtRegisterTest("DetectAsn1TestParse10", DetectAsn1TestParse10);
1426  UtRegisterTest("DetectAsn1TestParse11", DetectAsn1TestParse11);
1427  UtRegisterTest("DetectAsn1TestParse12", DetectAsn1TestParse12);
1428  UtRegisterTest("DetectAsn1TestParse13", DetectAsn1TestParse13);
1429  UtRegisterTest("DetectAsn1TestParse14", DetectAsn1TestParse14);
1430  UtRegisterTest("DetectAsn1TestParse15", DetectAsn1TestParse15);
1431  UtRegisterTest("DetectAsn1Test01 - oversize_len", DetectAsn1Test01);
1432  UtRegisterTest("DetectAsn1Test02 - oversize_len", DetectAsn1Test02);
1433  UtRegisterTest("DetectAsn1Test03 - bitstring_ovf", DetectAsn1Test03);
1434  UtRegisterTest("DetectAsn1Test04 - bitstring_ovf", DetectAsn1Test04);
1435  UtRegisterTest("DetectAsn1Test05 - double_ovf", DetectAsn1Test05);
1436  UtRegisterTest("DetectAsn1Test06 - double_ovf", DetectAsn1Test06);
1437  UtRegisterTest("DetectAsn1TestReal01", DetectAsn1TestReal01);
1438  UtRegisterTest("DetectAsn1TestReal02", DetectAsn1TestReal02);
1439  UtRegisterTest("DetectAsn1TestReal03", DetectAsn1TestReal03);
1440  UtRegisterTest("DetectAsn1TestReal04", DetectAsn1TestReal04);
1441  UtRegisterTest("DetectAsn1TestReal05", DetectAsn1TestReal05);
1442 
1443 #endif /* UNITTESTS */
1444 }
util-byte.h
Asn1Node_::data
Asn1Data data
Definition: util-decode-asn1.h:165
len
uint8_t len
Definition: app-layer-dnp3.h:2
ASN1_UNITAG_BIT_STRING
#define ASN1_UNITAG_BIT_STRING
Definition: util-decode-asn1.h:95
DetectEngineThreadCtx_::buffer_offset
uint32_t buffer_offset
Definition: detect.h:1040
StringParseUint16
int StringParseUint16(uint16_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:336
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SCAsn1CtxInit
void SCAsn1CtxInit(Asn1Ctx *ac, const uint8_t *data, uint16_t length)
Initialize the data of the ASN1 parser ctx with the asn1 raw buffer.
Definition: util-decode-asn1.c:422
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SC_ERR_INVALID_VALUE
@ SC_ERR_INVALID_VALUE
Definition: util-error.h:160
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1200
SigTableElmt_::name
const char * name
Definition: detect.h:1209
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
Packet_::payload
uint8_t * payload
Definition: decode.h:543
Asn1Node_::id
Asn1Id id
Definition: util-decode-asn1.h:164
results
struct DetectRfbSecresult_ results[]
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:766
DetectAsn1Data_::absolute_offset
uint16_t absolute_offset
Definition: detect-asn1.h:39
Asn1Id_::class_tag
uint8_t class_tag
Definition: util-decode-asn1.h:149
ASN1_TAG_TYPE_PRIMITIVE
#define ASN1_TAG_TYPE_PRIMITIVE
Definition: util-decode-asn1.h:138
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:336
Asn1Ctx_::asn1_stack
Asn1Node ** asn1_stack
Definition: util-decode-asn1.h:178
SCAsn1CtxNew
Asn1Ctx * SCAsn1CtxNew(void)
Create a new ASN1 Parsing context.
Definition: util-decode-asn1.c:346
ASN1_ABSOLUTE_OFFSET
#define ASN1_ABSOLUTE_OFFSET
Definition: detect-asn1.h:33
ASN1_OVERSIZE_LEN
#define ASN1_OVERSIZE_LEN
Definition: detect-asn1.h:32
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1195
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:544
Asn1Node_
Definition: util-decode-asn1.h:160
util-unittest.h
DETECT_ASN1
@ DETECT_ASN1
Definition: detect-engine-register.h:176
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
detect-asn1.h
ASN1_UNITAG_REAL
#define ASN1_UNITAG_REAL
Definition: util-decode-asn1.h:101
DetectAsn1Register
void DetectAsn1Register(void)
Registration function for asn1.
Definition: detect-asn1.c:54
decode.h
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1009
ASN1_RELATIVE_OFFSET
#define ASN1_RELATIVE_OFFSET
Definition: detect-asn1.h:34
Asn1Id_::tag_num
uint32_t tag_num
Definition: util-decode-asn1.h:151
detect.h
Asn1Data_::ptr
const uint8_t * ptr
Definition: util-decode-asn1.h:155
Asn1Ctx_
Definition: util-decode-asn1.h:169
Asn1Ctx_::cur_frame
uint16_t cur_frame
Definition: util-decode-asn1.h:176
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:89
ASN1_BER_CLASS_UNIV
#define ASN1_BER_CLASS_UNIV
Definition: util-decode-asn1.h:46
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:322
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:282
DetectAsn1Data_::relative_offset
int32_t relative_offset
Definition: detect-asn1.h:40
Packet_
Definition: decode.h:411
Asn1Node_::len
Asn1Len len
Definition: util-decode-asn1.h:163
DetectAsn1Data_::oversize_length
uint32_t oversize_length
Definition: detect-asn1.h:38
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1178
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:235
SigMatch_::type
uint8_t type
Definition: detect.h:320
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:314
util-decode-asn1.h
StringParseUint32
int StringParseUint32(uint32_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:313
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
Asn1Id_::ptr
const uint8_t * ptr
Definition: util-decode-asn1.h:148
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:73
SCAsn1CtxDestroy
void SCAsn1CtxDestroy(Asn1Ctx *ac)
Destroy an ASN1 Parsing context.
Definition: util-decode-asn1.c:371
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
Asn1Len_::len
uint32_t len
Definition: util-decode-asn1.h:143
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
DetectAsn1Data_
Definition: detect-asn1.h:36
UTHGenericTest
int UTHGenericTest(Packet **pkt, int numpkts, const char *sigs[], uint32_t sids[], uint32_t *results, int numsigs)
UTHGenericTest: function that perfom a generic check taking care of as maximum common unittest elemen...
Definition: util-unittest-helper.c:603
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:273
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Asn1Id_::tag_type
uint8_t tag_type
Definition: util-decode-asn1.h:150
detect-parse.h
Asn1Data_::len
uint32_t len
Definition: util-decode-asn1.h:156
Signature_
Signature container.
Definition: detect.h:527
SigMatch_
a single match condition for a signature
Definition: detect.h:319
ASN1_DOUBLE_OVF
#define ASN1_DOUBLE_OVF
Definition: detect-asn1.h:31
SCAsn1Decode
uint8_t SCAsn1Decode(Asn1Ctx *ac, uint16_t node_id)
Decode the nodes/frames located at certain position/level.
Definition: util-decode-asn1.c:439
ASN_DELIM
const char * ASN_DELIM
Definition: detect-asn1.c:43
flow.h
ASN1CTX_GET_NODE
#define ASN1CTX_GET_NODE(ac, node)
Definition: util-decode-asn1.h:89
DetectAsn1Data_::flags
uint8_t flags
Definition: detect-asn1.h:37
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:349
StringParseI32RangeCheck
int StringParseI32RangeCheck(int32_t *res, int base, uint16_t len, const char *str, int32_t min, int32_t max)
Definition: util-byte.c:704
debug.h
ASN1_BITSTRING_OVF
#define ASN1_BITSTRING_OVF
Definition: detect-asn1.h:30
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1201
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:467