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