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