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 = 0, x = 0; 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  x--;
811  } else if (s[u] == '[') {
812  if (!o_set) {
813  o_set = 1;
814  x = 0;
815  }
816  depth++;
817  } else if (s[u] == ']') {
818  if (depth == 1) {
819  port[x - 1] = '\0';
820  SCLogDebug("Parsed port from DetectPortParseDo - %s", port);
821  x = 0;
822 
823  r = DetectPortParseDo(
824  de_ctx, head, nhead, port, negate ? negate : n_set, var_list, recur);
825  if (r == -1)
826  goto error;
827 
828  n_set = 0;
829  }
830  depth--;
831  range = 0;
832  } else if (depth == 0 && s[u] == ',') {
833  if (o_set == 1) {
834  o_set = 0;
835  } else if (d_set == 1) {
836  char *temp_rule_var_port = NULL,
837  *alloc_rule_var_port = NULL;
838 
839  port[x - 1] = '\0';
840 
841  rule_var_port = SCRuleVarsGetConfVar(de_ctx, port, SC_RULE_VARS_PORT_GROUPS);
842  if (rule_var_port == NULL)
843  goto error;
844  if (strlen(rule_var_port) == 0) {
845  SCLogError("variable %s resolved "
846  "to nothing. This is likely a misconfiguration. "
847  "Note that a negated port needs to be quoted, "
848  "\"!$HTTP_PORTS\" instead of !$HTTP_PORTS. See issue #295.",
849  s);
850  goto error;
851  }
852  if (negate == 1 || n_set == 1) {
853  alloc_rule_var_port = SCMalloc(strlen(rule_var_port) + 3);
854  if (unlikely(alloc_rule_var_port == NULL))
855  goto error;
856  snprintf(alloc_rule_var_port, strlen(rule_var_port) + 3,
857  "[%s]", rule_var_port);
858  } else {
859  alloc_rule_var_port = SCStrdup(rule_var_port);
860  if (unlikely(alloc_rule_var_port == NULL))
861  goto error;
862  }
863  temp_rule_var_port = alloc_rule_var_port;
864  r = DetectPortParseDo(de_ctx, head, nhead, temp_rule_var_port,
865  (negate + n_set) % 2, var_list, recur);
866  if (r == -1) {
867  SCFree(alloc_rule_var_port);
868  goto error;
869  }
870  d_set = 0;
871  n_set = 0;
872  SCFree(alloc_rule_var_port);
873  } else {
874  port[x - 1] = '\0';
875  SCLogDebug("Parsed port from DetectPortParseDo - %s", port);
876 
877  if (negate == 0 && n_set == 0) {
878  r = DetectPortParseInsertString(de_ctx, head, port);
879  } else {
880  r = DetectPortParseInsertString(de_ctx, nhead, port);
881  }
882  if (r == -1)
883  goto error;
884 
885  n_set = 0;
886  }
887  x = 0;
888  range = 0;
889  } else if (depth == 0 && s[u] == '$') {
890  d_set = 1;
891  } else if (depth == 0 && u == size-1) {
892  range = 0;
893  if (x == 1024) {
894  port[x - 1] = '\0';
895  } else {
896  port[x] = '\0';
897  }
898  SCLogDebug("%s", port);
899 
900  if (AddVariableToResolveList(var_list, port) == -1) {
901  SCLogError("Found a loop in a port "
902  "groups declaration. This is likely a misconfiguration.");
903  goto error;
904  }
905 
906  x = 0;
907  if (d_set == 1) {
908  char *temp_rule_var_port = NULL,
909  *alloc_rule_var_port = NULL;
910 
911  rule_var_port = SCRuleVarsGetConfVar(de_ctx, port, SC_RULE_VARS_PORT_GROUPS);
912  if (rule_var_port == NULL)
913  goto error;
914  if (strlen(rule_var_port) == 0) {
915  SCLogError("variable %s resolved "
916  "to nothing. This is likely a misconfiguration. "
917  "Note that a negated port needs to be quoted, "
918  "\"!$HTTP_PORTS\" instead of !$HTTP_PORTS. See issue #295.",
919  s);
920  goto error;
921  }
922  if ((negate + n_set) % 2) {
923  alloc_rule_var_port = SCMalloc(strlen(rule_var_port) + 3);
924  if (unlikely(alloc_rule_var_port == NULL))
925  goto error;
926  snprintf(alloc_rule_var_port, strlen(rule_var_port) + 3,
927  "[%s]", rule_var_port);
928  } else {
929  alloc_rule_var_port = SCStrdup(rule_var_port);
930  if (unlikely(alloc_rule_var_port == NULL))
931  goto error;
932  }
933  temp_rule_var_port = alloc_rule_var_port;
934  r = DetectPortParseDo(de_ctx, head, nhead, temp_rule_var_port,
935  (negate + n_set) % 2, var_list, recur);
936  SCFree(alloc_rule_var_port);
937  if (r == -1)
938  goto error;
939 
940  d_set = 0;
941  } else {
942  if (!((negate + n_set) % 2)) {
943  r = DetectPortParseInsertString(de_ctx, head, port);
944  } else {
945  r = DetectPortParseInsertString(de_ctx, nhead, port);
946  }
947  if (r == -1)
948  goto error;
949  }
950  n_set = 0;
951  } else if (depth == 1 && s[u] == ',') {
952  range = 0;
953  }
954  }
955 
956  if (depth > 0) {
957  SCLogError("not every port block was "
958  "properly closed in \"%s\", %d missing closing brackets (]). "
959  "Note: problem might be in a variable.",
960  s, depth);
961  goto error;
962  } else if (depth < 0) {
963  SCLogError("not every port block was "
964  "properly opened in \"%s\", %d missing opening brackets ([). "
965  "Note: problem might be in a variable.",
966  s, depth * -1);
967  goto error;
968  }
969 
970  return 0;
971 error:
972  return -1;
973 }
974 
975 /**
976  * \brief Check if the port group list covers the complete port space.
977  * \retval 0 no
978  * \retval 1 yes
979  */
980 static int DetectPortIsCompletePortSpace(DetectPort *p)
981 {
982  uint16_t next_port = 0;
983 
984  if (p == NULL)
985  return 0;
986 
987  if (p->port != 0x0000)
988  return 0;
989 
990  /* if we're ending with 0xFFFF while we know
991  we started with 0x0000 it's the complete space */
992  if (p->port2 == 0xFFFF)
993  return 1;
994 
995  next_port = p->port2 + 1;
996  p = p->next;
997 
998  for ( ; p != NULL; p = p->next) {
999  if (p->port != next_port)
1000  return 0;
1001 
1002  if (p->port2 == 0xFFFF)
1003  return 1;
1004 
1005  next_port = p->port2 + 1;
1006  }
1007 
1008  return 0;
1009 }
1010 
1011 /**
1012  * \brief Helper function for the parsing process
1013  *
1014  * \param head Pointer to the head of the DetectPort group list
1015  * \param nhead Pointer to the new head of the DetectPort group list
1016  *
1017  * \retval 0 on success
1018  * \retval -1 on error
1019  */
1020 static int DetectPortParseMergeNotPorts(const DetectEngineCtx *de_ctx,
1021  DetectPort **head, DetectPort **nhead)
1022 {
1023  DetectPort *port = NULL;
1024  DetectPort *pg, *pg2;
1025  int r = 0;
1026 
1027  /** check if the full port space is negated */
1028  if (DetectPortIsCompletePortSpace(*nhead) == 1) {
1029  SCLogError("Complete port space is negated");
1030  goto error;
1031  }
1032 
1033  /**
1034  * step 0: if the head list is empty, but the nhead list isn't
1035  * we have a pure not thingy. In that case we add a 0:65535
1036  * first.
1037  */
1038  if (*head == NULL && *nhead != NULL) {
1039  SCLogDebug("inserting 0:65535 into head");
1040  r = DetectPortParseInsertString(de_ctx, head,"0:65535");
1041  if (r < 0) {
1042  goto error;
1043  }
1044  }
1045 
1046  /** step 1: insert our ghn members into the gh list */
1047  for (pg = *nhead; pg != NULL; pg = pg->next) {
1048  /** work with a copy of the port so we can easily clean up
1049  * the ghn group later.
1050  */
1051  port = DetectPortCopySingle(NULL, pg);
1052  if (port == NULL) {
1053  goto error;
1054  }
1055  r = DetectPortParseInsert(head, port);
1056  if (r < 0) {
1057  goto error;
1058  }
1059  port = NULL;
1060  }
1061 
1062  /** step 2: pull the port blocks that match our 'not' blocks */
1063  for (pg = *nhead; pg != NULL; pg = pg->next) {
1064  SCLogDebug("pg %p", pg);
1065  DetectPortPrint(pg);
1066 
1067  for (pg2 = *head; pg2 != NULL;) {
1068  SCLogDebug("pg2 %p", pg2);
1069  DetectPortPrint(pg2);
1070 
1071  r = DetectPortCmp(pg, pg2);
1072  if (r == PORT_EQ || r == PORT_EB) { /* XXX more ??? */
1073  if (pg2->prev != NULL)
1074  pg2->prev->next = pg2->next;
1075  if (pg2->next != NULL)
1076  pg2->next->prev = pg2->prev;
1077  if (*head == pg2)
1078  *head = pg2->next;
1079  /** store the next ptr and remove the group */
1080  DetectPort *next_pg2 = pg2->next;
1081  DetectPortFree(de_ctx, pg2);
1082  pg2 = next_pg2;
1083  } else {
1084  pg2 = pg2->next;
1085  }
1086  }
1087  }
1088 
1089  for (pg2 = *head; pg2 != NULL; pg2 = pg2->next) {
1090  SCLogDebug("pg2 %p", pg2);
1091  DetectPortPrint(pg2);
1092  }
1093 
1094  if (*head == NULL) {
1095  SCLogError("no ports left after merging ports with negated ports");
1096  goto error;
1097  }
1098 
1099  return 0;
1100 error:
1101  if (port != NULL)
1102  DetectPortFree(de_ctx, port);
1103  return -1;
1104 }
1105 
1107 {
1108  SCLogDebug("Testing port conf vars for any misconfigured values");
1109 
1110  ResolvedVariablesList var_list = TAILQ_HEAD_INITIALIZER(var_list);
1111 
1112  ConfNode *port_vars_node = ConfGetNode("vars.port-groups");
1113  if (port_vars_node == NULL) {
1114  return 0;
1115  }
1116 
1117  ConfNode *seq_node;
1118  TAILQ_FOREACH(seq_node, &port_vars_node->head, next) {
1119  SCLogDebug("Testing %s - %s\n", seq_node->name, seq_node->val);
1120 
1121  DetectPort *gh = DetectPortInit();
1122  if (gh == NULL) {
1123  goto error;
1124  }
1125  DetectPort *ghn = NULL;
1126 
1127  if (seq_node->val == NULL) {
1128  SCLogError("Port var \"%s\" probably has a sequence(something "
1129  "in brackets) value set without any quotes. Please "
1130  "quote it using \"..\".",
1131  seq_node->name);
1132  DetectPortCleanupList(NULL, gh);
1133  goto error;
1134  }
1135 
1136  int r = DetectPortParseDo(NULL, &gh, &ghn, seq_node->val,
1137  /* start with negate no */0, &var_list, 0);
1138 
1139  CleanVariableResolveList(&var_list);
1140 
1141  if (r < 0) {
1142  DetectPortCleanupList(NULL, gh);
1143  SCLogError("failed to parse port var \"%s\" with value \"%s\". "
1144  "Please check its syntax",
1145  seq_node->name, seq_node->val);
1146  goto error;
1147  }
1148 
1149  if (DetectPortIsCompletePortSpace(ghn)) {
1150  SCLogError("Port var - \"%s\" has the complete Port range negated "
1151  "with its value \"%s\". Port space range is NIL. "
1152  "Probably have a !any or a port range that supplies "
1153  "a NULL port range",
1154  seq_node->name, seq_node->val);
1155  DetectPortCleanupList(NULL, gh);
1156  DetectPortCleanupList(NULL, ghn);
1157  goto error;
1158  }
1159 
1160  if (gh != NULL)
1161  DetectPortCleanupList(NULL, gh);
1162  if (ghn != NULL)
1163  DetectPortCleanupList(NULL, ghn);
1164  }
1165 
1166  return 0;
1167  error:
1168  return -1;
1169 }
1170 
1171 
1172 /**
1173  * \brief Function for parsing port strings
1174  *
1175  * \param de_ctx Pointer to the detection engine context
1176  * \param head Pointer to the head of the DetectPort group list
1177  * \param str Pointer to the port string
1178  *
1179  * \retval 0 on success
1180  * \retval -1 on error
1181  */
1183  DetectPort **head, const char *str)
1184 {
1185  SCLogDebug("Port string to be parsed - str %s", str);
1186 
1187  /* negate port list */
1188  DetectPort *nhead = NULL;
1189 
1190  int r = DetectPortParseDo(de_ctx, head, &nhead, str,
1191  /* start with negate no */ 0, NULL, 0);
1192  if (r < 0)
1193  goto error;
1194 
1195  SCLogDebug("head %p %p, nhead %p", head, *head, nhead);
1196 
1197  /* merge the 'not' port groups */
1198  if (DetectPortParseMergeNotPorts(de_ctx, head, &nhead) < 0)
1199  goto error;
1200 
1201  /* free the temp negate head */
1202  DetectPortCleanupList(de_ctx, nhead);
1203  return 0;
1204 
1205 error:
1206  DetectPortCleanupList(de_ctx, nhead);
1207  return -1;
1208 }
1209 
1210 /**
1211  * \brief Helper function for parsing port strings
1212  *
1213  * \param str Pointer to the port string
1214  *
1215  * \retval DetectPort pointer of the parse string on success
1216  * \retval NULL on error
1217  */
1218 DetectPort *PortParse(const char *str)
1219 {
1220  char *port2 = NULL;
1221  char portstr[16];
1222 
1223  /* strip leading spaces */
1224  while (isspace(*str))
1225  str++;
1226  if (strlen(str) >= 16)
1227  return NULL;
1228  strlcpy(portstr, str, sizeof(portstr));
1229 
1230  DetectPort *dp = DetectPortInit();
1231  if (dp == NULL)
1232  goto error;
1233 
1234  /* we dup so we can put a nul-termination in it later */
1235  char *port = portstr;
1236 
1237  /* handle the negation case */
1238  if (port[0] == '!') {
1239  dp->flags |= PORT_FLAG_NOT;
1240  port++;
1241  }
1242 
1243  if ((port2 = strchr(port, ':')) != NULL) {
1244  /* 80:81 range format */
1245  port2[0] = '\0';
1246  port2++;
1247 
1248  if (strcmp(port, "") != 0) {
1249  if (!DetectPortIsValidRange(port, &dp->port))
1250  goto error;
1251  } else {
1252  dp->port = 0;
1253  }
1254 
1255  if (strcmp(port2, "") != 0) {
1256  if (!DetectPortIsValidRange(port2, &dp->port2))
1257  goto error;
1258  } else {
1259  dp->port2 = 65535;
1260  }
1261 
1262  /* a > b is illegal, a == b is ok */
1263  if (dp->port > dp->port2)
1264  goto error;
1265  } else {
1266  if (strcasecmp(port,"any") == 0) {
1267  dp->port = 0;
1268  dp->port2 = 65535;
1269  } else {
1270  if (!DetectPortIsValidRange(port, &dp->port))
1271  goto error;
1272  dp->port2 = dp->port;
1273  }
1274  }
1275 
1276  return dp;
1277 
1278 error:
1279  if (dp != NULL)
1280  DetectPortCleanupList(NULL, dp);
1281  return NULL;
1282 }
1283 
1284 /**
1285  * \brief Helper function to check if a parsed port is in the valid range
1286  * of available ports
1287  *
1288  * \param str Pointer to the port string
1289  *
1290  *
1291  * \retval true if port is in the valid range
1292  * \retval false if invalid
1293  */
1294 static bool DetectPortIsValidRange(char *port, uint16_t *port_val)
1295 {
1296  if (StringParseUint16(port_val, 10, 0, (const char *)port) < 0)
1297  return false;
1298 
1299  return true;
1300 }
1301 
1302 /********************** End parsing routines ********************/
1303 
1304 /* hash table */
1305 
1306 /**
1307  * \brief The hash function to be the used by the hash table -
1308  * DetectEngineCtx->dport_hash_table.
1309  *
1310  * \param ht Pointer to the hash table.
1311  * \param data Pointer to the DetectPort.
1312  * \param datalen Not used in our case.
1313  *
1314  * \retval hash The generated hash value.
1315  */
1316 static uint32_t DetectPortHashFunc(HashListTable *ht, void *data, uint16_t datalen)
1317 {
1318  DetectPort *p = (DetectPort *)data;
1319  SCLogDebug("hashing port %p", p);
1320 
1321  uint32_t hash = ((uint32_t)p->port << 16) | p->port2;
1322 
1323  hash %= ht->array_size;
1324  SCLogDebug("hash %"PRIu32, hash);
1325  return hash;
1326 }
1327 
1328 /**
1329  * \brief The Compare function to be used by the DetectPort hash table -
1330  * DetectEngineCtx->dport_hash_table.
1331  *
1332  * \param data1 Pointer to the first DetectPort.
1333  * \param len1 Not used.
1334  * \param data2 Pointer to the second DetectPort.
1335  * \param len2 Not used.
1336  *
1337  * \retval 1 If the 2 DetectPort sent as args match.
1338  * \retval 0 If the 2 DetectPort sent as args do not match.
1339  */
1340 static char DetectPortCompareFunc(void *data1, uint16_t len1,
1341  void *data2, uint16_t len2)
1342 {
1343  DetectPort *dp1 = (DetectPort *)data1;
1344  DetectPort *dp2 = (DetectPort *)data2;
1345 
1346  if (data1 == NULL || data2 == NULL)
1347  return 0;
1348 
1349  if (dp1->port == dp2->port && dp1->port2 == dp2->port2)
1350  return 1;
1351 
1352  return 0;
1353 }
1354 
1355 static void DetectPortHashFreeFunc(void *ptr)
1356 {
1357  DetectPort *p = ptr;
1358  DetectPortFree(NULL, p);
1359 }
1360 
1361 /**
1362  * \brief Initializes the hash table in the detection engine context to hold the
1363  * DetectPort hash.
1364  *
1365  * \param de_ctx Pointer to the detection engine context.
1366  *
1367  * \retval 0 On success.
1368  * \retval -1 On failure.
1369  */
1371 {
1372  de_ctx->dport_hash_table = HashListTableInit(4096, DetectPortHashFunc,
1373  DetectPortCompareFunc,
1374  DetectPortHashFreeFunc);
1375  if (de_ctx->dport_hash_table == NULL)
1376  return -1;
1377 
1378  return 0;
1379 }
1380 
1381 /**
1382  * \brief Adds a DetectPort to the detection engine context DetectPort
1383  * hash table.
1384  *
1385  * \param de_ctx Pointer to the detection engine context.
1386  * \param dp Pointer to the DetectPort.
1387  *
1388  * \retval ret 0 on Successfully adding the DetectPort; -1 on failure.
1389  */
1391 {
1392  int ret = HashListTableAdd(de_ctx->dport_hash_table, (void *)dp, 0);
1393  return ret;
1394 }
1395 
1396 /**
1397  * \brief Used to lookup a DetectPort hash from the detection engine context
1398  * DetectPort hash table.
1399  *
1400  * \param de_ctx Pointer to the detection engine context.
1401  * \param sgh Pointer to the DetectPort.
1402  *
1403  * \retval rsgh On success a pointer to the DetectPort if the DetectPort is
1404  * found in the hash table; NULL on failure.
1405  */
1407 {
1408  SCEnter();
1409 
1410  DetectPort *rdp = HashListTableLookup(de_ctx->dport_hash_table, (void *)dp, 0);
1411 
1412  SCReturnPtr(rdp, "DetectPort");
1413 }
1414 
1415 /**
1416  * \brief Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by
1417  * DetectPortInit() function.
1418  *
1419  * \param de_ctx Pointer to the detection engine context.
1420  */
1422 {
1423  if (de_ctx->sgh_hash_table == NULL)
1424  return;
1425 
1427  de_ctx->dport_hash_table = NULL;
1428 }
1429 
1430 /*---------------------- Unittests -------------------------*/
1431 
1432 #ifdef UNITTESTS
1433 #include "packet.h"
1434 
1435 /**
1436  * \brief Do a sorted insert, where the top of the list should be the biggest
1437  * port range.
1438  *
1439  * \todo XXX current sorting only works for overlapping ranges
1440  *
1441  * \param head Pointer to the DetectPort list head
1442  * \param dp Pointer to DetectPort to search in the DetectPort list
1443  * \retval 0 if dp is added correctly
1444  */
1445 static int PortTestDetectPortAdd(DetectPort **head, DetectPort *dp)
1446 {
1447  DetectPort *cur, *prev_cur = NULL;
1448 
1449  //SCLogDebug("DetectPortAdd: adding "); DetectPortPrint(ag); SCLogDebug("");
1450 
1451  if (*head != NULL) {
1452  for (cur = *head; cur != NULL; cur = cur->next) {
1453  prev_cur = cur;
1454  int r = DetectPortCmp(dp,cur);
1455  if (r == PORT_EB) {
1456  /* insert here */
1457  dp->prev = cur->prev;
1458  dp->next = cur;
1459 
1460  cur->prev = dp;
1461  if (*head == cur) {
1462  *head = dp;
1463  } else {
1464  dp->prev->next = dp;
1465  }
1466  return 0;
1467  }
1468  }
1469  dp->prev = prev_cur;
1470  if (prev_cur != NULL)
1471  prev_cur->next = dp;
1472  } else {
1473  *head = dp;
1474  }
1475 
1476  return 0;
1477 }
1478 
1479 
1480 /**
1481  * \test Check if a DetectPort is properly allocated
1482  */
1483 static int PortTestParse01 (void)
1484 {
1485  DetectPort *dd = NULL;
1486  int r = DetectPortParse(NULL,&dd,"80");
1487  FAIL_IF_NOT(r == 0);
1488  DetectPortFree(NULL, dd);
1489  PASS;
1490 }
1491 
1492 /**
1493  * \test Check if two ports are properly allocated in the DetectPort group
1494  */
1495 static int PortTestParse02 (void)
1496 {
1497  DetectPort *dd = NULL;
1498  int r = DetectPortParse(NULL,&dd,"80");
1499  FAIL_IF_NOT(r == 0);
1500  r = DetectPortParse(NULL,&dd,"22");
1501  FAIL_IF_NOT(r == 0);
1502  DetectPortCleanupList(NULL, dd);
1503  PASS;
1504 }
1505 
1506 /**
1507  * \test Check if two port ranges are properly allocated in the DetectPort group
1508  */
1509 static int PortTestParse03 (void)
1510 {
1511  DetectPort *dd = NULL;
1512  int r = DetectPortParse(NULL,&dd,"80:88");
1513  FAIL_IF_NOT(r == 0);
1514  r = DetectPortParse(NULL,&dd,"85:100");
1515  FAIL_IF_NOT(r == 0);
1516  DetectPortCleanupList(NULL, dd);
1517  PASS;
1518 }
1519 
1520 /**
1521  * \test Check if a negated port range is properly allocated in the DetectPort
1522  */
1523 static int PortTestParse04 (void)
1524 {
1525  DetectPort *dd = NULL;
1526  int r = DetectPortParse(NULL,&dd,"!80:81");
1527  FAIL_IF_NOT(r == 0);
1528  DetectPortCleanupList(NULL, dd);
1529  PASS;
1530 }
1531 
1532 /**
1533  * \test Check if a negated port range is properly fragmented in the allowed
1534  * real groups, ex !80:81 should allow 0:79 and 82:65535
1535  */
1536 static int PortTestParse05 (void)
1537 {
1538  DetectPort *dd = NULL;
1539  int r = DetectPortParse(NULL,&dd,"!80:81");
1540  FAIL_IF_NOT(r == 0);
1541  FAIL_IF_NULL(dd->next);
1542  FAIL_IF_NOT(dd->port == 0);
1543  FAIL_IF_NOT(dd->port2 == 79);
1544  FAIL_IF_NOT(dd->next->port == 82);
1545  FAIL_IF_NOT(dd->next->port2 == 65535);
1546  DetectPortCleanupList(NULL, dd);
1547  PASS;
1548 }
1549 
1550 /**
1551  * \test Check if a negated port range is properly fragmented in the allowed
1552  * real groups
1553  */
1554 static int PortTestParse07 (void)
1555 {
1556  DetectPort *dd = NULL;
1557 
1558  int r = DetectPortParse(NULL,&dd,"!21:902");
1559  FAIL_IF_NOT(r == 0);
1560  FAIL_IF_NULL(dd->next);
1561 
1562  FAIL_IF_NOT(dd->port == 0);
1563  FAIL_IF_NOT(dd->port2 == 20);
1564  FAIL_IF_NOT(dd->next->port == 903);
1565  FAIL_IF_NOT(dd->next->port2 == 65535);
1566 
1567  DetectPortCleanupList(NULL, dd);
1568  PASS;
1569 }
1570 
1571 /**
1572  * \test Check if we dont allow invalid port range specification
1573  */
1574 static int PortTestParse08 (void)
1575 {
1576  DetectPort *dd = NULL;
1577 
1578  int r = DetectPortParse(NULL,&dd,"[80:!80]");
1579  FAIL_IF(r == 0);
1580 
1581  DetectPortCleanupList(NULL, dd);
1582  PASS;
1583 }
1584 
1585 /**
1586  * \test Check if we autocomplete correctly an open range
1587  */
1588 static int PortTestParse09 (void)
1589 {
1590  DetectPort *dd = NULL;
1591 
1592  int r = DetectPortParse(NULL,&dd,"1024:");
1593  FAIL_IF_NOT(r == 0);
1594  FAIL_IF_NULL(dd);
1595 
1596  FAIL_IF_NOT(dd->port == 1024);
1597  FAIL_IF_NOT(dd->port2 == 0xffff);
1598 
1599  DetectPortCleanupList(NULL, dd);
1600  PASS;
1601 }
1602 
1603 /**
1604  * \test Test we don't allow a port that is too big
1605  */
1606 static int PortTestParse10 (void)
1607 {
1608  DetectPort *dd = NULL;
1609  int r = DetectPortParse(NULL,&dd,"77777777777777777777777777777777777777777777");
1610  FAIL_IF(r == 0);
1611  PASS;
1612 }
1613 
1614 /**
1615  * \test Test second port of range being too big
1616  */
1617 static int PortTestParse11 (void)
1618 {
1619  DetectPort *dd = NULL;
1620 
1621  int r = DetectPortParse(NULL,&dd,"1024:65536");
1622  FAIL_IF(r == 0);
1623  PASS;
1624 }
1625 
1626 /**
1627  * \test Test second port of range being just right
1628  */
1629 static int PortTestParse12 (void)
1630 {
1631  DetectPort *dd = NULL;
1632  int r = DetectPortParse(NULL,&dd,"1024:65535");
1633  FAIL_IF_NOT(r == 0);
1634  DetectPortFree(NULL, dd);
1635  PASS;
1636 }
1637 
1638 /**
1639  * \test Test first port of range being too big
1640  */
1641 static int PortTestParse13 (void)
1642 {
1643  DetectPort *dd = NULL;
1644  int r = DetectPortParse(NULL,&dd,"65536:65535");
1645  FAIL_IF(r == 0);
1646  PASS;
1647 }
1648 
1649 /**
1650  * \test Test merging port groups
1651  */
1652 static int PortTestParse14 (void)
1653 {
1654  DetectPort *dd = NULL;
1655 
1656  int r = DetectPortParseInsertString(NULL, &dd, "0:100");
1657  FAIL_IF_NOT(r == 0);
1658  r = DetectPortParseInsertString(NULL, &dd, "1000:65535");
1659  FAIL_IF_NOT(r == 0);
1660  FAIL_IF_NULL(dd->next);
1661 
1662  FAIL_IF_NOT(dd->port == 0);
1663  FAIL_IF_NOT(dd->port2 == 100);
1664  FAIL_IF_NOT(dd->next->port == 1000);
1665  FAIL_IF_NOT(dd->next->port2 == 65535);
1666 
1667  DetectPortCleanupList(NULL, dd);
1668  PASS;
1669 }
1670 
1671 /**
1672  * \test Test merging negated port groups
1673  */
1674 static int PortTestParse15 (void)
1675 {
1676  DetectPort *dd = NULL;
1677 
1678  int r = DetectPortParse(NULL,&dd,"![0:100,1000:3000]");
1679  FAIL_IF_NOT(r == 0);
1680  FAIL_IF_NULL(dd->next);
1681 
1682  FAIL_IF_NOT(dd->port == 101);
1683  FAIL_IF_NOT(dd->port2 == 999);
1684  FAIL_IF_NOT(dd->next->port == 3001);
1685  FAIL_IF_NOT(dd->next->port2 == 65535);
1686 
1687  DetectPortCleanupList(NULL, dd);
1688  PASS;
1689 }
1690 
1691 static int PortTestParse16 (void)
1692 {
1693  DetectPort *dd = NULL;
1694  int r = DetectPortParse(NULL,&dd,"\
1695 [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\
1696 1:65535\
1697 ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\
1698 ");
1699  FAIL_IF_NOT(r == 0);
1700  DetectPortFree(NULL, dd);
1701  dd = NULL;
1702  r = DetectPortParse(NULL,&dd,"\
1703 [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\
1704 1:65535\
1705 ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\
1706 ");
1707  FAIL_IF(r == 0);
1708  PASS;
1709 }
1710 
1711 /**
1712  * \test Test general functions
1713  */
1714 static int PortTestFunctions01(void)
1715 {
1716  DetectPort *head = NULL;
1717  DetectPort *dp1= NULL;
1718  int result = 0;
1719 
1720  /* Parse */
1721  int r = DetectPortParse(NULL,&head,"![0:100,1000:65535]");
1722  if (r != 0 || head->next != NULL)
1723  goto end;
1724 
1725  /* We should have only one DetectPort */
1726  if (!(head->port == 101))
1727  goto end;
1728  if (!(head->port2 == 999))
1729  goto end;
1730  if (!(head->next == NULL))
1731  goto end;
1732 
1733  r = DetectPortParse(NULL, &dp1,"2000:3000");
1734  if (r != 0 || dp1->next != NULL)
1735  goto end;
1736  if (!(dp1->port == 2000))
1737  goto end;
1738  if (!(dp1->port2 == 3000))
1739  goto end;
1740 
1741  /* Add */
1742  r = PortTestDetectPortAdd(&head, dp1);
1743  if (r != 0 || head->next == NULL)
1744  goto end;
1745  if (!(head->port == 101))
1746  goto end;
1747  if (!(head->port2 == 999))
1748  goto end;
1749  if (!(head->next->port == 2000))
1750  goto end;
1751  if (!(head->next->port2 == 3000))
1752  goto end;
1753 
1754  /* Match */
1755  if (!DetectPortMatch(head, 150))
1756  goto end;
1757  if (DetectPortMatch(head->next, 1500))
1758  goto end;
1759  if ((DetectPortMatch(head, 3500)))
1760  goto end;
1761  if ((DetectPortMatch(head, 50)))
1762  goto end;
1763 
1764  result = 1;
1765 end:
1766  if (dp1 != NULL)
1767  DetectPortFree(NULL, dp1);
1768  if (head != NULL)
1769  DetectPortFree(NULL, head);
1770  return result;
1771 }
1772 
1773 /**
1774  * \test Test general functions
1775  */
1776 static int PortTestFunctions02(void)
1777 {
1778  DetectPort *head = NULL;
1779  DetectPort *dp1= NULL;
1780  DetectPort *dp2= NULL;
1781  int result = 0;
1782 
1783  /* Parse */
1784  int r = DetectPortParse(NULL,&head, "![0:100,1000:65535]");
1785  if (r != 0 || head->next != NULL)
1786  goto end;
1787 
1788  r = DetectPortParse(NULL, &dp1, "!200:300");
1789  if (r != 0 || dp1->next == NULL)
1790  goto end;
1791 
1792  /* Merge Nots */
1793  r = DetectPortParseMergeNotPorts(NULL, &head, &dp1);
1794  if (r != 0 || head->next != NULL)
1795  goto end;
1796 
1797  r = DetectPortParse(NULL, &dp2, "!100:500");
1798  if (r != 0 || dp2->next == NULL)
1799  goto end;
1800 
1801  /* Merge Nots */
1802  r = DetectPortParseMergeNotPorts(NULL, &head, &dp2);
1803  if (r != 0 || head->next != NULL)
1804  goto end;
1805 
1806  if (!(head->port == 200))
1807  goto end;
1808  if (!(head->port2 == 300))
1809  goto end;
1810 
1811  result = 1;
1812 
1813 end:
1814  if (dp1 != NULL)
1815  DetectPortFree(NULL, dp1);
1816  if (dp2 != NULL)
1817  DetectPortFree(NULL, dp2);
1818  if (head != NULL)
1819  DetectPortFree(NULL, head);
1820  return result;
1821 }
1822 
1823 /**
1824  * \test Test general functions
1825  */
1826 static int PortTestFunctions03(void)
1827 {
1828  DetectPort *dp1= NULL;
1829  DetectPort *dp2= NULL;
1830  DetectPort *dp3= NULL;
1831  int result = 0;
1832 
1833  int r = DetectPortParse(NULL, &dp1, "200:300");
1834  if (r != 0)
1835  goto end;
1836 
1837  r = DetectPortParse(NULL, &dp2, "250:300");
1838  if (r != 0)
1839  goto end;
1840 
1841  /* Cut */
1842  DetectPortCut(NULL, dp1, dp2, &dp3);
1843  if (r != 0)
1844  goto end;
1845 
1846  if (!(dp1->port == 200))
1847  goto end;
1848  if (!(dp1->port2 == 249))
1849  goto end;
1850  if (!(dp2->port == 250))
1851  goto end;
1852  if (!(dp2->port2 == 300))
1853  goto end;
1854 
1855  dp1->port = 0;
1856  dp1->port2 = 500;
1857  dp2->port = 250;
1858  dp2->port2 = 750;
1859 
1860  /* Cut */
1861  DetectPortCut(NULL, dp1, dp2, &dp3);
1862  if (r != 0)
1863  goto end;
1864  if (!(dp1->port == 0))
1865  goto end;
1866  if (!(dp1->port2 == 249))
1867  goto end;
1868  if (!(dp2->port == 250))
1869  goto end;
1870  if (!(dp2->port2 == 500))
1871  goto end;
1872  if (!(dp3->port == 501))
1873  goto end;
1874  if (!(dp3->port2 == 750))
1875  goto end;
1876 
1877  result = 1;
1878 
1879 end:
1880  if (dp1 != NULL)
1881  DetectPortFree(NULL, dp1);
1882  if (dp2 != NULL)
1883  DetectPortFree(NULL, dp2);
1884  if (dp3 != NULL)
1885  DetectPortFree(NULL, dp3);
1886  return result;
1887 }
1888 
1889 /**
1890  * \test Test general functions
1891  */
1892 static int PortTestFunctions04(void)
1893 {
1894  DetectPort *dp1= NULL;
1895  DetectPort *dp2= NULL;
1896  int result = 0;
1897 
1898  int r = DetectPortParse(NULL, &dp1, "200:300");
1899  if (r != 0)
1900  goto end;
1901 
1902  dp2 = DetectPortInit();
1903 
1904  /* Cut Not */
1905  DetectPortCutNot(dp1, &dp2);
1906  if (r != 0)
1907  goto end;
1908 
1909  if (!(dp1->port == 0))
1910  goto end;
1911  if (!(dp1->port2 == 199))
1912  goto end;
1913  if (!(dp2->port == 301))
1914  goto end;
1915  if (!(dp2->port2 == 65535))
1916  goto end;
1917 
1918  result = 1;
1919 end:
1920  if (dp1 != NULL)
1921  DetectPortFree(NULL, dp1);
1922  if (dp2 != NULL)
1923  DetectPortFree(NULL, dp2);
1924  return result;
1925 }
1926 
1927 /**
1928  * \test Test general functions
1929  */
1930 static int PortTestFunctions07(void)
1931 {
1932  DetectPort *dd = NULL;
1933 
1934  // This one should fail due to negation in a range
1935  FAIL_IF(DetectPortParse(NULL, &dd, "[80:!99]") == 0);
1936 
1937  // Correct: from 80 till 100 but 99 excluded
1938  FAIL_IF_NOT(DetectPortParse(NULL, &dd, "[80:100,!99]") == 0);
1939  FAIL_IF_NULL(dd->next);
1940  FAIL_IF_NOT(dd->port == 80);
1941  FAIL_IF_NOT(dd->port2 == 98);
1942  FAIL_IF_NOT(dd->next->port == 100);
1943 
1944  // Also good: from 1 till 80 except of 2 and 4
1945  FAIL_IF_NOT(DetectPortParse(NULL, &dd, "[1:80,![2,4]]") == 0);
1946  FAIL_IF_NOT(dd->port == 1);
1950 
1951  DetectPortCleanupList(NULL, dd);
1952  PASS;
1953 }
1954 
1955 /**
1956  * \test Test packet Matches
1957  * \param raw_eth_pkt pointer to the ethernet packet
1958  * \param pktsize size of the packet
1959  * \param sig pointer to the signature to test
1960  * \param sid sid number of the signature
1961  * \retval return 1 if match
1962  * \retval return 0 if not
1963  */
1964 static int PortTestMatchReal(uint8_t *raw_eth_pkt, uint16_t pktsize, const char *sig,
1965  uint32_t sid)
1966 {
1967  int result = 0;
1969  Packet *p = UTHBuildPacketFromEth(raw_eth_pkt, pktsize);
1970  result = UTHPacketMatchSig(p, sig);
1971  PacketRecycle(p);
1972  FlowShutdown();
1973  return result;
1974 }
1975 
1976 /**
1977  * \brief Wrapper for PortTestMatchReal
1978  */
1979 static int PortTestMatchRealWrp(const char *sig, uint32_t sid)
1980 {
1981  /* Real HTTP packeth doing a GET method
1982  * tcp.sport=47370 tcp.dport=80
1983  * ip.src=192.168.28.131 ip.dst=192.168.1.1
1984  */
1985  uint8_t raw_eth_pkt[] = {
1986  0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
1987  0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
1988  0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
1989  0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
1990  0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
1991  0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
1992  0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
1993  0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
1994  0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
1995  0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
1996  0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
1997  0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
1998  0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
1999  0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
2000  0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
2001  0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
2002  0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
2003  0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
2004  0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
2005  0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
2006  0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
2007  0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
2008  0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
2009  0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
2010  0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
2011  0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
2012  0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
2013  0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
2014  0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
2015  0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
2016  0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
2017  0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
2018  0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
2019  0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
2020  0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
2021  0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
2022  0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
2023  0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
2024  0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
2025  0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
2026  0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
2027  0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
2028  0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
2029  0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
2030  0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
2031  0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
2032  0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
2033  0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
2034  0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
2035  0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
2036  0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
2037  0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
2038  0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
2039  0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
2040  0x76,0x65,0x0d,0x0a,0x0d,0x0a };
2041  /* end raw_eth_pkt */
2042 
2043  return PortTestMatchReal(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
2044  sig, sid);
2045 }
2046 
2047 /**
2048  * \test Check if we match a dest port
2049  */
2050 static int PortTestMatchReal01(void)
2051 {
2052  /* tcp.sport=47370 tcp.dport=80 */
2053  const char *sig = "alert tcp any any -> any 80 (msg:\"Nothing..\"; content:\"GET\"; sid:1;)";
2054  return PortTestMatchRealWrp(sig, 1);
2055 }
2056 
2057 /**
2058  * \test Check if we match a source port
2059  */
2060 static int PortTestMatchReal02(void)
2061 {
2062  const char *sig = "alert tcp any 47370 -> any any (msg:\"Nothing..\";"
2063  " content:\"GET\"; sid:1;)";
2064  return PortTestMatchRealWrp(sig, 1);
2065 }
2066 
2067 /**
2068  * \test Check if we match both of them
2069  */
2070 static int PortTestMatchReal03(void)
2071 {
2072  const char *sig = "alert tcp any 47370 -> any 80 (msg:\"Nothing..\";"
2073  " content:\"GET\"; sid:1;)";
2074  return PortTestMatchRealWrp(sig, 1);
2075 }
2076 
2077 /**
2078  * \test Check if we negate dest ports correctly
2079  */
2080 static int PortTestMatchReal04(void)
2081 {
2082  const char *sig = "alert tcp any any -> any !80 (msg:\"Nothing..\";"
2083  " content:\"GET\"; sid:1;)";
2084  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2085 }
2086 
2087 /**
2088  * \test Check if we negate source ports correctly
2089  */
2090 static int PortTestMatchReal05(void)
2091 {
2092  const char *sig = "alert tcp any !47370 -> any any (msg:\"Nothing..\";"
2093  " content:\"GET\"; sid:1;)";
2094  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2095 }
2096 
2097 /**
2098  * \test Check if we negate both ports correctly
2099  */
2100 static int PortTestMatchReal06(void)
2101 {
2102  const char *sig = "alert tcp any !47370 -> any !80 (msg:\"Nothing..\";"
2103  " content:\"GET\"; sid:1;)";
2104  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2105 }
2106 
2107 /**
2108  * \test Check if we match a dest port range
2109  */
2110 static int PortTestMatchReal07(void)
2111 {
2112  const char *sig = "alert tcp any any -> any 70:100 (msg:\"Nothing..\";"
2113  " content:\"GET\"; sid:1;)";
2114  return PortTestMatchRealWrp(sig, 1);
2115 }
2116 
2117 /**
2118  * \test Check if we match a source port range
2119  */
2120 static int PortTestMatchReal08(void)
2121 {
2122  const char *sig = "alert tcp any 47000:50000 -> any any (msg:\"Nothing..\";"
2123  " content:\"GET\"; sid:1;)";
2124  return PortTestMatchRealWrp(sig, 1);
2125 }
2126 
2127 /**
2128  * \test Check if we match both port ranges
2129  */
2130 static int PortTestMatchReal09(void)
2131 {
2132  const char *sig = "alert tcp any 47000:50000 -> any 70:100 (msg:\"Nothing..\";"
2133  " content:\"GET\"; sid:1;)";
2134  return PortTestMatchRealWrp(sig, 1);
2135 }
2136 
2137 /**
2138  * \test Check if we negate a dest port range
2139  */
2140 static int PortTestMatchReal10(void)
2141 {
2142  const char *sig = "alert tcp any any -> any !70:100 (msg:\"Nothing..\";"
2143  " content:\"GET\"; sid:1;)";
2144  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2145 }
2146 
2147 /**
2148  * \test Check if we negate a source port range
2149  */
2150 static int PortTestMatchReal11(void)
2151 {
2152  const char *sig = "alert tcp any !47000:50000 -> any any (msg:\"Nothing..\";"
2153  " content:\"GET\"; sid:1;)";
2154  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2155 }
2156 
2157 /**
2158  * \test Check if we negate both port ranges
2159  */
2160 static int PortTestMatchReal12(void)
2161 {
2162  const char *sig = "alert tcp any !47000:50000 -> any !70:100 (msg:\"Nothing..\";"
2163  " content:\"GET\"; sid:1;)";
2164  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2165 }
2166 
2167 /**
2168  * \test Check if we autocomplete ranges correctly
2169  */
2170 static int PortTestMatchReal13(void)
2171 {
2172  const char *sig = "alert tcp any 47000:50000 -> any !81: (msg:\"Nothing..\";"
2173  " content:\"GET\"; sid:1;)";
2174  return PortTestMatchRealWrp(sig, 1);
2175 }
2176 
2177 /**
2178  * \test Check if we autocomplete ranges correctly
2179  */
2180 static int PortTestMatchReal14(void)
2181 {
2182  const char *sig = "alert tcp any !48000:50000 -> any :100 (msg:\"Nothing..\";"
2183  " content:\"GET\"; sid:1;)";
2184  return PortTestMatchRealWrp(sig, 1);
2185 }
2186 
2187 /**
2188  * \test Check if we autocomplete ranges correctly
2189  */
2190 static int PortTestMatchReal15(void)
2191 {
2192  const char *sig = "alert tcp any :50000 -> any 81:100 (msg:\"Nothing..\";"
2193  " content:\"GET\"; sid:1;)";
2194  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2195 }
2196 
2197 /**
2198  * \test Check if we separate ranges correctly
2199  */
2200 static int PortTestMatchReal16(void)
2201 {
2202  const char *sig = "alert tcp any 100: -> any ![0:79,81:65535] (msg:\"Nothing..\";"
2203  " content:\"GET\"; sid:1;)";
2204  return PortTestMatchRealWrp(sig, 1);
2205 }
2206 
2207 /**
2208  * \test Check if we separate ranges correctly
2209  */
2210 static int PortTestMatchReal17(void)
2211 {
2212  const char *sig = "alert tcp any ![0:39999,48000:50000] -> any ![0:80,82:65535] "
2213  "(msg:\"Nothing..\"; content:\"GET\"; sid:1;)";
2214  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2215 }
2216 
2217 /**
2218  * \test Check if we separate ranges correctly
2219  */
2220 static int PortTestMatchReal18(void)
2221 {
2222  const char *sig = "alert tcp any ![0:39999,48000:50000] -> any 80 (msg:\"Nothing"
2223  " at all\"; content:\"GET\"; sid:1;)";
2224  return PortTestMatchRealWrp(sig, 1);
2225 }
2226 
2227 /**
2228  * \test Check if we separate ranges correctly
2229  */
2230 static int PortTestMatchReal19(void)
2231 {
2232  const char *sig = "alert tcp any any -> any 80 (msg:\"Nothing..\";"
2233  " content:\"GET\"; sid:1;)";
2234  return PortTestMatchRealWrp(sig, 1);
2235 }
2236 
2237 static int PortTestMatchDoubleNegation(void)
2238 {
2239  int result = 0;
2240  DetectPort *head = NULL, *nhead = NULL;
2241 
2242  if (DetectPortParseDo(NULL, &head, &nhead, "![!80]", 0, NULL, 0) == -1)
2243  return result;
2244 
2245  result = (head != NULL);
2246  result = (nhead == NULL);
2247 
2248  return result;
2249 }
2250 
2251 // Test that negation is successfully parsed with whitespace for port strings of
2252 // length < 16
2253 static int DetectPortParseDoTest(void)
2254 {
2257  DetectPort *head = NULL;
2258  DetectPort *nhead = NULL;
2259  const char *str = "[30:50, !45]";
2260  int r = DetectPortParseDo(de_ctx, &head, &nhead, str, 0, NULL, 0);
2261 
2262  // Assertions
2263  FAIL_IF_NULL(head);
2264  FAIL_IF_NULL(nhead);
2265  FAIL_IF(r < 0);
2266  FAIL_IF(head->port != 30);
2267  FAIL_IF(head->port2 != 50);
2268  FAIL_IF(nhead->port != 45);
2269  FAIL_IF(nhead->port2 != 45);
2270  DetectPortCleanupList(NULL, head);
2271  DetectPortCleanupList(NULL, nhead);
2272  PASS;
2273 }
2274 
2275 static int DetectPortParseDoTest2(void)
2276 {
2279  DetectPort *head = NULL;
2280  DetectPort *nhead = NULL;
2281  const char *str = "[30:50, !45]";
2282  int r = DetectPortParseDo(de_ctx, &head, &nhead, str, 0, NULL, 0);
2283  FAIL_IF(r < 0);
2284  DetectPortCleanupList(NULL, head);
2285  DetectPortCleanupList(NULL, nhead);
2286  PASS;
2287 }
2288 
2289 // Verifies correct parsing when negation port string length < 16
2290 static int PortParseTestLessThan14Spaces(void)
2291 {
2292  const char *str = " 45";
2293  DetectPort *dp = PortParse(str);
2294  FAIL_IF_NULL(dp);
2295  FAIL_IF(dp->port != 45);
2296  FAIL_IF(dp->port2 != 45);
2297  DetectPortFree(NULL, dp);
2298  PASS;
2299 }
2300 
2301 // Verifies NULL returned when negation port string length == 16
2302 static int PortParseTest14Spaces(void)
2303 {
2304  const char *str = " 45";
2305  DetectPort *dp = PortParse(str);
2306  FAIL_IF_NULL(dp);
2307  FAIL_IF(dp->port != 45);
2308  FAIL_IF(dp->port2 != 45);
2309  DetectPortFree(NULL, dp);
2310  PASS;
2311 }
2312 
2313 // Verifies NULL returned when negation port string length >= 16
2314 static int PortParseTestMoreThan14Spaces(void)
2315 {
2316  const char *str = " 45";
2317  DetectPort *dp = PortParse(str);
2318  FAIL_IF_NULL(dp);
2319  FAIL_IF(dp->port != 45);
2320  FAIL_IF(dp->port2 != 45);
2321  DetectPortFree(NULL, dp);
2322  PASS;
2323 }
2324 
2325 void DetectPortTests(void)
2326 {
2327  UtRegisterTest("PortTestParse01", PortTestParse01);
2328  UtRegisterTest("PortTestParse02", PortTestParse02);
2329  UtRegisterTest("PortTestParse03", PortTestParse03);
2330  UtRegisterTest("PortTestParse04", PortTestParse04);
2331  UtRegisterTest("PortTestParse05", PortTestParse05);
2332  UtRegisterTest("PortTestParse07", PortTestParse07);
2333  UtRegisterTest("PortTestParse08", PortTestParse08);
2334  UtRegisterTest("PortTestParse09", PortTestParse09);
2335  UtRegisterTest("PortTestParse10", PortTestParse10);
2336  UtRegisterTest("PortTestParse11", PortTestParse11);
2337  UtRegisterTest("PortTestParse12", PortTestParse12);
2338  UtRegisterTest("PortTestParse13", PortTestParse13);
2339  UtRegisterTest("PortTestParse14", PortTestParse14);
2340  UtRegisterTest("PortTestParse15", PortTestParse15);
2341  UtRegisterTest("PortTestParse16", PortTestParse16);
2342  UtRegisterTest("PortTestFunctions01", PortTestFunctions01);
2343  UtRegisterTest("PortTestFunctions02", PortTestFunctions02);
2344  UtRegisterTest("PortTestFunctions03", PortTestFunctions03);
2345  UtRegisterTest("PortTestFunctions04", PortTestFunctions04);
2346  UtRegisterTest("PortTestFunctions07", PortTestFunctions07);
2347  UtRegisterTest("PortTestMatchReal01", PortTestMatchReal01);
2348  UtRegisterTest("PortTestMatchReal02", PortTestMatchReal02);
2349  UtRegisterTest("PortTestMatchReal03", PortTestMatchReal03);
2350  UtRegisterTest("PortTestMatchReal04", PortTestMatchReal04);
2351  UtRegisterTest("PortTestMatchReal05", PortTestMatchReal05);
2352  UtRegisterTest("PortTestMatchReal06", PortTestMatchReal06);
2353  UtRegisterTest("PortTestMatchReal07", PortTestMatchReal07);
2354  UtRegisterTest("PortTestMatchReal08", PortTestMatchReal08);
2355  UtRegisterTest("PortTestMatchReal09", PortTestMatchReal09);
2356  UtRegisterTest("PortTestMatchReal10", PortTestMatchReal10);
2357  UtRegisterTest("PortTestMatchReal11", PortTestMatchReal11);
2358  UtRegisterTest("PortTestMatchReal12", PortTestMatchReal12);
2359  UtRegisterTest("PortTestMatchReal13", PortTestMatchReal13);
2360  UtRegisterTest("PortTestMatchReal14", PortTestMatchReal14);
2361  UtRegisterTest("PortTestMatchReal15", PortTestMatchReal15);
2362  UtRegisterTest("PortTestMatchReal16", PortTestMatchReal16);
2363  UtRegisterTest("PortTestMatchReal17", PortTestMatchReal17);
2364  UtRegisterTest("PortTestMatchReal18", PortTestMatchReal18);
2365  UtRegisterTest("PortTestMatchReal19", PortTestMatchReal19);
2366  UtRegisterTest("PortTestMatchDoubleNegation", PortTestMatchDoubleNegation);
2367  UtRegisterTest("DetectPortParseDoTest", DetectPortParseDoTest);
2368  UtRegisterTest("DetectPortParseDoTest2", DetectPortParseDoTest2);
2369  UtRegisterTest("PortParseTestLessThan14Spaces", PortParseTestLessThan14Spaces);
2370  UtRegisterTest("PortParseTest14Spaces", PortParseTest14Spaces);
2371  UtRegisterTest("PortParseTestMoreThan14Spaces", PortParseTestMoreThan14Spaces);
2372 }
2373 
2374 #endif /* UNITTESTS */
DetectEngineCtx_::sgh_hash_table
HashListTable * sgh_hash_table
Definition: detect.h:876
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
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:1370
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
ConfNode_::val
char * val
Definition: conf.h:34
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
PORT_LT
@ PORT_LT
Definition: detect.h:203
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:269
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
DetectPort_::port
uint16_t port
Definition: detect.h:218
PORT_SIGGROUPHEAD_COPY
#define PORT_SIGGROUPHEAD_COPY
Definition: detect.h:214
PacketRecycle
void PacketRecycle(Packet *p)
Definition: packet.c:143
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:181
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:843
StringParseUint16
int StringParseUint16(uint16_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:337
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
DetectPort_::next
struct DetectPort_ * next
Definition: detect.h:231
UTHPacketMatchSig
int UTHPacketMatchSig(Packet *p, const char *sig)
Definition: util-unittest-helper.c:804
DetectEngineCtx_::dport_hash_table
HashListTable * dport_hash_table
Definition: detect.h:980
DetectPort_::sh
struct SigGroupHead_ * sh
Definition: detect.h:228
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:1106
util-var.h
PortParse
DetectPort * PortParse(const char *str)
Helper function for parsing port strings.
Definition: detect-engine-port.c:1218
DetectPort_::port2
uint16_t port2
Definition: detect.h:219
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:221
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
FlowInitConfig
void FlowInitConfig(bool quiet)
initialize the configuration
Definition: flow.c:533
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:1182
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:212
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:17
PORT_ES
@ PORT_ES
Definition: detect.h:206
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
detect-engine-mpm.h
detect.h
StreamContentInspectEngineData::s
const Signature * s
Definition: detect-engine-payload.c:265
pkt-var.h
PORT_EB
@ PORT_EB
Definition: detect.h:207
PORT_GT
@ PORT_GT
Definition: detect.h:209
detect-engine-port.h
DetectPort_
Port structure for detection engine.
Definition: detect.h:217
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
PORT_ER
@ PORT_ER
Definition: detect.h:202
util-profiling.h
util-rule-vars.h
Packet_
Definition: decode.h:476
conf.h
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:287
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:162
Flow_::next
struct Flow_ * next
Definition: flow.h:401
PORT_LE
@ PORT_LE
Definition: detect.h:204
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:680
packet.h
ConfNode_::name
char * name
Definition: conf.h:33
DetectPort_::prev
struct DetectPort_ * prev
Definition: detect.h:230
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:291
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
head
Flow * head
Definition: flow-hash.h:1
SCFree
#define SCFree(p)
Definition: util-mem.h:61
ConfNode_
Definition: conf.h:32
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:376
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2584
PORT_FLAG_NOT
#define PORT_FLAG_NOT
Definition: detect.h:213
PORT_EQ
@ PORT_EQ
Definition: detect.h:205
DetectPortHashAdd
int DetectPortHashAdd(DetectEngineCtx *de_ctx, DetectPort *dp)
Adds a DetectPort to the detection engine context DetectPort hash table.
Definition: detect-engine-port.c:1390
FLOW_QUIET
#define FLOW_QUIET
Definition: flow.h:43
DetectPortTests
void DetectPortTests(void)
dst
uint16_t dst
Definition: app-layer-dnp3.h:4
DetectPortHashFree
void DetectPortHashFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by DetectPortInit() function.
Definition: detect-engine-port.c:1421
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:1406
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
flow-var.h
PORT_GE
@ PORT_GE
Definition: detect.h:208
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
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:401