suricata
detect-engine-port.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2019 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
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  * Ports part of the detection engine.
24  *
25  * \todo more unit testing
26  *
27  */
28 
29 #include "suricata-common.h"
30 #include "decode.h"
31 #include "detect.h"
32 #include "flow-var.h"
33 
34 #include "util-cidr.h"
35 #include "util-unittest.h"
36 #include "util-unittest-helper.h"
37 #include "util-rule-vars.h"
38 
39 #include "detect-parse.h"
40 #include "detect-engine.h"
41 #include "detect-engine-mpm.h"
42 
43 #include "detect-engine-siggroup.h"
44 #include "detect-engine-port.h"
45 
46 #include "conf.h"
47 #include "util-debug.h"
48 #include "util-error.h"
49 
50 #include "pkt-var.h"
51 #include "host.h"
52 #include "util-profiling.h"
53 #include "util-var.h"
54 #include "util-byte.h"
55 
56 static int DetectPortCutNot(DetectPort *, DetectPort **);
57 static int DetectPortCut(DetectEngineCtx *, DetectPort *, DetectPort *,
58  DetectPort **);
59 DetectPort *PortParse(const char *str);
60 static bool DetectPortIsValidRange(char *, uint16_t *);
61 
62 /**
63  * \brief Alloc a DetectPort structure and update counters
64  *
65  * \retval dp newly created DetectPort on success; or NULL in case of error.
66  */
68 {
69  DetectPort *dp = SCCalloc(1, sizeof(DetectPort));
70  if (unlikely(dp == NULL))
71  return NULL;
72  return dp;
73 }
74 
75 /**
76  * \brief Free a DetectPort and its members
77  *
78  * \param dp Pointer to the DetectPort that has to be freed.
79  */
81 {
82  if (dp == NULL)
83  return;
84 
85  /* only free the head if we have the original */
86  if (dp->sh != NULL && !(dp->flags & PORT_SIGGROUPHEAD_COPY)) {
88  }
89  dp->sh = NULL;
90 
91  SCFree(dp);
92 }
93 
94 /**
95  * \brief Helper function used to print the list of ports
96  * present in this DetectPort list.
97  *
98  * \param head Pointer to the DetectPort list head
99  */
101 {
102  DetectPort *cur;
103 #ifdef DEBUG
104  uint16_t cnt = 0;
105 #endif
106  SCLogDebug("= list start:");
107  if (head != NULL) {
108  for (cur = head; cur != NULL; cur = cur->next) {
109  DetectPortPrint(cur);
110 #ifdef DEBUG
111  cnt++;
112 #endif
113  }
114  SCLogDebug(" ");
115  }
116  SCLogDebug("= list end (cnt %" PRIu32 ")", cnt);
117 }
118 
119 /**
120  * \brief Free a DetectPort list and each of its members
121  *
122  * \param head Pointer to the DetectPort list head
123  */
125 {
126  if (head == NULL)
127  return;
128 
129  DetectPort *cur, *next;
130 
131  for (cur = head; cur != NULL; ) {
132  next = cur->next;
133  cur->next = NULL;
134  DetectPortFree(de_ctx, cur);
135  cur = next;
136  }
137 }
138 
139 /**
140  * \brief function for inserting a port group object. This also makes sure
141  * SigGroupContainer lists are handled correctly.
142  *
143  * \param de_ctx Pointer to the current detection engine context
144  * \param head Pointer to the DetectPort list head
145  * \param dp DetectPort to search in the DetectPort list
146  *
147  * \retval 1 inserted
148  * \retval 0 not inserted, memory of new is freed
149  * \retval -1 error
150  *
151  * \todo rewrite to avoid recursive calls
152  * */
154  DetectPort *new)
155 {
156  if (new == NULL)
157  return 0;
158 
159  //BUG_ON(new->next != NULL);
160  //BUG_ON(new->prev != NULL);
161 
162  /* see if it already exists or overlaps with existing ports */
163  if (*head != NULL) {
164  DetectPort *cur = NULL;
165  int r = 0;
166 
167  for (cur = *head; cur != NULL; cur = cur->next) {
168  r = DetectPortCmp(new,cur);
169  BUG_ON(r == PORT_ER);
170 
171  /* if so, handle that */
172  if (r == PORT_EQ) {
173  SCLogDebug("PORT_EQ %p %p", cur, new);
174  /* exact overlap/match */
175  if (cur != new) {
176  DetectPortFree(de_ctx, new);
177  return 0;
178  }
179  return 1;
180  } else if (r == PORT_GT) {
181  SCLogDebug("PORT_GT (cur->next %p)", cur->next);
182  /* only add it now if we are bigger than the last
183  * group. Otherwise we'll handle it later. */
184  if (cur->next == NULL) {
185  SCLogDebug("adding GT");
186  /* put in the list */
187  new->prev = cur;
188  cur->next = new;
189  return 1;
190  }
191  } else if (r == PORT_LT) {
192  SCLogDebug("PORT_LT");
193 
194  /* see if we need to insert the ag anywhere */
195  /* put in the list */
196  if (cur->prev != NULL)
197  cur->prev->next = new;
198  new->prev = cur->prev;
199  new->next = cur;
200  cur->prev = new;
201 
202  /* update head if required */
203  if (*head == cur) {
204  *head = new;
205  }
206  return 1;
207 
208  /* alright, those were the simple cases,
209  * lets handle the more complex ones now */
210 
211  } else {
212  DetectPort *c = NULL;
213  r = DetectPortCut(de_ctx, cur, new, &c);
214  if (r == -1)
215  goto error;
216 
217  r = DetectPortInsert(de_ctx, head, new);
218  if (r == -1) {
219  if (c != NULL) {
221  }
222  goto error;
223  }
224 
225  if (c != NULL) {
226  SCLogDebug("inserting C (%p)", c);
227  if (SCLogDebugEnabled()) {
228  DetectPortPrint(c);
229  }
230  r = DetectPortInsert(de_ctx, head, c);
231  if (r == -1)
232  goto error;
233  }
234  return 1;
235 
236  }
237  }
238 
239  /* head is NULL, so get a group and set head to it */
240  } else {
241  SCLogDebug("setting new head %p", new);
242  *head = new;
243  }
244 
245  return 1;
246 error:
247  /* XXX */
248  return -1;
249 }
250 
251 /**
252  * \brief Function that cuts port groups and merge them
253  *
254  * \param de_ctx Pointer to the current detection engine context
255  * \param a pointer to DetectPort "a"
256  * \param b pointer to DetectPort "b"
257  * \param c pointer to DetectPort "c"
258  *
259  * \retval 0 ok
260  * \retval -1 error
261  * */
262 static int DetectPortCut(DetectEngineCtx *de_ctx, DetectPort *a,
263  DetectPort *b, DetectPort **c)
264 {
265  uint16_t a_port1 = a->port;
266  uint16_t a_port2 = a->port2;
267  uint16_t b_port1 = b->port;
268  uint16_t b_port2 = b->port2;
269 
270  /* default to NULL */
271  *c = NULL;
272 
273  int r = DetectPortCmp(a,b);
274  BUG_ON(r != PORT_ES && r != PORT_EB && r != PORT_LE && r != PORT_GE);
275 
276  /* get a place to temporary put sigs lists */
277  DetectPort *tmp = DetectPortInit();
278  if (tmp == NULL) {
279  goto error;
280  }
281 
282  /**
283  * We have 3 parts: [aaa[abab]bbb]
284  * part a: a_port1 <-> b_port1 - 1
285  * part b: b_port1 <-> a_port2
286  * part c: a_port2 + 1 <-> b_port2
287  */
288  if (r == PORT_LE) {
289  SCLogDebug("cut r == PORT_LE");
290  a->port = a_port1;
291  a->port2 = b_port1 - 1;
292 
293  b->port = b_port1;
294  b->port2 = a_port2;
295 
296  DetectPort *tmp_c = DetectPortInit();
297  if (tmp_c == NULL) {
298  goto error;
299  }
300  *c = tmp_c;
301 
302  tmp_c->port = a_port2 + 1;
303  tmp_c->port2 = b_port2;
304 
305  /**
306  * We have 3 parts: [bbb[baba]aaa]
307  * part a: b_port1 <-> a_port1 - 1
308  * part b: a_port1 <-> b_port2
309  * part c: b_port2 + 1 <-> a_port2
310  */
311  } else if (r == PORT_GE) {
312  SCLogDebug("cut r == PORT_GE");
313  a->port = b_port1;
314  a->port2 = a_port1 - 1;
315 
316  b->port = a_port1;
317  b->port2 = b_port2;
318 
319  DetectPort *tmp_c = DetectPortInit();
320  if (tmp_c == NULL) {
321  goto error;
322  }
323  *c = tmp_c;
324 
325  tmp_c->port = b_port2 + 1;
326  tmp_c->port2 = a_port2;
327 
328  /**
329  * We have 2 or three parts:
330  *
331  * 2 part: [[abab]bbb] or [bbb[baba]]
332  * part a: a_port1 <-> a_port2
333  * part b: a_port2 + 1 <-> b_port2
334  *
335  * part a: b_port1 <-> a_port1 - 1
336  * part b: a_port1 <-> a_port2
337  *
338  * 3 part [bbb[aaa]bbb]
339  * becomes[aaa[bbb]ccc]
340  *
341  * part a: b_port1 <-> a_port1 - 1
342  * part b: a_port1 <-> a_port2
343  * part c: a_port2 + 1 <-> b_port2
344  */
345  } else if (r == PORT_ES) {
346  SCLogDebug("cut r == PORT_ES");
347  if (a_port1 == b_port1) {
348  SCLogDebug("1");
349  a->port = a_port1;
350  a->port2 = a_port2;
351 
352  b->port = a_port2 + 1;
353  b->port2 = b_port2;
354  } else if (a_port2 == b_port2) {
355  SCLogDebug("2");
356  a->port = b_port1;
357  a->port2 = a_port1 - 1;
358 
359  b->port = a_port1;
360  b->port2 = a_port2;
361  } else {
362  SCLogDebug("3");
363  a->port = b_port1;
364  a->port2 = a_port1 - 1;
365 
366  b->port = a_port1;
367  b->port2 = a_port2;
368 
369  DetectPort *tmp_c = DetectPortInit();
370  if (tmp_c == NULL) {
371  goto error;
372  }
373  *c = tmp_c;
374 
375  tmp_c->port = a_port2 + 1;
376  tmp_c->port2 = b_port2;
377  }
378  /**
379  * We have 2 or three parts:
380  *
381  * 2 part: [[baba]aaa] or [aaa[abab]]
382  * part a: b_port1 <-> b_port2
383  * part b: b_port2 + 1 <-> a_port2
384  *
385  * part a: a_port1 <-> b_port1 - 1
386  * part b: b_port1 <-> b_port2
387  *
388  * 3 part [aaa[bbb]aaa]
389  * becomes[aaa[bbb]ccc]
390  *
391  * part a: a_port1 <-> b_port2 - 1
392  * part b: b_port1 <-> b_port2
393  * part c: b_port2 + 1 <-> a_port2
394  */
395  } else if (r == PORT_EB) {
396  SCLogDebug("cut r == PORT_EB");
397  if (a_port1 == b_port1) {
398  SCLogDebug("1");
399  a->port = b_port1;
400  a->port2 = b_port2;
401 
402  b->port = b_port2 + 1;
403  b->port2 = a_port2;
404  } else if (a_port2 == b_port2) {
405  SCLogDebug("2");
406 
407  a->port = a_port1;
408  a->port2 = b_port1 - 1;
409 
410  b->port = b_port1;
411  b->port2 = b_port2;
412 
413  } else {
414  SCLogDebug("3");
415  a->port = a_port1;
416  a->port2 = b_port1 - 1;
417 
418  b->port = b_port1;
419  b->port2 = b_port2;
420 
421  DetectPort *tmp_c = DetectPortInit();
422  if (tmp_c == NULL) {
423  goto error;
424  }
425  *c = tmp_c;
426 
427  tmp_c->port = b_port2 + 1;
428  tmp_c->port2 = a_port2;
429  }
430  }
431 
432  if (tmp != NULL) {
433  DetectPortFree(de_ctx, tmp);
434  }
435  return 0;
436 
437 error:
438  if (tmp != NULL)
439  DetectPortFree(de_ctx, tmp);
440  return -1;
441 }
442 
443 /**
444  * \brief Function that cuts port groups implementing group negation
445  *
446  * \param a pointer to DetectPort "a"
447  * \param b pointer to DetectPort "b"
448  *
449  * \retval 0 ok
450  * \retval -1 error
451  * */
452 static int DetectPortCutNot(DetectPort *a, DetectPort **b)
453 {
454  uint16_t a_port1 = a->port;
455  uint16_t a_port2 = a->port2;
456 
457  /* default to NULL */
458  *b = NULL;
459 
460  if (a_port1 != 0x0000 && a_port2 != 0xFFFF) {
461  a->port = 0x0000;
462  a->port2 = a_port1 - 1;
463 
464  DetectPort *tmp_b;
465  tmp_b = DetectPortInit();
466  if (tmp_b == NULL) {
467  return -1;
468  }
469 
470  tmp_b->port = a_port2 + 1;
471  tmp_b->port2 = 0xFFFF;
472  *b = tmp_b;
473 
474  } else if (a_port1 == 0x0000 && a_port2 != 0xFFFF) {
475  a->port = a_port2 + 1;
476  a->port2 = 0xFFFF;
477 
478  } else if (a_port1 != 0x0000 && a_port2 == 0xFFFF) {
479  a->port = 0x0000;
480  a->port2 = a_port1 - 1;
481  } else {
482  return -1;
483  }
484 
485  return 0;
486 }
487 
488 /**
489  * \brief Function that compare port groups
490  *
491  * \param a pointer to DetectPort "a"
492  * \param b pointer to DetectPort "b"
493  *
494  * \retval PORT_XX (Port enum value, XX is EQ, ES, EB, LE, etc)
495  * \retval PORT_ER on error
496  * */
498 {
499  /* check any */
500  if ((a->flags & PORT_FLAG_ANY) && (b->flags & PORT_FLAG_ANY))
501  return PORT_EQ;
502  if ((a->flags & PORT_FLAG_ANY) && !(b->flags & PORT_FLAG_ANY))
503  return PORT_LT;
504  if (!(a->flags & PORT_FLAG_ANY) && (b->flags & PORT_FLAG_ANY))
505  return PORT_GT;
506 
507  uint16_t a_port1 = a->port;
508  uint16_t a_port2 = a->port2;
509  uint16_t b_port1 = b->port;
510  uint16_t b_port2 = b->port2;
511 
512  /* PORT_EQ */
513  if (a_port1 == b_port1 && a_port2 == b_port2) {
514  //SCLogDebug("PORT_EQ");
515  return PORT_EQ;
516  /* PORT_ES */
517  } else if (a_port1 >= b_port1 && a_port1 <= b_port2 && a_port2 <= b_port2) {
518  //SCLogDebug("PORT_ES");
519  return PORT_ES;
520  /* PORT_EB */
521  } else if (a_port1 <= b_port1 && a_port2 >= b_port2) {
522  //SCLogDebug("PORT_EB");
523  return PORT_EB;
524  } else if (a_port1 < b_port1 && a_port2 < b_port2 && a_port2 >= b_port1) {
525  //SCLogDebug("PORT_LE");
526  return PORT_LE;
527  } else if (a_port1 < b_port1 && a_port2 < b_port2) {
528  //SCLogDebug("PORT_LT");
529  return PORT_LT;
530  } else if (a_port1 > b_port1 && a_port1 <= b_port2 && a_port2 > b_port2) {
531  //SCLogDebug("PORT_GE");
532  return PORT_GE;
533  } else if (a_port1 > b_port2) {
534  //SCLogDebug("PORT_GT");
535  return PORT_GT;
536  }
537 
538  return PORT_ER;
539 }
540 
541 /**
542  * \brief Function that return a copy of DetectPort src sigs
543  *
544  * \param de_ctx Pointer to the current Detection Engine Context
545  * \param src Pointer to a DetectPort group to copy
546  *
547  * \retval Pointer to a DetectPort instance (copy of src)
548  * \retval NULL on error
549  * */
551 {
552  if (src == NULL)
553  return NULL;
554 
556  if (dst == NULL) {
557  return NULL;
558  }
559 
560  dst->port = src->port;
561  dst->port2 = src->port2;
562 
564  return dst;
565 }
566 
567 /**
568  * \brief Function Match to Match a port against a DetectPort group
569  *
570  * \param dp Pointer to DetectPort group where we try to match the port
571  * \param port To compare/match
572  *
573  * \retval 1 if port is in the range (it match)
574  * \retval 0 if port is not in the range
575  * */
576 static int DetectPortMatch(DetectPort *dp, uint16_t port)
577 {
578  if (port >= dp->port &&
579  port <= dp->port2) {
580  return 1;
581  }
582 
583  return 0;
584 }
585 
586 /**
587  * \brief Helper function that print the DetectPort info
588  * \retval none
589  */
591 {
592  if (dp == NULL)
593  return;
594 
595  if (dp->flags & PORT_FLAG_ANY) {
596  SCLogDebug("=> port %p: ANY", dp);
597 // printf("ANY");
598  } else {
599  SCLogDebug("=> port %p %" PRIu32 "-%" PRIu32 "", dp, dp->port, dp->port2);
600 // printf("%" PRIu32 "-%" PRIu32 "", dp->port, dp->port2);
601  }
602 }
603 
604 /**
605  * \brief Function that find the group matching port in a group head
606  *
607  * \param dp Pointer to DetectPort group where we try to find the group
608  * \param port port to search/lookup
609  *
610  * \retval Pointer to the DetectPort group of our port if it matched
611  * \retval NULL if port is not in the list
612  * */
614 {
615  if (dp == NULL)
616  return NULL;
617 
618  for (DetectPort *p = dp; p != NULL; p = p->next) {
619  if (DetectPortMatch(p, port) == 1) {
620  //SCLogDebug("match, port %" PRIu32 ", dp ", port);
621  //DetectPortPrint(p); SCLogDebug("");
622  return p;
623  }
624  }
625 
626  return NULL;
627 }
628 
629 /**
630  * \brief Checks if two port group lists are equal.
631  *
632  * \param list1 Pointer to the first port group list.
633  * \param list2 Pointer to the second port group list.
634  *
635  * \retval true On success.
636  * \retval false On failure.
637  */
639 {
640  DetectPort *item = list1;
641  DetectPort *it = list2;
642 
643  // First, compare items one by one.
644  while (item != NULL && it != NULL) {
645  if (DetectPortCmp(item, it) != PORT_EQ) {
646  return false;
647  }
648 
649  item = item->next;
650  it = it->next;
651  }
652 
653  // Are the lists of the same size?
654  if (!(item == NULL && it == NULL)) {
655  return false;
656  }
657 
658  return true;
659 }
660 
661 /******************* parsing routines ************************/
662 
663 /**
664  * \brief Wrapper function that call the internal/real function
665  * to insert the new DetectPort
666  * \param head Pointer to the head of the DetectPort group list
667  * \param new Pointer to the new DetectPort group list
668  *
669  * \retval 1 inserted
670  * \retval 0 not inserted, memory of new is freed
671  * \retval -1 error
672  */
673 static int DetectPortParseInsert(DetectPort **head, DetectPort *new)
674 {
675  return DetectPortInsert(NULL, head, new);
676 }
677 
678 /**
679  * \brief Function to parse and insert the string in the DetectPort head list
680  *
681  * \param head Pointer to the head of the DetectPort group list
682  * \param s Pointer to the port string
683  *
684  * \retval 0 on success
685  * \retval -1 on error
686  */
687 static int DetectPortParseInsertString(const DetectEngineCtx *de_ctx,
688  DetectPort **head, const char *s)
689 {
690  DetectPort *port = NULL, *port_any = NULL;
691  int r = 0;
692  bool is_port_any = false;
693 
694  SCLogDebug("head %p, *head %p, s %s", head, *head, s);
695 
696  /** parse the port */
697  port = PortParse(s);
698  if (port == NULL) {
699  SCLogError(" failed to parse port \"%s\"", s);
700  return -1;
701  }
702 
703  if (port->flags & PORT_FLAG_ANY) {
704  is_port_any = true;
705  }
706 
707  /** handle the not case, we apply the negation then insert the part(s) */
708  if (port->flags & PORT_FLAG_NOT) {
709  DetectPort *port2 = NULL;
710 
711  if (DetectPortCutNot(port, &port2) < 0) {
712  goto error;
713  }
714 
715  /** normally, a 'not' will at most result in two ports */
716  if (port2 != NULL) {
717  if (DetectPortParseInsert(head, port2) < 0) {
718  if (port2 != NULL)
719  SCFree(port2);
720  goto error;
721  }
722  }
723  }
724 
725  r = DetectPortParseInsert(head, port);
726  if (r < 0)
727  goto error;
728 
729  /** if any, insert [0:65535] */
730  if (r == 1 && is_port_any) {
731  SCLogDebug("inserting 0:65535 as port is \"any\"");
732 
733  port_any = PortParse("0:65535");
734  if (port_any == NULL)
735  goto error;
736 
737  if (DetectPortParseInsert(head, port_any) < 0)
738  goto error;
739  }
740 
741  return 0;
742 
743 error:
744  SCLogError("DetectPortParseInsertString error");
745  if (port != NULL)
747  if (port_any != NULL)
748  DetectPortCleanupList(de_ctx, port_any);
749  return -1;
750 }
751 
752 /**
753  * \brief Parses a port string and updates the 2 port heads with the
754  * port groups.
755  *
756  * \todo We don't seem to be handling negated cases, like [port,![!port,port]],
757  * since we pass around negate without keeping a count of ! with depth.
758  * Can solve this by keeping a count of the negations with depth, so that
759  * an even no of negations would count as no negation and an odd no of
760  * negations would count as a negation.
761  *
762  * \param gh Pointer to the port group head that should hold port ranges
763  * that are not negated.
764  * \param ghn Pointer to the port group head that should hold port ranges
765  * that are negated.
766  * \param s Pointer to the character string holding the port to be
767  * parsed.
768  * \param negate Flag that indicates if the received port string is negated
769  * or not. 0 if it is not, 1 it it is.
770  *
771  * \retval 0 On successfully parsing.
772  * \retval -1 On failure.
773  */
774 static int DetectPortParseDo(const DetectEngineCtx *de_ctx,
775  DetectPort **head, DetectPort **nhead,
776  const char *s, int negate,
777  ResolvedVariablesList *var_list, int recur)
778 {
779  size_t u = 0;
780  size_t x = 0;
781  int o_set = 0, n_set = 0, d_set = 0;
782  int range = 0;
783  int depth = 0;
784  size_t size = strlen(s);
785  char port[1024] = "";
786  const char *rule_var_port = NULL;
787  int r = 0;
788 
789  if (recur++ > 64) {
790  SCLogError("port block recursion "
791  "limit reached (max 64)");
792  goto error;
793  }
794 
795  SCLogDebug("head %p, *head %p, negate %d", head, *head, negate);
796 
797  for (; u < size && x < sizeof(port); u++) {
798  port[x] = s[u];
799  x++;
800 
801  if (s[u] == ':')
802  range = 1;
803 
804  if (range == 1 && s[u] == '!') {
805  SCLogError("Can't have a negated value in a range.");
806  return -1;
807  } else if (!o_set && s[u] == '!') {
808  SCLogDebug("negation encountered");
809  n_set = 1;
810  BUG_ON(x == 0); /* always false; added to guide static code analyzers like Coverity */
811  x--;
812  } else if (s[u] == '[') {
813  if (!o_set) {
814  o_set = 1;
815  x = 0;
816  }
817  depth++;
818  } else if (s[u] == ']') {
819  if (depth == 1) {
820  port[x - 1] = '\0';
821  SCLogDebug("Parsed port from DetectPortParseDo - %s", port);
822  x = 0;
823 
824  r = DetectPortParseDo(
825  de_ctx, head, nhead, port, negate ? negate : n_set, var_list, recur);
826  if (r == -1)
827  goto error;
828 
829  n_set = 0;
830  }
831  depth--;
832  range = 0;
833  } else if (depth == 0 && s[u] == ',') {
834  if (o_set == 1) {
835  o_set = 0;
836  } else if (d_set == 1) {
837  char *temp_rule_var_port = NULL,
838  *alloc_rule_var_port = NULL;
839 
840  port[x - 1] = '\0';
841 
842  rule_var_port = SCRuleVarsGetConfVar(de_ctx, port, SC_RULE_VARS_PORT_GROUPS);
843  if (rule_var_port == NULL)
844  goto error;
845  if (strlen(rule_var_port) == 0) {
846  SCLogError("variable %s resolved "
847  "to nothing. This is likely a misconfiguration. "
848  "Note that a negated port needs to be quoted, "
849  "\"!$HTTP_PORTS\" instead of !$HTTP_PORTS. See issue #295.",
850  s);
851  goto error;
852  }
853  if (negate == 1 || n_set == 1) {
854  alloc_rule_var_port = SCMalloc(strlen(rule_var_port) + 3);
855  if (unlikely(alloc_rule_var_port == NULL))
856  goto error;
857  snprintf(alloc_rule_var_port, strlen(rule_var_port) + 3,
858  "[%s]", rule_var_port);
859  } else {
860  alloc_rule_var_port = SCStrdup(rule_var_port);
861  if (unlikely(alloc_rule_var_port == NULL))
862  goto error;
863  }
864  temp_rule_var_port = alloc_rule_var_port;
865  r = DetectPortParseDo(de_ctx, head, nhead, temp_rule_var_port,
866  (negate + n_set) % 2, var_list, recur);
867  if (r == -1) {
868  SCFree(alloc_rule_var_port);
869  goto error;
870  }
871  d_set = 0;
872  n_set = 0;
873  SCFree(alloc_rule_var_port);
874  } else {
875  port[x - 1] = '\0';
876  SCLogDebug("Parsed port from DetectPortParseDo - %s", port);
877 
878  if (negate == 0 && n_set == 0) {
879  r = DetectPortParseInsertString(de_ctx, head, port);
880  } else {
881  r = DetectPortParseInsertString(de_ctx, nhead, port);
882  }
883  if (r == -1)
884  goto error;
885 
886  n_set = 0;
887  }
888  x = 0;
889  range = 0;
890  } else if (depth == 0 && s[u] == '$') {
891  d_set = 1;
892  } else if (depth == 0 && u == size-1) {
893  range = 0;
894  if (x == 1024) {
895  port[x - 1] = '\0';
896  } else {
897  port[x] = '\0';
898  }
899  SCLogDebug("%s", port);
900 
901  if (AddVariableToResolveList(var_list, port) == -1) {
902  SCLogError("Found a loop in a port "
903  "groups declaration. This is likely a misconfiguration.");
904  goto error;
905  }
906 
907  x = 0;
908  if (d_set == 1) {
909  char *temp_rule_var_port = NULL,
910  *alloc_rule_var_port = NULL;
911 
912  rule_var_port = SCRuleVarsGetConfVar(de_ctx, port, SC_RULE_VARS_PORT_GROUPS);
913  if (rule_var_port == NULL)
914  goto error;
915  if (strlen(rule_var_port) == 0) {
916  SCLogError("variable %s resolved "
917  "to nothing. This is likely a misconfiguration. "
918  "Note that a negated port needs to be quoted, "
919  "\"!$HTTP_PORTS\" instead of !$HTTP_PORTS. See issue #295.",
920  s);
921  goto error;
922  }
923  if ((negate + n_set) % 2) {
924  alloc_rule_var_port = SCMalloc(strlen(rule_var_port) + 3);
925  if (unlikely(alloc_rule_var_port == NULL))
926  goto error;
927  snprintf(alloc_rule_var_port, strlen(rule_var_port) + 3,
928  "[%s]", rule_var_port);
929  } else {
930  alloc_rule_var_port = SCStrdup(rule_var_port);
931  if (unlikely(alloc_rule_var_port == NULL))
932  goto error;
933  }
934  temp_rule_var_port = alloc_rule_var_port;
935  r = DetectPortParseDo(de_ctx, head, nhead, temp_rule_var_port,
936  (negate + n_set) % 2, var_list, recur);
937  SCFree(alloc_rule_var_port);
938  if (r == -1)
939  goto error;
940 
941  d_set = 0;
942  } else {
943  if (!((negate + n_set) % 2)) {
944  r = DetectPortParseInsertString(de_ctx, head, port);
945  } else {
946  r = DetectPortParseInsertString(de_ctx, nhead, port);
947  }
948  if (r == -1)
949  goto error;
950  }
951  n_set = 0;
952  } else if (depth == 1 && s[u] == ',') {
953  range = 0;
954  }
955  }
956 
957  if (depth > 0) {
958  SCLogError("not every port block was "
959  "properly closed in \"%s\", %d missing closing brackets (]). "
960  "Note: problem might be in a variable.",
961  s, depth);
962  goto error;
963  } else if (depth < 0) {
964  SCLogError("not every port block was "
965  "properly opened in \"%s\", %d missing opening brackets ([). "
966  "Note: problem might be in a variable.",
967  s, depth * -1);
968  goto error;
969  }
970 
971  return 0;
972 error:
973  return -1;
974 }
975 
976 /**
977  * \brief Check if the port group list covers the complete port space.
978  * \retval 0 no
979  * \retval 1 yes
980  */
981 static int DetectPortIsCompletePortSpace(DetectPort *p)
982 {
983  uint16_t next_port = 0;
984 
985  if (p == NULL)
986  return 0;
987 
988  if (p->port != 0x0000)
989  return 0;
990 
991  /* if we're ending with 0xFFFF while we know
992  we started with 0x0000 it's the complete space */
993  if (p->port2 == 0xFFFF)
994  return 1;
995 
996  next_port = p->port2 + 1;
997  p = p->next;
998 
999  for ( ; p != NULL; p = p->next) {
1000  if (p->port != next_port)
1001  return 0;
1002 
1003  if (p->port2 == 0xFFFF)
1004  return 1;
1005 
1006  next_port = p->port2 + 1;
1007  }
1008 
1009  return 0;
1010 }
1011 
1012 /**
1013  * \brief Helper function for the parsing process
1014  *
1015  * \param head Pointer to the head of the DetectPort group list
1016  * \param nhead Pointer to the new head of the DetectPort group list
1017  *
1018  * \retval 0 on success
1019  * \retval -1 on error
1020  */
1021 static int DetectPortParseMergeNotPorts(const DetectEngineCtx *de_ctx,
1022  DetectPort **head, DetectPort **nhead)
1023 {
1024  DetectPort *port = NULL;
1025  DetectPort *pg, *pg2;
1026  int r = 0;
1027 
1028  /** check if the full port space is negated */
1029  if (DetectPortIsCompletePortSpace(*nhead) == 1) {
1030  SCLogError("Complete port space is negated");
1031  goto error;
1032  }
1033 
1034  /**
1035  * step 0: if the head list is empty, but the nhead list isn't
1036  * we have a pure not thingy. In that case we add a 0:65535
1037  * first.
1038  */
1039  if (*head == NULL && *nhead != NULL) {
1040  SCLogDebug("inserting 0:65535 into head");
1041  r = DetectPortParseInsertString(de_ctx, head,"0:65535");
1042  if (r < 0) {
1043  goto error;
1044  }
1045  }
1046 
1047  /** step 1: insert our ghn members into the gh list */
1048  for (pg = *nhead; pg != NULL; pg = pg->next) {
1049  /** work with a copy of the port so we can easily clean up
1050  * the ghn group later.
1051  */
1052  port = DetectPortCopySingle(NULL, pg);
1053  if (port == NULL) {
1054  goto error;
1055  }
1056  r = DetectPortParseInsert(head, port);
1057  if (r < 0) {
1058  goto error;
1059  }
1060  port = NULL;
1061  }
1062 
1063  /** step 2: pull the port blocks that match our 'not' blocks */
1064  for (pg = *nhead; pg != NULL; pg = pg->next) {
1065  SCLogDebug("pg %p", pg);
1066  DetectPortPrint(pg);
1067 
1068  for (pg2 = *head; pg2 != NULL;) {
1069  SCLogDebug("pg2 %p", pg2);
1070  DetectPortPrint(pg2);
1071 
1072  r = DetectPortCmp(pg, pg2);
1073  if (r == PORT_EQ || r == PORT_EB) { /* XXX more ??? */
1074  if (pg2->prev != NULL)
1075  pg2->prev->next = pg2->next;
1076  if (pg2->next != NULL)
1077  pg2->next->prev = pg2->prev;
1078  if (*head == pg2)
1079  *head = pg2->next;
1080  /** store the next ptr and remove the group */
1081  DetectPort *next_pg2 = pg2->next;
1082  DetectPortFree(de_ctx, pg2);
1083  pg2 = next_pg2;
1084  } else {
1085  pg2 = pg2->next;
1086  }
1087  }
1088  }
1089 
1090  for (pg2 = *head; pg2 != NULL; pg2 = pg2->next) {
1091  SCLogDebug("pg2 %p", pg2);
1092  DetectPortPrint(pg2);
1093  }
1094 
1095  if (*head == NULL) {
1096  SCLogError("no ports left after merging ports with negated ports");
1097  goto error;
1098  }
1099 
1100  return 0;
1101 error:
1102  if (port != NULL)
1103  DetectPortFree(de_ctx, port);
1104  return -1;
1105 }
1106 
1108 {
1109  SCLogDebug("Testing port conf vars for any misconfigured values");
1110 
1111  ResolvedVariablesList var_list = TAILQ_HEAD_INITIALIZER(var_list);
1112 
1113  SCConfNode *port_vars_node = SCConfGetNode("vars.port-groups");
1114  if (port_vars_node == NULL) {
1115  return 0;
1116  }
1117 
1118  SCConfNode *seq_node;
1119  TAILQ_FOREACH(seq_node, &port_vars_node->head, next) {
1120  SCLogDebug("Testing %s - %s\n", seq_node->name, seq_node->val);
1121 
1122  DetectPort *gh = DetectPortInit();
1123  if (gh == NULL) {
1124  goto error;
1125  }
1126  DetectPort *ghn = NULL;
1127 
1128  if (seq_node->val == NULL) {
1129  SCLogError("Port var \"%s\" probably has a sequence(something "
1130  "in brackets) value set without any quotes. Please "
1131  "quote it using \"..\".",
1132  seq_node->name);
1133  DetectPortCleanupList(NULL, gh);
1134  goto error;
1135  }
1136 
1137  int r = DetectPortParseDo(NULL, &gh, &ghn, seq_node->val,
1138  /* start with negate no */0, &var_list, 0);
1139 
1140  CleanVariableResolveList(&var_list);
1141 
1142  if (r < 0) {
1143  DetectPortCleanupList(NULL, gh);
1144  SCLogError("failed to parse port var \"%s\" with value \"%s\". "
1145  "Please check its syntax",
1146  seq_node->name, seq_node->val);
1147  goto error;
1148  }
1149 
1150  if (DetectPortIsCompletePortSpace(ghn)) {
1151  SCLogError("Port var - \"%s\" has the complete Port range negated "
1152  "with its value \"%s\". Port space range is NIL. "
1153  "Probably have a !any or a port range that supplies "
1154  "a NULL port range",
1155  seq_node->name, seq_node->val);
1156  DetectPortCleanupList(NULL, gh);
1157  DetectPortCleanupList(NULL, ghn);
1158  goto error;
1159  }
1160 
1161  if (gh != NULL)
1162  DetectPortCleanupList(NULL, gh);
1163  if (ghn != NULL)
1164  DetectPortCleanupList(NULL, ghn);
1165  }
1166 
1167  return 0;
1168  error:
1169  return -1;
1170 }
1171 
1172 
1173 /**
1174  * \brief Function for parsing port strings
1175  *
1176  * \param de_ctx Pointer to the detection engine context
1177  * \param head Pointer to the head of the DetectPort group list
1178  * \param str Pointer to the port string
1179  *
1180  * \retval 0 on success
1181  * \retval -1 on error
1182  */
1184  DetectPort **head, const char *str)
1185 {
1186  SCLogDebug("Port string to be parsed - str %s", str);
1187 
1188  /* negate port list */
1189  DetectPort *nhead = NULL;
1190 
1191  int r = DetectPortParseDo(de_ctx, head, &nhead, str,
1192  /* start with negate no */ 0, NULL, 0);
1193  if (r < 0)
1194  goto error;
1195 
1196  SCLogDebug("head %p %p, nhead %p", head, *head, nhead);
1197 
1198  /* merge the 'not' port groups */
1199  if (DetectPortParseMergeNotPorts(de_ctx, head, &nhead) < 0)
1200  goto error;
1201 
1202  /* free the temp negate head */
1203  DetectPortCleanupList(de_ctx, nhead);
1204  return 0;
1205 
1206 error:
1207  DetectPortCleanupList(de_ctx, nhead);
1208  return -1;
1209 }
1210 
1211 /**
1212  * \brief Helper function for parsing port strings
1213  *
1214  * \param str Pointer to the port string
1215  *
1216  * \retval DetectPort pointer of the parse string on success
1217  * \retval NULL on error
1218  */
1219 DetectPort *PortParse(const char *str)
1220 {
1221  char *port2 = NULL;
1222  char portstr[16];
1223 
1224  /* strip leading spaces */
1225  while (isspace(*str))
1226  str++;
1227  if (strlen(str) >= 16)
1228  return NULL;
1229  strlcpy(portstr, str, sizeof(portstr));
1230 
1231  DetectPort *dp = DetectPortInit();
1232  if (dp == NULL)
1233  goto error;
1234 
1235  /* we dup so we can put a nul-termination in it later */
1236  char *port = portstr;
1237 
1238  /* handle the negation case */
1239  if (port[0] == '!') {
1240  dp->flags |= PORT_FLAG_NOT;
1241  port++;
1242  }
1243 
1244  if ((port2 = strchr(port, ':')) != NULL) {
1245  /* 80:81 range format */
1246  port2[0] = '\0';
1247  port2++;
1248 
1249  if (strcmp(port, "") != 0) {
1250  if (!DetectPortIsValidRange(port, &dp->port))
1251  goto error;
1252  } else {
1253  dp->port = 0;
1254  }
1255 
1256  if (strcmp(port2, "") != 0) {
1257  if (!DetectPortIsValidRange(port2, &dp->port2))
1258  goto error;
1259  } else {
1260  dp->port2 = 65535;
1261  }
1262 
1263  /* a > b is illegal, a == b is ok */
1264  if (dp->port > dp->port2)
1265  goto error;
1266  } else {
1267  if (strcasecmp(port,"any") == 0) {
1268  dp->port = 0;
1269  dp->port2 = 65535;
1270  } else {
1271  if (!DetectPortIsValidRange(port, &dp->port))
1272  goto error;
1273  dp->port2 = dp->port;
1274  }
1275  }
1276 
1277  return dp;
1278 
1279 error:
1280  if (dp != NULL)
1281  DetectPortCleanupList(NULL, dp);
1282  return NULL;
1283 }
1284 
1285 /**
1286  * \brief Helper function to check if a parsed port is in the valid range
1287  * of available ports
1288  *
1289  * \param str Pointer to the port string
1290  *
1291  *
1292  * \retval true if port is in the valid range
1293  * \retval false if invalid
1294  */
1295 static bool DetectPortIsValidRange(char *port, uint16_t *port_val)
1296 {
1297  if (StringParseUint16(port_val, 10, 0, (const char *)port) < 0)
1298  return false;
1299 
1300  return true;
1301 }
1302 
1303 /********************** End parsing routines ********************/
1304 
1305 /* hash table */
1306 
1307 /**
1308  * \brief The hash function to be the used by the hash table -
1309  * DetectEngineCtx->dport_hash_table.
1310  *
1311  * \param ht Pointer to the hash table.
1312  * \param data Pointer to the DetectPort.
1313  * \param datalen Not used in our case.
1314  *
1315  * \retval hash The generated hash value.
1316  */
1317 static uint32_t DetectPortHashFunc(HashListTable *ht, void *data, uint16_t datalen)
1318 {
1319  DetectPort *p = (DetectPort *)data;
1320  SCLogDebug("hashing port %p", p);
1321 
1322  uint32_t hash = ((uint32_t)p->port << 16) | p->port2;
1323 
1324  hash %= ht->array_size;
1325  SCLogDebug("hash %"PRIu32, hash);
1326  return hash;
1327 }
1328 
1329 /**
1330  * \brief The Compare function to be used by the DetectPort hash table -
1331  * DetectEngineCtx->dport_hash_table.
1332  *
1333  * \param data1 Pointer to the first DetectPort.
1334  * \param len1 Not used.
1335  * \param data2 Pointer to the second DetectPort.
1336  * \param len2 Not used.
1337  *
1338  * \retval 1 If the 2 DetectPort sent as args match.
1339  * \retval 0 If the 2 DetectPort sent as args do not match.
1340  */
1341 static char DetectPortCompareFunc(void *data1, uint16_t len1,
1342  void *data2, uint16_t len2)
1343 {
1344  DetectPort *dp1 = (DetectPort *)data1;
1345  DetectPort *dp2 = (DetectPort *)data2;
1346 
1347  if (data1 == NULL || data2 == NULL)
1348  return 0;
1349 
1350  if (dp1->port == dp2->port && dp1->port2 == dp2->port2)
1351  return 1;
1352 
1353  return 0;
1354 }
1355 
1356 static void DetectPortHashFreeFunc(void *ptr)
1357 {
1358  DetectPort *p = ptr;
1359  DetectPortFree(NULL, p);
1360 }
1361 
1362 /**
1363  * \brief Initializes the hash table in the detection engine context to hold the
1364  * DetectPort hash.
1365  *
1366  * \param de_ctx Pointer to the detection engine context.
1367  *
1368  * \retval 0 On success.
1369  * \retval -1 On failure.
1370  */
1372 {
1373  de_ctx->dport_hash_table = HashListTableInit(4096, DetectPortHashFunc,
1374  DetectPortCompareFunc,
1375  DetectPortHashFreeFunc);
1376  if (de_ctx->dport_hash_table == NULL)
1377  return -1;
1378 
1379  return 0;
1380 }
1381 
1382 /**
1383  * \brief Adds a DetectPort to the detection engine context DetectPort
1384  * hash table.
1385  *
1386  * \param de_ctx Pointer to the detection engine context.
1387  * \param dp Pointer to the DetectPort.
1388  *
1389  * \retval ret 0 on Successfully adding the DetectPort; -1 on failure.
1390  */
1392 {
1393  int ret = HashListTableAdd(de_ctx->dport_hash_table, (void *)dp, 0);
1394  return ret;
1395 }
1396 
1397 /**
1398  * \brief Used to lookup a DetectPort hash from the detection engine context
1399  * DetectPort hash table.
1400  *
1401  * \param de_ctx Pointer to the detection engine context.
1402  * \param sgh Pointer to the DetectPort.
1403  *
1404  * \retval rsgh On success a pointer to the DetectPort if the DetectPort is
1405  * found in the hash table; NULL on failure.
1406  */
1408 {
1409  SCEnter();
1410 
1411  DetectPort *rdp = HashListTableLookup(de_ctx->dport_hash_table, (void *)dp, 0);
1412 
1413  SCReturnPtr(rdp, "DetectPort");
1414 }
1415 
1416 /**
1417  * \brief Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by
1418  * DetectPortInit() function.
1419  *
1420  * \param de_ctx Pointer to the detection engine context.
1421  */
1423 {
1424  if (de_ctx->sgh_hash_table == NULL)
1425  return;
1426 
1428  de_ctx->dport_hash_table = NULL;
1429 }
1430 
1431 /*---------------------- Unittests -------------------------*/
1432 
1433 #ifdef UNITTESTS
1434 #include "packet.h"
1435 
1436 /**
1437  * \brief Do a sorted insert, where the top of the list should be the biggest
1438  * port range.
1439  *
1440  * \todo XXX current sorting only works for overlapping ranges
1441  *
1442  * \param head Pointer to the DetectPort list head
1443  * \param dp Pointer to DetectPort to search in the DetectPort list
1444  * \retval 0 if dp is added correctly
1445  */
1446 static int PortTestDetectPortAdd(DetectPort **head, DetectPort *dp)
1447 {
1448  DetectPort *cur, *prev_cur = NULL;
1449 
1450  //SCLogDebug("DetectPortAdd: adding "); DetectPortPrint(ag); SCLogDebug("");
1451 
1452  if (*head != NULL) {
1453  for (cur = *head; cur != NULL; cur = cur->next) {
1454  prev_cur = cur;
1455  int r = DetectPortCmp(dp,cur);
1456  if (r == PORT_EB) {
1457  /* insert here */
1458  dp->prev = cur->prev;
1459  dp->next = cur;
1460 
1461  cur->prev = dp;
1462  if (*head == cur) {
1463  *head = dp;
1464  } else {
1465  dp->prev->next = dp;
1466  }
1467  return 0;
1468  }
1469  }
1470  dp->prev = prev_cur;
1471  if (prev_cur != NULL)
1472  prev_cur->next = dp;
1473  } else {
1474  *head = dp;
1475  }
1476 
1477  return 0;
1478 }
1479 
1480 
1481 /**
1482  * \test Check if a DetectPort is properly allocated
1483  */
1484 static int PortTestParse01 (void)
1485 {
1486  DetectPort *dd = NULL;
1487  int r = DetectPortParse(NULL,&dd,"80");
1488  FAIL_IF_NOT(r == 0);
1489  DetectPortFree(NULL, dd);
1490  PASS;
1491 }
1492 
1493 /**
1494  * \test Check if two ports are properly allocated in the DetectPort group
1495  */
1496 static int PortTestParse02 (void)
1497 {
1498  DetectPort *dd = NULL;
1499  int r = DetectPortParse(NULL,&dd,"80");
1500  FAIL_IF_NOT(r == 0);
1501  r = DetectPortParse(NULL,&dd,"22");
1502  FAIL_IF_NOT(r == 0);
1503  DetectPortCleanupList(NULL, dd);
1504  PASS;
1505 }
1506 
1507 /**
1508  * \test Check if two port ranges are properly allocated in the DetectPort group
1509  */
1510 static int PortTestParse03 (void)
1511 {
1512  DetectPort *dd = NULL;
1513  int r = DetectPortParse(NULL,&dd,"80:88");
1514  FAIL_IF_NOT(r == 0);
1515  r = DetectPortParse(NULL,&dd,"85:100");
1516  FAIL_IF_NOT(r == 0);
1517  DetectPortCleanupList(NULL, dd);
1518  PASS;
1519 }
1520 
1521 /**
1522  * \test Check if a negated port range is properly allocated in the DetectPort
1523  */
1524 static int PortTestParse04 (void)
1525 {
1526  DetectPort *dd = NULL;
1527  int r = DetectPortParse(NULL,&dd,"!80:81");
1528  FAIL_IF_NOT(r == 0);
1529  DetectPortCleanupList(NULL, dd);
1530  PASS;
1531 }
1532 
1533 /**
1534  * \test Check if a negated port range is properly fragmented in the allowed
1535  * real groups, ex !80:81 should allow 0:79 and 82:65535
1536  */
1537 static int PortTestParse05 (void)
1538 {
1539  DetectPort *dd = NULL;
1540  int r = DetectPortParse(NULL,&dd,"!80:81");
1541  FAIL_IF_NOT(r == 0);
1542  FAIL_IF_NULL(dd->next);
1543  FAIL_IF_NOT(dd->port == 0);
1544  FAIL_IF_NOT(dd->port2 == 79);
1545  FAIL_IF_NOT(dd->next->port == 82);
1546  FAIL_IF_NOT(dd->next->port2 == 65535);
1547  DetectPortCleanupList(NULL, dd);
1548  PASS;
1549 }
1550 
1551 /**
1552  * \test Check if a negated port range is properly fragmented in the allowed
1553  * real groups
1554  */
1555 static int PortTestParse07 (void)
1556 {
1557  DetectPort *dd = NULL;
1558 
1559  int r = DetectPortParse(NULL,&dd,"!21:902");
1560  FAIL_IF_NOT(r == 0);
1561  FAIL_IF_NULL(dd->next);
1562 
1563  FAIL_IF_NOT(dd->port == 0);
1564  FAIL_IF_NOT(dd->port2 == 20);
1565  FAIL_IF_NOT(dd->next->port == 903);
1566  FAIL_IF_NOT(dd->next->port2 == 65535);
1567 
1568  DetectPortCleanupList(NULL, dd);
1569  PASS;
1570 }
1571 
1572 /**
1573  * \test Check if we dont allow invalid port range specification
1574  */
1575 static int PortTestParse08 (void)
1576 {
1577  DetectPort *dd = NULL;
1578 
1579  int r = DetectPortParse(NULL,&dd,"[80:!80]");
1580  FAIL_IF(r == 0);
1581 
1582  DetectPortCleanupList(NULL, dd);
1583  PASS;
1584 }
1585 
1586 /**
1587  * \test Check if we autocomplete correctly an open range
1588  */
1589 static int PortTestParse09 (void)
1590 {
1591  DetectPort *dd = NULL;
1592 
1593  int r = DetectPortParse(NULL,&dd,"1024:");
1594  FAIL_IF_NOT(r == 0);
1595  FAIL_IF_NULL(dd);
1596 
1597  FAIL_IF_NOT(dd->port == 1024);
1598  FAIL_IF_NOT(dd->port2 == 0xffff);
1599 
1600  DetectPortCleanupList(NULL, dd);
1601  PASS;
1602 }
1603 
1604 /**
1605  * \test Test we don't allow a port that is too big
1606  */
1607 static int PortTestParse10 (void)
1608 {
1609  DetectPort *dd = NULL;
1610  int r = DetectPortParse(NULL,&dd,"77777777777777777777777777777777777777777777");
1611  FAIL_IF(r == 0);
1612  PASS;
1613 }
1614 
1615 /**
1616  * \test Test second port of range being too big
1617  */
1618 static int PortTestParse11 (void)
1619 {
1620  DetectPort *dd = NULL;
1621 
1622  int r = DetectPortParse(NULL,&dd,"1024:65536");
1623  FAIL_IF(r == 0);
1624  PASS;
1625 }
1626 
1627 /**
1628  * \test Test second port of range being just right
1629  */
1630 static int PortTestParse12 (void)
1631 {
1632  DetectPort *dd = NULL;
1633  int r = DetectPortParse(NULL,&dd,"1024:65535");
1634  FAIL_IF_NOT(r == 0);
1635  DetectPortFree(NULL, dd);
1636  PASS;
1637 }
1638 
1639 /**
1640  * \test Test first port of range being too big
1641  */
1642 static int PortTestParse13 (void)
1643 {
1644  DetectPort *dd = NULL;
1645  int r = DetectPortParse(NULL,&dd,"65536:65535");
1646  FAIL_IF(r == 0);
1647  PASS;
1648 }
1649 
1650 /**
1651  * \test Test merging port groups
1652  */
1653 static int PortTestParse14 (void)
1654 {
1655  DetectPort *dd = NULL;
1656 
1657  int r = DetectPortParseInsertString(NULL, &dd, "0:100");
1658  FAIL_IF_NOT(r == 0);
1659  r = DetectPortParseInsertString(NULL, &dd, "1000:65535");
1660  FAIL_IF_NOT(r == 0);
1661  FAIL_IF_NULL(dd->next);
1662 
1663  FAIL_IF_NOT(dd->port == 0);
1664  FAIL_IF_NOT(dd->port2 == 100);
1665  FAIL_IF_NOT(dd->next->port == 1000);
1666  FAIL_IF_NOT(dd->next->port2 == 65535);
1667 
1668  DetectPortCleanupList(NULL, dd);
1669  PASS;
1670 }
1671 
1672 /**
1673  * \test Test merging negated port groups
1674  */
1675 static int PortTestParse15 (void)
1676 {
1677  DetectPort *dd = NULL;
1678 
1679  int r = DetectPortParse(NULL,&dd,"![0:100,1000:3000]");
1680  FAIL_IF_NOT(r == 0);
1681  FAIL_IF_NULL(dd->next);
1682 
1683  FAIL_IF_NOT(dd->port == 101);
1684  FAIL_IF_NOT(dd->port2 == 999);
1685  FAIL_IF_NOT(dd->next->port == 3001);
1686  FAIL_IF_NOT(dd->next->port2 == 65535);
1687 
1688  DetectPortCleanupList(NULL, dd);
1689  PASS;
1690 }
1691 
1692 static int PortTestParse16 (void)
1693 {
1694  DetectPort *dd = NULL;
1695  int r = DetectPortParse(NULL,&dd,"\
1696 [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\
1697 1:65535\
1698 ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\
1699 ");
1700  FAIL_IF_NOT(r == 0);
1701  DetectPortFree(NULL, dd);
1702  dd = NULL;
1703  r = DetectPortParse(NULL,&dd,"\
1704 [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\
1705 1:65535\
1706 ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\
1707 ");
1708  FAIL_IF(r == 0);
1709  PASS;
1710 }
1711 
1712 /**
1713  * \test Test general functions
1714  */
1715 static int PortTestFunctions01(void)
1716 {
1717  DetectPort *head = NULL;
1718  DetectPort *dp1= NULL;
1719  int result = 0;
1720 
1721  /* Parse */
1722  int r = DetectPortParse(NULL,&head,"![0:100,1000:65535]");
1723  if (r != 0 || head->next != NULL)
1724  goto end;
1725 
1726  /* We should have only one DetectPort */
1727  if (!(head->port == 101))
1728  goto end;
1729  if (!(head->port2 == 999))
1730  goto end;
1731  if (!(head->next == NULL))
1732  goto end;
1733 
1734  r = DetectPortParse(NULL, &dp1,"2000:3000");
1735  if (r != 0 || dp1->next != NULL)
1736  goto end;
1737  if (!(dp1->port == 2000))
1738  goto end;
1739  if (!(dp1->port2 == 3000))
1740  goto end;
1741 
1742  /* Add */
1743  r = PortTestDetectPortAdd(&head, dp1);
1744  if (r != 0 || head->next == NULL)
1745  goto end;
1746  if (!(head->port == 101))
1747  goto end;
1748  if (!(head->port2 == 999))
1749  goto end;
1750  if (!(head->next->port == 2000))
1751  goto end;
1752  if (!(head->next->port2 == 3000))
1753  goto end;
1754 
1755  /* Match */
1756  if (!DetectPortMatch(head, 150))
1757  goto end;
1758  if (DetectPortMatch(head->next, 1500))
1759  goto end;
1760  if ((DetectPortMatch(head, 3500)))
1761  goto end;
1762  if ((DetectPortMatch(head, 50)))
1763  goto end;
1764 
1765  result = 1;
1766 end:
1767  if (dp1 != NULL)
1768  DetectPortFree(NULL, dp1);
1769  if (head != NULL)
1770  DetectPortFree(NULL, head);
1771  return result;
1772 }
1773 
1774 /**
1775  * \test Test general functions
1776  */
1777 static int PortTestFunctions02(void)
1778 {
1779  DetectPort *head = NULL;
1780  DetectPort *dp1= NULL;
1781  DetectPort *dp2= NULL;
1782  int result = 0;
1783 
1784  /* Parse */
1785  int r = DetectPortParse(NULL,&head, "![0:100,1000:65535]");
1786  if (r != 0 || head->next != NULL)
1787  goto end;
1788 
1789  r = DetectPortParse(NULL, &dp1, "!200:300");
1790  if (r != 0 || dp1->next == NULL)
1791  goto end;
1792 
1793  /* Merge Nots */
1794  r = DetectPortParseMergeNotPorts(NULL, &head, &dp1);
1795  if (r != 0 || head->next != NULL)
1796  goto end;
1797 
1798  r = DetectPortParse(NULL, &dp2, "!100:500");
1799  if (r != 0 || dp2->next == NULL)
1800  goto end;
1801 
1802  /* Merge Nots */
1803  r = DetectPortParseMergeNotPorts(NULL, &head, &dp2);
1804  if (r != 0 || head->next != NULL)
1805  goto end;
1806 
1807  if (!(head->port == 200))
1808  goto end;
1809  if (!(head->port2 == 300))
1810  goto end;
1811 
1812  result = 1;
1813 
1814 end:
1815  if (dp1 != NULL)
1816  DetectPortFree(NULL, dp1);
1817  if (dp2 != NULL)
1818  DetectPortFree(NULL, dp2);
1819  if (head != NULL)
1820  DetectPortFree(NULL, head);
1821  return result;
1822 }
1823 
1824 /**
1825  * \test Test general functions
1826  */
1827 static int PortTestFunctions03(void)
1828 {
1829  DetectPort *dp1= NULL;
1830  DetectPort *dp2= NULL;
1831  DetectPort *dp3= NULL;
1832  int result = 0;
1833 
1834  int r = DetectPortParse(NULL, &dp1, "200:300");
1835  if (r != 0)
1836  goto end;
1837 
1838  r = DetectPortParse(NULL, &dp2, "250:300");
1839  if (r != 0)
1840  goto end;
1841 
1842  /* Cut */
1843  DetectPortCut(NULL, dp1, dp2, &dp3);
1844  if (r != 0)
1845  goto end;
1846 
1847  if (!(dp1->port == 200))
1848  goto end;
1849  if (!(dp1->port2 == 249))
1850  goto end;
1851  if (!(dp2->port == 250))
1852  goto end;
1853  if (!(dp2->port2 == 300))
1854  goto end;
1855 
1856  dp1->port = 0;
1857  dp1->port2 = 500;
1858  dp2->port = 250;
1859  dp2->port2 = 750;
1860 
1861  /* Cut */
1862  DetectPortCut(NULL, dp1, dp2, &dp3);
1863  if (r != 0)
1864  goto end;
1865  if (!(dp1->port == 0))
1866  goto end;
1867  if (!(dp1->port2 == 249))
1868  goto end;
1869  if (!(dp2->port == 250))
1870  goto end;
1871  if (!(dp2->port2 == 500))
1872  goto end;
1873  if (!(dp3->port == 501))
1874  goto end;
1875  if (!(dp3->port2 == 750))
1876  goto end;
1877 
1878  result = 1;
1879 
1880 end:
1881  if (dp1 != NULL)
1882  DetectPortFree(NULL, dp1);
1883  if (dp2 != NULL)
1884  DetectPortFree(NULL, dp2);
1885  if (dp3 != NULL)
1886  DetectPortFree(NULL, dp3);
1887  return result;
1888 }
1889 
1890 /**
1891  * \test Test general functions
1892  */
1893 static int PortTestFunctions04(void)
1894 {
1895  DetectPort *dp1= NULL;
1896  DetectPort *dp2= NULL;
1897  int result = 0;
1898 
1899  int r = DetectPortParse(NULL, &dp1, "200:300");
1900  if (r != 0)
1901  goto end;
1902 
1903  dp2 = DetectPortInit();
1904 
1905  /* Cut Not */
1906  DetectPortCutNot(dp1, &dp2);
1907  if (r != 0)
1908  goto end;
1909 
1910  if (!(dp1->port == 0))
1911  goto end;
1912  if (!(dp1->port2 == 199))
1913  goto end;
1914  if (!(dp2->port == 301))
1915  goto end;
1916  if (!(dp2->port2 == 65535))
1917  goto end;
1918 
1919  result = 1;
1920 end:
1921  if (dp1 != NULL)
1922  DetectPortFree(NULL, dp1);
1923  if (dp2 != NULL)
1924  DetectPortFree(NULL, dp2);
1925  return result;
1926 }
1927 
1928 /**
1929  * \test Test general functions
1930  */
1931 static int PortTestFunctions07(void)
1932 {
1933  DetectPort *dd = NULL;
1934 
1935  // This one should fail due to negation in a range
1936  FAIL_IF(DetectPortParse(NULL, &dd, "[80:!99]") == 0);
1937 
1938  // Correct: from 80 till 100 but 99 excluded
1939  FAIL_IF_NOT(DetectPortParse(NULL, &dd, "[80:100,!99]") == 0);
1940  FAIL_IF_NULL(dd->next);
1941  FAIL_IF_NOT(dd->port == 80);
1942  FAIL_IF_NOT(dd->port2 == 98);
1943  FAIL_IF_NOT(dd->next->port == 100);
1944 
1945  // Also good: from 1 till 80 except of 2 and 4
1946  FAIL_IF_NOT(DetectPortParse(NULL, &dd, "[1:80,![2,4]]") == 0);
1947  FAIL_IF_NOT(dd->port == 1);
1951 
1952  DetectPortCleanupList(NULL, dd);
1953  PASS;
1954 }
1955 
1956 /**
1957  * \test Test packet Matches
1958  * \param raw_eth_pkt pointer to the ethernet packet
1959  * \param pktsize size of the packet
1960  * \param sig pointer to the signature to test
1961  * \param sid sid number of the signature
1962  * \retval return 1 if match
1963  * \retval return 0 if not
1964  */
1965 static int PortTestMatchReal(uint8_t *raw_eth_pkt, uint16_t pktsize, const char *sig,
1966  uint32_t sid)
1967 {
1968  int result = 0;
1970  Packet *p = UTHBuildPacketFromEth(raw_eth_pkt, pktsize);
1971  result = UTHPacketMatchSig(p, sig);
1972  PacketRecycle(p);
1973  FlowShutdown();
1974  return result;
1975 }
1976 
1977 /**
1978  * \brief Wrapper for PortTestMatchReal
1979  */
1980 static int PortTestMatchRealWrp(const char *sig, uint32_t sid)
1981 {
1982  /* Real HTTP packeth doing a GET method
1983  * tcp.sport=47370 tcp.dport=80
1984  * ip.src=192.168.28.131 ip.dst=192.168.1.1
1985  */
1986  uint8_t raw_eth_pkt[] = {
1987  0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
1988  0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
1989  0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
1990  0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
1991  0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
1992  0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
1993  0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
1994  0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
1995  0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
1996  0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
1997  0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
1998  0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
1999  0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
2000  0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
2001  0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
2002  0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
2003  0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
2004  0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
2005  0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
2006  0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
2007  0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
2008  0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
2009  0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
2010  0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
2011  0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
2012  0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
2013  0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
2014  0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
2015  0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
2016  0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
2017  0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
2018  0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
2019  0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
2020  0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
2021  0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
2022  0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
2023  0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
2024  0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
2025  0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
2026  0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
2027  0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
2028  0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
2029  0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
2030  0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
2031  0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
2032  0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
2033  0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
2034  0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
2035  0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
2036  0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
2037  0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
2038  0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
2039  0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
2040  0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
2041  0x76,0x65,0x0d,0x0a,0x0d,0x0a };
2042  /* end raw_eth_pkt */
2043 
2044  return PortTestMatchReal(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
2045  sig, sid);
2046 }
2047 
2048 /**
2049  * \test Check if we match a dest port
2050  */
2051 static int PortTestMatchReal01(void)
2052 {
2053  /* tcp.sport=47370 tcp.dport=80 */
2054  const char *sig = "alert tcp any any -> any 80 (msg:\"Nothing..\"; content:\"GET\"; sid:1;)";
2055  return PortTestMatchRealWrp(sig, 1);
2056 }
2057 
2058 /**
2059  * \test Check if we match a source port
2060  */
2061 static int PortTestMatchReal02(void)
2062 {
2063  const char *sig = "alert tcp any 47370 -> any any (msg:\"Nothing..\";"
2064  " content:\"GET\"; sid:1;)";
2065  return PortTestMatchRealWrp(sig, 1);
2066 }
2067 
2068 /**
2069  * \test Check if we match both of them
2070  */
2071 static int PortTestMatchReal03(void)
2072 {
2073  const char *sig = "alert tcp any 47370 -> any 80 (msg:\"Nothing..\";"
2074  " content:\"GET\"; sid:1;)";
2075  return PortTestMatchRealWrp(sig, 1);
2076 }
2077 
2078 /**
2079  * \test Check if we negate dest ports correctly
2080  */
2081 static int PortTestMatchReal04(void)
2082 {
2083  const char *sig = "alert tcp any any -> any !80 (msg:\"Nothing..\";"
2084  " content:\"GET\"; sid:1;)";
2085  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2086 }
2087 
2088 /**
2089  * \test Check if we negate source ports correctly
2090  */
2091 static int PortTestMatchReal05(void)
2092 {
2093  const char *sig = "alert tcp any !47370 -> any any (msg:\"Nothing..\";"
2094  " content:\"GET\"; sid:1;)";
2095  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2096 }
2097 
2098 /**
2099  * \test Check if we negate both ports correctly
2100  */
2101 static int PortTestMatchReal06(void)
2102 {
2103  const char *sig = "alert tcp any !47370 -> any !80 (msg:\"Nothing..\";"
2104  " content:\"GET\"; sid:1;)";
2105  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2106 }
2107 
2108 /**
2109  * \test Check if we match a dest port range
2110  */
2111 static int PortTestMatchReal07(void)
2112 {
2113  const char *sig = "alert tcp any any -> any 70:100 (msg:\"Nothing..\";"
2114  " content:\"GET\"; sid:1;)";
2115  return PortTestMatchRealWrp(sig, 1);
2116 }
2117 
2118 /**
2119  * \test Check if we match a source port range
2120  */
2121 static int PortTestMatchReal08(void)
2122 {
2123  const char *sig = "alert tcp any 47000:50000 -> any any (msg:\"Nothing..\";"
2124  " content:\"GET\"; sid:1;)";
2125  return PortTestMatchRealWrp(sig, 1);
2126 }
2127 
2128 /**
2129  * \test Check if we match both port ranges
2130  */
2131 static int PortTestMatchReal09(void)
2132 {
2133  const char *sig = "alert tcp any 47000:50000 -> any 70:100 (msg:\"Nothing..\";"
2134  " content:\"GET\"; sid:1;)";
2135  return PortTestMatchRealWrp(sig, 1);
2136 }
2137 
2138 /**
2139  * \test Check if we negate a dest port range
2140  */
2141 static int PortTestMatchReal10(void)
2142 {
2143  const char *sig = "alert tcp any any -> any !70:100 (msg:\"Nothing..\";"
2144  " content:\"GET\"; sid:1;)";
2145  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2146 }
2147 
2148 /**
2149  * \test Check if we negate a source port range
2150  */
2151 static int PortTestMatchReal11(void)
2152 {
2153  const char *sig = "alert tcp any !47000:50000 -> any any (msg:\"Nothing..\";"
2154  " content:\"GET\"; sid:1;)";
2155  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2156 }
2157 
2158 /**
2159  * \test Check if we negate both port ranges
2160  */
2161 static int PortTestMatchReal12(void)
2162 {
2163  const char *sig = "alert tcp any !47000:50000 -> any !70:100 (msg:\"Nothing..\";"
2164  " content:\"GET\"; sid:1;)";
2165  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2166 }
2167 
2168 /**
2169  * \test Check if we autocomplete ranges correctly
2170  */
2171 static int PortTestMatchReal13(void)
2172 {
2173  const char *sig = "alert tcp any 47000:50000 -> any !81: (msg:\"Nothing..\";"
2174  " content:\"GET\"; sid:1;)";
2175  return PortTestMatchRealWrp(sig, 1);
2176 }
2177 
2178 /**
2179  * \test Check if we autocomplete ranges correctly
2180  */
2181 static int PortTestMatchReal14(void)
2182 {
2183  const char *sig = "alert tcp any !48000:50000 -> any :100 (msg:\"Nothing..\";"
2184  " content:\"GET\"; sid:1;)";
2185  return PortTestMatchRealWrp(sig, 1);
2186 }
2187 
2188 /**
2189  * \test Check if we autocomplete ranges correctly
2190  */
2191 static int PortTestMatchReal15(void)
2192 {
2193  const char *sig = "alert tcp any :50000 -> any 81:100 (msg:\"Nothing..\";"
2194  " content:\"GET\"; sid:1;)";
2195  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2196 }
2197 
2198 /**
2199  * \test Check if we separate ranges correctly
2200  */
2201 static int PortTestMatchReal16(void)
2202 {
2203  const char *sig = "alert tcp any 100: -> any ![0:79,81:65535] (msg:\"Nothing..\";"
2204  " content:\"GET\"; sid:1;)";
2205  return PortTestMatchRealWrp(sig, 1);
2206 }
2207 
2208 /**
2209  * \test Check if we separate ranges correctly
2210  */
2211 static int PortTestMatchReal17(void)
2212 {
2213  const char *sig = "alert tcp any ![0:39999,48000:50000] -> any ![0:80,82:65535] "
2214  "(msg:\"Nothing..\"; content:\"GET\"; sid:1;)";
2215  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2216 }
2217 
2218 /**
2219  * \test Check if we separate ranges correctly
2220  */
2221 static int PortTestMatchReal18(void)
2222 {
2223  const char *sig = "alert tcp any ![0:39999,48000:50000] -> any 80 (msg:\"Nothing"
2224  " at all\"; content:\"GET\"; sid:1;)";
2225  return PortTestMatchRealWrp(sig, 1);
2226 }
2227 
2228 /**
2229  * \test Check if we separate ranges correctly
2230  */
2231 static int PortTestMatchReal19(void)
2232 {
2233  const char *sig = "alert tcp any any -> any 80 (msg:\"Nothing..\";"
2234  " content:\"GET\"; sid:1;)";
2235  return PortTestMatchRealWrp(sig, 1);
2236 }
2237 
2238 static int PortTestMatchDoubleNegation(void)
2239 {
2240  int result = 0;
2241  DetectPort *head = NULL, *nhead = NULL;
2242 
2243  if (DetectPortParseDo(NULL, &head, &nhead, "![!80]", 0, NULL, 0) == -1)
2244  return result;
2245 
2246  result = (head != NULL);
2247  result = (nhead == NULL);
2248 
2249  return result;
2250 }
2251 
2252 // Test that negation is successfully parsed with whitespace for port strings of
2253 // length < 16
2254 static int DetectPortParseDoTest(void)
2255 {
2258  DetectPort *head = NULL;
2259  DetectPort *nhead = NULL;
2260  const char *str = "[30:50, !45]";
2261  int r = DetectPortParseDo(de_ctx, &head, &nhead, str, 0, NULL, 0);
2262 
2263  // Assertions
2264  FAIL_IF_NULL(head);
2265  FAIL_IF_NULL(nhead);
2266  FAIL_IF(r < 0);
2267  FAIL_IF(head->port != 30);
2268  FAIL_IF(head->port2 != 50);
2269  FAIL_IF(nhead->port != 45);
2270  FAIL_IF(nhead->port2 != 45);
2271  DetectPortCleanupList(NULL, head);
2272  DetectPortCleanupList(NULL, nhead);
2273  PASS;
2274 }
2275 
2276 static int DetectPortParseDoTest2(void)
2277 {
2280  DetectPort *head = NULL;
2281  DetectPort *nhead = NULL;
2282  const char *str = "[30:50, !45]";
2283  int r = DetectPortParseDo(de_ctx, &head, &nhead, str, 0, NULL, 0);
2284  FAIL_IF(r < 0);
2285  DetectPortCleanupList(NULL, head);
2286  DetectPortCleanupList(NULL, nhead);
2287  PASS;
2288 }
2289 
2290 // Verifies correct parsing when negation port string length < 16
2291 static int PortParseTestLessThan14Spaces(void)
2292 {
2293  const char *str = " 45";
2294  DetectPort *dp = PortParse(str);
2295  FAIL_IF_NULL(dp);
2296  FAIL_IF(dp->port != 45);
2297  FAIL_IF(dp->port2 != 45);
2298  DetectPortFree(NULL, dp);
2299  PASS;
2300 }
2301 
2302 // Verifies NULL returned when negation port string length == 16
2303 static int PortParseTest14Spaces(void)
2304 {
2305  const char *str = " 45";
2306  DetectPort *dp = PortParse(str);
2307  FAIL_IF_NULL(dp);
2308  FAIL_IF(dp->port != 45);
2309  FAIL_IF(dp->port2 != 45);
2310  DetectPortFree(NULL, dp);
2311  PASS;
2312 }
2313 
2314 // Verifies NULL returned when negation port string length >= 16
2315 static int PortParseTestMoreThan14Spaces(void)
2316 {
2317  const char *str = " 45";
2318  DetectPort *dp = PortParse(str);
2319  FAIL_IF_NULL(dp);
2320  FAIL_IF(dp->port != 45);
2321  FAIL_IF(dp->port2 != 45);
2322  DetectPortFree(NULL, dp);
2323  PASS;
2324 }
2325 
2326 void DetectPortTests(void)
2327 {
2328  UtRegisterTest("PortTestParse01", PortTestParse01);
2329  UtRegisterTest("PortTestParse02", PortTestParse02);
2330  UtRegisterTest("PortTestParse03", PortTestParse03);
2331  UtRegisterTest("PortTestParse04", PortTestParse04);
2332  UtRegisterTest("PortTestParse05", PortTestParse05);
2333  UtRegisterTest("PortTestParse07", PortTestParse07);
2334  UtRegisterTest("PortTestParse08", PortTestParse08);
2335  UtRegisterTest("PortTestParse09", PortTestParse09);
2336  UtRegisterTest("PortTestParse10", PortTestParse10);
2337  UtRegisterTest("PortTestParse11", PortTestParse11);
2338  UtRegisterTest("PortTestParse12", PortTestParse12);
2339  UtRegisterTest("PortTestParse13", PortTestParse13);
2340  UtRegisterTest("PortTestParse14", PortTestParse14);
2341  UtRegisterTest("PortTestParse15", PortTestParse15);
2342  UtRegisterTest("PortTestParse16", PortTestParse16);
2343  UtRegisterTest("PortTestFunctions01", PortTestFunctions01);
2344  UtRegisterTest("PortTestFunctions02", PortTestFunctions02);
2345  UtRegisterTest("PortTestFunctions03", PortTestFunctions03);
2346  UtRegisterTest("PortTestFunctions04", PortTestFunctions04);
2347  UtRegisterTest("PortTestFunctions07", PortTestFunctions07);
2348  UtRegisterTest("PortTestMatchReal01", PortTestMatchReal01);
2349  UtRegisterTest("PortTestMatchReal02", PortTestMatchReal02);
2350  UtRegisterTest("PortTestMatchReal03", PortTestMatchReal03);
2351  UtRegisterTest("PortTestMatchReal04", PortTestMatchReal04);
2352  UtRegisterTest("PortTestMatchReal05", PortTestMatchReal05);
2353  UtRegisterTest("PortTestMatchReal06", PortTestMatchReal06);
2354  UtRegisterTest("PortTestMatchReal07", PortTestMatchReal07);
2355  UtRegisterTest("PortTestMatchReal08", PortTestMatchReal08);
2356  UtRegisterTest("PortTestMatchReal09", PortTestMatchReal09);
2357  UtRegisterTest("PortTestMatchReal10", PortTestMatchReal10);
2358  UtRegisterTest("PortTestMatchReal11", PortTestMatchReal11);
2359  UtRegisterTest("PortTestMatchReal12", PortTestMatchReal12);
2360  UtRegisterTest("PortTestMatchReal13", PortTestMatchReal13);
2361  UtRegisterTest("PortTestMatchReal14", PortTestMatchReal14);
2362  UtRegisterTest("PortTestMatchReal15", PortTestMatchReal15);
2363  UtRegisterTest("PortTestMatchReal16", PortTestMatchReal16);
2364  UtRegisterTest("PortTestMatchReal17", PortTestMatchReal17);
2365  UtRegisterTest("PortTestMatchReal18", PortTestMatchReal18);
2366  UtRegisterTest("PortTestMatchReal19", PortTestMatchReal19);
2367  UtRegisterTest("PortTestMatchDoubleNegation", PortTestMatchDoubleNegation);
2368  UtRegisterTest("DetectPortParseDoTest", DetectPortParseDoTest);
2369  UtRegisterTest("DetectPortParseDoTest2", DetectPortParseDoTest2);
2370  UtRegisterTest("PortParseTestLessThan14Spaces", PortParseTestLessThan14Spaces);
2371  UtRegisterTest("PortParseTest14Spaces", PortParseTest14Spaces);
2372  UtRegisterTest("PortParseTestMoreThan14Spaces", PortParseTestMoreThan14Spaces);
2373 }
2374 
2375 #endif /* UNITTESTS */
DetectEngineCtx_::sgh_hash_table
HashListTable * sgh_hash_table
Definition: detect.h:962
util-byte.h
host.h
DetectPortCmp
int DetectPortCmp(DetectPort *a, DetectPort *b)
Function that compare port groups.
Definition: detect-engine-port.c:497
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
PORT_GT
@ PORT_GT
Definition: detect.h:212
DetectPortHashInit
int DetectPortHashInit(DetectEngineCtx *de_ctx)
Initializes the hash table in the detection engine context to hold the DetectPort hash.
Definition: detect-engine-port.c:1371
detect-engine-siggroup.h
DetectPortListsAreEqual
bool DetectPortListsAreEqual(DetectPort *list1, DetectPort *list2)
Checks if two port group lists are equal.
Definition: detect-engine-port.c:638
DetectPortInsert
int DetectPortInsert(DetectEngineCtx *de_ctx, DetectPort **head, DetectPort *new)
function for inserting a port group object. This also makes sure SigGroupContainer lists are handled ...
Definition: detect-engine-port.c:153
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectPortFree
void DetectPortFree(const DetectEngineCtx *de_ctx, DetectPort *dp)
Free a DetectPort and its members.
Definition: detect-engine-port.c:80
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:275
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
DetectPort_::port
uint16_t port
Definition: detect.h:221
PORT_SIGGROUPHEAD_COPY
#define PORT_SIGGROUPHEAD_COPY
Definition: detect.h:217
PacketRecycle
void PacketRecycle(Packet *p)
Definition: packet.c:150
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:932
StringParseUint16
int StringParseUint16(uint16_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:343
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
DetectPort_::next
struct DetectPort_ * next
Definition: detect.h:234
UTHPacketMatchSig
int UTHPacketMatchSig(Packet *p, const char *sig)
Definition: util-unittest-helper.c:810
DetectEngineCtx_::dport_hash_table
HashListTable * dport_hash_table
Definition: detect.h:1066
DetectPort_::sh
struct SigGroupHead_ * sh
Definition: detect.h:231
DetectPortPrintList
void DetectPortPrintList(DetectPort *head)
Helper function used to print the list of ports present in this DetectPort list.
Definition: detect-engine-port.c:100
HashListTableLookup
void * HashListTableLookup(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:245
CleanVariableResolveList
void CleanVariableResolveList(ResolvedVariablesList *var_list)
Definition: util-var.c:168
DetectPortTestConfVars
int DetectPortTestConfVars(void)
Definition: detect-engine-port.c:1107
util-var.h
PortParse
DetectPort * PortParse(const char *str)
Helper function for parsing port strings.
Definition: detect-engine-port.c:1219
DetectPort_::port2
uint16_t port2
Definition: detect.h:222
DetectPortInit
DetectPort * DetectPortInit(void)
Alloc a DetectPort structure and update counters.
Definition: detect-engine-port.c:67
util-unittest.h
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
DetectPort_::flags
uint8_t flags
Definition: detect.h:224
DetectPortPrint
void DetectPortPrint(DetectPort *dp)
Helper function that print the DetectPort info.
Definition: detect-engine-port.c:590
HashListTableAdd
int HashListTableAdd(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:114
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
HashListTable_::array_size
uint32_t array_size
Definition: util-hashlist.h:41
PORT_LT
@ PORT_LT
Definition: detect.h:206
FlowInitConfig
void FlowInitConfig(bool quiet)
initialize the configuration
Definition: flow.c:546
DetectPortCopySingle
DetectPort * DetectPortCopySingle(DetectEngineCtx *de_ctx, DetectPort *src)
Function that return a copy of DetectPort src sigs.
Definition: detect-engine-port.c:550
util-cidr.h
DetectPortParse
int DetectPortParse(const DetectEngineCtx *de_ctx, DetectPort **head, const char *str)
Function for parsing port strings.
Definition: detect-engine-port.c:1183
TAILQ_HEAD_INITIALIZER
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:236
HashListTableInit
HashListTable * HashListTableInit(uint32_t size, uint32_t(*Hash)(struct HashListTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
Definition: util-hashlist.c:35
PORT_FLAG_ANY
#define PORT_FLAG_ANY
Definition: detect.h:215
decode.h
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
util-debug.h
SC_RULE_VARS_PORT_GROUPS
@ SC_RULE_VARS_PORT_GROUPS
Definition: util-rule-vars.h:32
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
util-error.h
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
PORT_ES
@ PORT_ES
Definition: detect.h:209
SCEnter
#define SCEnter(...)
Definition: util-debug.h:277
detect-engine-mpm.h
detect.h
StreamContentInspectEngineData::s
const Signature * s
Definition: detect-engine-payload.c:265
pkt-var.h
detect-engine-port.h
DetectPort_
Port structure for detection engine.
Definition: detect.h:220
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:317
util-profiling.h
util-rule-vars.h
Packet_
Definition: decode.h:501
conf.h
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:293
HashListTable_
Definition: util-hashlist.h:37
SigGroupHeadFree
void SigGroupHeadFree(const DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Free a SigGroupHead and its members.
Definition: detect-engine-siggroup.c:163
PORT_ER
@ PORT_ER
Definition: detect.h:205
Flow_::next
struct Flow_ * next
Definition: flow.h:388
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
suricata-common.h
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:88
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:690
packet.h
DetectPort_::prev
struct DetectPort_ * prev
Definition: detect.h:233
PORT_GE
@ PORT_GE
Definition: detect.h:211
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:308
SCConfGetNode
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition: conf.c:181
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:267
head
Flow * head
Definition: flow-hash.h:1
SCFree
#define SCFree(p)
Definition: util-mem.h:61
detect-parse.h
src
uint16_t src
Definition: app-layer-dnp3.h:5
AddVariableToResolveList
int AddVariableToResolveList(ResolvedVariablesList *list, const char *var)
Definition: util-var.c:139
UTHBuildPacketFromEth
Packet * UTHBuildPacketFromEth(uint8_t *raw_eth, uint16_t pktsize)
UTHBuildPacketFromEth is a wrapper that build a packet for the rawbytes.
Definition: util-unittest-helper.c:382
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2602
PORT_FLAG_NOT
#define PORT_FLAG_NOT
Definition: detect.h:216
DetectPortHashAdd
int DetectPortHashAdd(DetectEngineCtx *de_ctx, DetectPort *dp)
Adds a DetectPort to the detection engine context DetectPort hash table.
Definition: detect-engine-port.c:1391
FLOW_QUIET
#define FLOW_QUIET
Definition: flow.h:43
SCConfNode_::name
char * name
Definition: conf.h:38
DetectPortTests
void DetectPortTests(void)
PORT_EQ
@ PORT_EQ
Definition: detect.h:208
dst
uint16_t dst
Definition: app-layer-dnp3.h:4
PORT_EB
@ PORT_EB
Definition: detect.h:210
DetectPortHashFree
void DetectPortHashFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by DetectPortInit() function.
Definition: detect-engine-port.c:1422
SCRuleVarsGetConfVar
const char * SCRuleVarsGetConfVar(const DetectEngineCtx *de_ctx, const char *conf_var_name, SCRuleVarsType conf_vars_type)
Definition: util-rule-vars.c:65
DetectPortHashLookup
DetectPort * DetectPortHashLookup(DetectEngineCtx *de_ctx, DetectPort *dp)
Used to lookup a DetectPort hash from the detection engine context DetectPort hash table.
Definition: detect-engine-port.c:1407
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCConfNode_
Definition: conf.h:37
flow-var.h
SCConfNode_::val
char * val
Definition: conf.h:39
DetectPortCleanupList
void DetectPortCleanupList(const DetectEngineCtx *de_ctx, DetectPort *head)
Free a DetectPort list and each of its members.
Definition: detect-engine-port.c:124
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:767
PORT_LE
@ PORT_LE
Definition: detect.h:207
DetectPortLookupGroup
DetectPort * DetectPortLookupGroup(DetectPort *dp, uint16_t port)
Function that find the group matching port in a group head.
Definition: detect-engine-port.c:613
SigGroupHeadCopySigs
int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHead **dst)
Copies the bitarray holding the sids from the source SigGroupHead to the destination SigGroupHead.
Definition: detect-engine-siggroup.c:390