suricata
detect-ssh-software-version.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2016 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 Pablo Rincon <pablo.rincon.crespo@gmail.com>
22  *
23  * Implements the ssh.softwareversion keyword
24  * You can match over the software version string of ssh, and it will
25  * be compared from the beginning of the string so you can say for
26  * example ssh.softwareversion:"PuTTY" and it can match, or you can
27  * also specify the version, something like
28  * ssh.softwareversion:"PuTTY-Release-0.55"
29  * I find this useful to match over a known vulnerable server/client
30  * software version incombination to other checks, so you can know
31  * that the risk is higher
32  */
33 
34 #include "suricata-common.h"
35 #include "threads.h"
36 #include "debug.h"
37 #include "decode.h"
38 
39 #include "detect.h"
40 #include "detect-parse.h"
41 
42 #include "detect-engine.h"
43 #include "detect-engine-mpm.h"
44 #include "detect-engine-state.h"
45 
46 #include "flow.h"
47 #include "flow-var.h"
48 #include "flow-util.h"
49 
50 #include "util-debug.h"
51 #include "util-unittest.h"
52 #include "util-unittest-helper.h"
53 
54 #include "app-layer.h"
55 #include "app-layer-parser.h"
56 #include "app-layer-ssh.h"
58 
59 #include "stream-tcp.h"
60 
61 /**
62  * \brief Regex for parsing the softwareversion string
63  */
64 #define PARSE_REGEX "^\\s*\"?\\s*?([0-9a-zA-Z\\:\\.\\-\\_\\+\\s+]+)\\s*\"?\\s*$"
65 
66 static pcre *parse_regex;
67 static pcre_extra *parse_regex_study;
68 
69 static int DetectSshSoftwareVersionMatch (ThreadVars *, DetectEngineThreadCtx *,
70  Flow *, uint8_t, void *, void *,
71  const Signature *, const SigMatchCtx *);
72 static int DetectSshSoftwareVersionSetup (DetectEngineCtx *, Signature *, const char *);
73 static void DetectSshSoftwareVersionRegisterTests(void);
74 static void DetectSshSoftwareVersionFree(void *);
75 static int g_ssh_banner_list_id = 0;
76 
77 static int InspectSshBanner(ThreadVars *tv,
78  DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
79  const Signature *s, const SigMatchData *smd,
80  Flow *f, uint8_t flags, void *alstate,
81  void *txv, uint64_t tx_id)
82 {
83  return DetectEngineInspectGenericList(tv, de_ctx, det_ctx, s, smd,
84  f, flags, alstate, txv, tx_id);
85 }
86 
87 /**
88  * \brief Registration function for keyword: ssh.softwareversion
89  */
91 {
92  sigmatch_table[DETECT_AL_SSH_SOFTWAREVERSION].name = "ssh.softwareversion";
93  sigmatch_table[DETECT_AL_SSH_SOFTWAREVERSION].desc = "match SSH software string";
94  sigmatch_table[DETECT_AL_SSH_SOFTWAREVERSION].url = DOC_URL DOC_VERSION "/rules/ssh-keywords.html#ssh-softwareversion";
95  sigmatch_table[DETECT_AL_SSH_SOFTWAREVERSION].AppLayerTxMatch = DetectSshSoftwareVersionMatch;
96  sigmatch_table[DETECT_AL_SSH_SOFTWAREVERSION].Setup = DetectSshSoftwareVersionSetup;
97  sigmatch_table[DETECT_AL_SSH_SOFTWAREVERSION].Free = DetectSshSoftwareVersionFree;
98  sigmatch_table[DETECT_AL_SSH_SOFTWAREVERSION].RegisterTests = DetectSshSoftwareVersionRegisterTests;
100 
101  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study);
102 
103  g_ssh_banner_list_id = DetectBufferTypeRegister("ssh_banner");
104 
107  InspectSshBanner);
110  InspectSshBanner);
111 }
112 
113 /**
114  * \brief match the specified version on a ssh session
115  *
116  * \param t pointer to thread vars
117  * \param det_ctx pointer to the pattern matcher thread
118  * \param p pointer to the current packet
119  * \param m pointer to the sigmatch that we will cast into DetectSshSoftwareVersionData
120  *
121  * \retval 0 no match
122  * \retval 1 match
123  */
124 static int DetectSshSoftwareVersionMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
125  Flow *f, uint8_t flags, void *state, void *txv,
126  const Signature *s, const SigMatchCtx *m)
127 {
128  SCEnter();
129 
131  SshState *ssh_state = (SshState *)state;
132  if (ssh_state == NULL) {
133  SCLogDebug("no ssh state, no match");
134  SCReturnInt(0);
135  }
136 
137  int ret = 0;
138  if ((flags & STREAM_TOCLIENT) && (ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
139  SCLogDebug("looking for ssh server softwareversion %s length %"PRIu16" on %s", ssh->software_ver, ssh->len, ssh_state->srv_hdr.software_version);
140  ret = (strncmp((char *) ssh_state->srv_hdr.software_version, (char *) ssh->software_ver, ssh->len) == 0)? 1 : 0;
141  } else if ((flags & STREAM_TOSERVER) && (ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
142  SCLogDebug("looking for ssh client softwareversion %s length %"PRIu16" on %s", ssh->software_ver, ssh->len, ssh_state->cli_hdr.software_version);
143  ret = (strncmp((char *) ssh_state->cli_hdr.software_version, (char *) ssh->software_ver, ssh->len) == 0)? 1 : 0;
144  }
145  SCReturnInt(ret);
146 }
147 
148 /**
149  * \brief This function is used to parse IPV4 ip_id passed via keyword: "id"
150  *
151  * \param idstr Pointer to the user provided id option
152  *
153  * \retval id_d pointer to DetectSshSoftwareVersionData on success
154  * \retval NULL on failure
155  */
156 static DetectSshSoftwareVersionData *DetectSshSoftwareVersionParse (const char *str)
157 {
158  DetectSshSoftwareVersionData *ssh = NULL;
159 #define MAX_SUBSTRINGS 30
160  int ret = 0, res = 0;
161  int ov[MAX_SUBSTRINGS];
162 
163  ret = pcre_exec(parse_regex, parse_regex_study, str, strlen(str), 0, 0,
164  ov, MAX_SUBSTRINGS);
165 
166  if (ret < 1 || ret > 3) {
167  SCLogError(SC_ERR_PCRE_MATCH, "invalid ssh.softwareversion option");
168  goto error;
169  }
170 
171  if (ret > 1) {
172  const char *str_ptr = NULL;
173  res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
174  if (res < 0) {
175  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
176  goto error;
177  }
178 
179  /* We have a correct id option */
180  ssh = SCMalloc(sizeof(DetectSshSoftwareVersionData));
181  if (unlikely(ssh == NULL))
182  goto error;
183 
184  ssh->software_ver = (uint8_t *)SCStrdup((char *)str_ptr);
185  if (ssh->software_ver == NULL) {
186  goto error;
187  }
188  pcre_free_substring(str_ptr);
189 
190  ssh->len = strlen((char *)ssh->software_ver);
191 
192  SCLogDebug("will look for ssh %s", ssh->software_ver);
193  }
194 
195  return ssh;
196 
197 error:
198  if (ssh != NULL)
199  DetectSshSoftwareVersionFree(ssh);
200  return NULL;
201 
202 }
203 
204 /**
205  * \brief this function is used to add the parsed "id" option
206  * \brief into the current signature
207  *
208  * \param de_ctx pointer to the Detection Engine Context
209  * \param s pointer to the Current Signature
210  * \param idstr pointer to the user provided "id" option
211  *
212  * \retval 0 on Success
213  * \retval -1 on Failure
214  */
215 static int DetectSshSoftwareVersionSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
216 {
217  DetectSshSoftwareVersionData *ssh = NULL;
218  SigMatch *sm = NULL;
219 
221  return -1;
222 
223  ssh = DetectSshSoftwareVersionParse(str);
224  if (ssh == NULL)
225  goto error;
226 
227  /* Okay so far so good, lets get this into a SigMatch
228  * and put it in the Signature. */
229  sm = SigMatchAlloc();
230  if (sm == NULL)
231  goto error;
232 
234  sm->ctx = (void *)ssh;
235 
236  SigMatchAppendSMToList(s, sm, g_ssh_banner_list_id);
237  return 0;
238 
239 error:
240  if (ssh != NULL)
241  DetectSshSoftwareVersionFree(ssh);
242  if (sm != NULL)
243  SCFree(sm);
244  return -1;
245 
246 }
247 
248 /**
249  * \brief this function will free memory associated with DetectSshSoftwareVersionData
250  *
251  * \param id_d pointer to DetectSshSoftwareVersionData
252  */
253 static void DetectSshSoftwareVersionFree(void *ptr)
254 {
255  if (ptr == NULL)
256  return;
257 
259  if (ssh->software_ver != NULL)
260  SCFree(ssh->software_ver);
261  SCFree(ssh);
262 }
263 
264 #ifdef UNITTESTS /* UNITTESTS */
265 
266 /**
267  * \test DetectSshSoftwareVersionTestParse01 is a test to make sure that we parse
268  * a software version correctly
269  */
270 static int DetectSshSoftwareVersionTestParse01 (void)
271 {
272  DetectSshSoftwareVersionData *ssh = NULL;
273  ssh = DetectSshSoftwareVersionParse("PuTTY_1.0");
274  if (ssh != NULL && strncmp((char *) ssh->software_ver, "PuTTY_1.0", 9) == 0) {
275  DetectSshSoftwareVersionFree(ssh);
276  return 1;
277  }
278 
279  return 0;
280 }
281 
282 /**
283  * \test DetectSshSoftwareVersionTestParse02 is a test to make sure that we parse
284  * the software version correctly
285  */
286 static int DetectSshSoftwareVersionTestParse02 (void)
287 {
288  DetectSshSoftwareVersionData *ssh = NULL;
289  ssh = DetectSshSoftwareVersionParse("\"SecureCRT-4.0\"");
290  if (ssh != NULL && strncmp((char *) ssh->software_ver, "SecureCRT-4.0", 13) == 0) {
291  DetectSshSoftwareVersionFree(ssh);
292  return 1;
293  }
294 
295  return 0;
296 }
297 
298 /**
299  * \test DetectSshSoftwareVersionTestParse03 is a test to make sure that we
300  * don't return a ssh_data with an empty value specified
301  */
302 static int DetectSshSoftwareVersionTestParse03 (void)
303 {
304  DetectSshSoftwareVersionData *ssh = NULL;
305  ssh = DetectSshSoftwareVersionParse("");
306  if (ssh != NULL) {
307  DetectSshSoftwareVersionFree(ssh);
308  return 0;
309  }
310 
311  return 1;
312 }
313 
314 
315 #include "stream-tcp-reassemble.h"
316 
317 /** \test Send a get request in three chunks + more data. */
318 static int DetectSshSoftwareVersionTestDetect01(void)
319 {
320  int result = 0;
321  Flow f;
322  uint8_t sshbuf1[] = "SSH-1.";
323  uint32_t sshlen1 = sizeof(sshbuf1) - 1;
324  uint8_t sshbuf2[] = "10-PuTTY_2.123" ;
325  uint32_t sshlen2 = sizeof(sshbuf2) - 1;
326  uint8_t sshbuf3[] = "\n";
327  uint32_t sshlen3 = sizeof(sshbuf3) - 1;
328  uint8_t sshbuf4[] = "whatever...";
329  uint32_t sshlen4 = sizeof(sshbuf4) - 1;
330  TcpSession ssn;
331  Packet *p = NULL;
332  Signature *s = NULL;
333  ThreadVars th_v;
334  DetectEngineThreadCtx *det_ctx = NULL;
336 
337  memset(&th_v, 0, sizeof(th_v));
338  memset(&f, 0, sizeof(f));
339  memset(&ssn, 0, sizeof(ssn));
340 
341  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
342 
343  FLOW_INITIALIZE(&f);
344  f.protoctx = (void *)&ssn;
345  p->flow = &f;
349  f.alproto = ALPROTO_SSH;
350  f.proto = IPPROTO_TCP;
351 
353 
355  if (de_ctx == NULL) {
356  goto end;
357  }
358 
359  de_ctx->flags |= DE_QUIET;
360 
361  s = de_ctx->sig_list = SigInit(de_ctx,"alert ssh any any -> any any (msg:\"SSH\"; ssh.softwareversion:PuTTY_2.123; sid:1;)");
362  if (s == NULL) {
363  goto end;
364  }
365 
366  SigGroupBuild(de_ctx);
367  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
368 
369  FLOWLOCK_WRLOCK(&f);
370  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
371  STREAM_TOSERVER, sshbuf1, sshlen1);
372  if (r != 0) {
373  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
374  FLOWLOCK_UNLOCK(&f);
375  goto end;
376  }
377 
378  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
379  sshbuf2, sshlen2);
380  if (r != 0) {
381  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
382  FLOWLOCK_UNLOCK(&f);
383  goto end;
384  }
385 
386  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
387  sshbuf3, sshlen3);
388  if (r != 0) {
389  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
390  FLOWLOCK_UNLOCK(&f);
391  goto end;
392  }
393 
394  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
395  sshbuf4, sshlen4);
396  if (r != 0) {
397  printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
398  FLOWLOCK_UNLOCK(&f);
399  goto end;
400  }
401  FLOWLOCK_UNLOCK(&f);
402 
403  SshState *ssh_state = f.alstate;
404  if (ssh_state == NULL) {
405  printf("no ssh state: ");
406  goto end;
407  }
408 
409  /* do detect */
410  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
411 
412  if ( !(PacketAlertCheck(p, 1))) {
413  printf("Error, the sig should match: ");
414  goto end;
415  }
416 
417  result = 1;
418 end:
419  SigGroupCleanup(de_ctx);
420  SigCleanSignatures(de_ctx);
421 
422  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
423  DetectEngineCtxFree(de_ctx);
424 
426  FLOW_DESTROY(&f);
427 
428  UTHFreePackets(&p, 1);
429 
430  if (alp_tctx != NULL)
431  AppLayerParserThreadCtxFree(alp_tctx);
432  return result;
433 }
434 
435 /** \test Send a get request in three chunks + more data. */
436 static int DetectSshSoftwareVersionTestDetect02(void)
437 {
438  int result = 0;
439  Flow f;
440  uint8_t sshbuf1[] = "SSH-1.99-Pu";
441  uint32_t sshlen1 = sizeof(sshbuf1) - 1;
442  uint8_t sshbuf2[] = "TTY_2.123" ;
443  uint32_t sshlen2 = sizeof(sshbuf2) - 1;
444  uint8_t sshbuf3[] = "\n";
445  uint32_t sshlen3 = sizeof(sshbuf3) - 1;
446  uint8_t sshbuf4[] = "whatever...";
447  uint32_t sshlen4 = sizeof(sshbuf4) - 1;
448  TcpSession ssn;
449  Packet *p = NULL;
450  Signature *s = NULL;
451  ThreadVars th_v;
452  DetectEngineThreadCtx *det_ctx = NULL;
454 
455  memset(&th_v, 0, sizeof(th_v));
456  memset(&f, 0, sizeof(f));
457  memset(&ssn, 0, sizeof(ssn));
458 
459  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
460 
461  FLOW_INITIALIZE(&f);
462  f.protoctx = (void *)&ssn;
463  p->flow = &f;
467  f.alproto = ALPROTO_SSH;
468  f.proto = IPPROTO_TCP;
469 
471 
473  if (de_ctx == NULL) {
474  goto end;
475  }
476 
477  de_ctx->flags |= DE_QUIET;
478 
479  s = de_ctx->sig_list = SigInit(de_ctx,"alert ssh any any -> any any (msg:\"SSH\"; ssh.softwareversion:PuTTY_2.123; sid:1;)");
480  if (s == NULL) {
481  goto end;
482  }
483 
484  SigGroupBuild(de_ctx);
485  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
486 
487  FLOWLOCK_WRLOCK(&f);
488  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
489  STREAM_TOSERVER, sshbuf1, sshlen1);
490  if (r != 0) {
491  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
492  FLOWLOCK_UNLOCK(&f);
493  goto end;
494  }
495 
496  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
497  sshbuf2, sshlen2);
498  if (r != 0) {
499  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
500  FLOWLOCK_UNLOCK(&f);
501  goto end;
502  }
503 
504  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
505  sshbuf3, sshlen3);
506  if (r != 0) {
507  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
508  FLOWLOCK_UNLOCK(&f);
509  goto end;
510  }
511 
512  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
513  sshbuf4, sshlen4);
514  if (r != 0) {
515  printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
516  FLOWLOCK_UNLOCK(&f);
517  goto end;
518  }
519  FLOWLOCK_UNLOCK(&f);
520 
521  SshState *ssh_state = f.alstate;
522  if (ssh_state == NULL) {
523  printf("no ssh state: ");
524  goto end;
525  }
526 
527  /* do detect */
528  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
529 
530  if ( !(PacketAlertCheck(p, 1))) {
531  printf("Error, the sig should match: ");
532  goto end;
533  }
534 
535  result = 1;
536 end:
537  SigGroupCleanup(de_ctx);
538  SigCleanSignatures(de_ctx);
539 
540  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
541  DetectEngineCtxFree(de_ctx);
542 
544  FLOW_DESTROY(&f);
545 
546  UTHFreePackets(&p, 1);
547  if (alp_tctx != NULL)
548  AppLayerParserThreadCtxFree(alp_tctx);
549  return result;
550 }
551 
552 /** \test Send a get request in three chunks + more data. */
553 static int DetectSshSoftwareVersionTestDetect03(void)
554 {
555  int result = 0;
556  Flow f;
557  uint8_t sshbuf1[] = "SSH-1.";
558  uint32_t sshlen1 = sizeof(sshbuf1) - 1;
559  uint8_t sshbuf2[] = "7-PuTTY_2.123" ;
560  uint32_t sshlen2 = sizeof(sshbuf2) - 1;
561  uint8_t sshbuf3[] = "\n";
562  uint32_t sshlen3 = sizeof(sshbuf3) - 1;
563  uint8_t sshbuf4[] = "whatever...";
564  uint32_t sshlen4 = sizeof(sshbuf4) - 1;
565  TcpSession ssn;
566  Packet *p = NULL;
567  Signature *s = NULL;
568  ThreadVars th_v;
569  DetectEngineThreadCtx *det_ctx = NULL;
571 
572  memset(&th_v, 0, sizeof(th_v));
573  memset(&f, 0, sizeof(f));
574  memset(&ssn, 0, sizeof(ssn));
575 
576  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
577 
578  FLOW_INITIALIZE(&f);
579  f.protoctx = (void *)&ssn;
580  p->flow = &f;
584  f.alproto = ALPROTO_SSH;
585  f.proto = IPPROTO_TCP;
586 
588 
590  if (de_ctx == NULL) {
591  goto end;
592  }
593 
594  de_ctx->flags |= DE_QUIET;
595 
596  s = de_ctx->sig_list = SigInit(de_ctx,"alert ssh any any -> any any (msg:\"SSH\"; ssh.softwareversion:lalala-3.1.4; sid:1;)");
597  if (s == NULL) {
598  goto end;
599  }
600 
601  SigGroupBuild(de_ctx);
602  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
603 
604  FLOWLOCK_WRLOCK(&f);
605  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
606  STREAM_TOSERVER, sshbuf1, sshlen1);
607  if (r != 0) {
608  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
609  FLOWLOCK_UNLOCK(&f);
610  goto end;
611  }
612 
613  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
614  sshbuf2, sshlen2);
615  if (r != 0) {
616  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
617  FLOWLOCK_UNLOCK(&f);
618  goto end;
619  }
620 
621  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
622  sshbuf3, sshlen3);
623  if (r != 0) {
624  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
625  FLOWLOCK_UNLOCK(&f);
626  goto end;
627  }
628 
629  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
630  sshbuf4, sshlen4);
631  if (r != 0) {
632  printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
633  FLOWLOCK_UNLOCK(&f);
634  goto end;
635  }
636  FLOWLOCK_UNLOCK(&f);
637 
638  SshState *ssh_state = f.alstate;
639  if (ssh_state == NULL) {
640  printf("no ssh state: ");
641  goto end;
642  }
643 
644  /* do detect */
645  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
646 
647  if (PacketAlertCheck(p, 1)) {
648  printf("Error, 1.7 version is not 2 compat, so the sig should not match: ");
649  goto end;
650  }
651 
652  result = 1;
653 end:
654  SigGroupCleanup(de_ctx);
655  SigCleanSignatures(de_ctx);
656 
657  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
658  DetectEngineCtxFree(de_ctx);
659 
661  FLOW_DESTROY(&f);
662 
663  UTHFreePackets(&p, 1);
664  if (alp_tctx != NULL)
665  AppLayerParserThreadCtxFree(alp_tctx);
666  return result;
667 }
668 
669 #endif /* UNITTESTS */
670 
671 /**
672  * \brief this function registers unit tests for DetectSshSoftwareVersion
673  */
674 static void DetectSshSoftwareVersionRegisterTests(void)
675 {
676 #ifdef UNITTESTS /* UNITTESTS */
677  UtRegisterTest("DetectSshSoftwareVersionTestParse01",
678  DetectSshSoftwareVersionTestParse01);
679  UtRegisterTest("DetectSshSoftwareVersionTestParse02",
680  DetectSshSoftwareVersionTestParse02);
681  UtRegisterTest("DetectSshSoftwareVersionTestParse03",
682  DetectSshSoftwareVersionTestParse03);
683  UtRegisterTest("DetectSshSoftwareVersionTestDetect01",
684  DetectSshSoftwareVersionTestDetect01);
685  UtRegisterTest("DetectSshSoftwareVersionTestDetect02",
686  DetectSshSoftwareVersionTestDetect02);
687  UtRegisterTest("DetectSshSoftwareVersionTestDetect03",
688  DetectSshSoftwareVersionTestDetect03);
689 #endif /* UNITTESTS */
690 }
691 
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1403
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1146
int(* AppLayerTxMatch)(ThreadVars *, DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition: detect.h:1132
SshHeader cli_hdr
Definition: app-layer-ssh.h:74
#define SCLogDebug(...)
Definition: util-debug.h:335
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
struct Flow_ * flow
Definition: decode.h:444
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
uint8_t proto
Definition: flow.h:346
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:235
#define unlikely(expr)
Definition: util-optimize.h:35
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Signature * sig_list
Definition: detect.h:726
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:195
Data needed for Match()
Definition: detect.h:333
void SigCleanSignatures(DetectEngineCtx *de_ctx)
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:232
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
const char * name
Definition: detect.h:1160
int DetectEngineInspectGenericList(ThreadVars *tv, const DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Flow *f, const uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Do the content inspection & validation for a signature.
Signature container.
Definition: detect.h:492
#define TRUE
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:319
#define MAX_SUBSTRINGS
void * protoctx
Definition: flow.h:398
main detection engine ctx
Definition: detect.h:720
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
void * alstate
Definition: flow.h:436
#define DE_QUIET
Definition: detect.h:298
#define str(s)
#define SSH_FLAG_VERSION_PARSED
Definition: app-layer-ssh.h:29
#define SIG_FLAG_TOCLIENT
Definition: detect.h:244
uint8_t flags
Definition: detect.h:721
SshHeader srv_hdr
Definition: app-layer-ssh.h:73
Data structures and function prototypes for keeping state for the detection engine.
void(* Free)(void *)
Definition: detect.h:1151
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define FLOW_DESTROY(f)
Definition: flow-util.h:115
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1752
void DetectSetupParseRegexes(const char *parse_str, pcre **parse_regex, pcre_extra **parse_regex_study)
#define SIGMATCH_QUOTES_OPTIONAL
Definition: detect.h:1340
#define SIG_FLAG_TOSERVER
Definition: detect.h:243
#define SCEnter(...)
Definition: util-debug.h:337
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
uint8_t flowflags
Definition: decode.h:438
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
uint8_t * software_version
Definition: app-layer-ssh.h:61
#define STREAM_TOCLIENT
Definition: stream.h:32
#define FLOW_PKT_TOSERVER
Definition: flow.h:193
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol&#39;s parser thread context.
int SigGroupCleanup(DetectEngineCtx *de_ctx)
uint8_t type
Definition: detect.h:325
#define SCReturnInt(x)
Definition: util-debug.h:341
const char * desc
Definition: detect.h:1162
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:282
int DetectBufferTypeRegister(const char *name)
uint8_t flags
Definition: app-layer-ssh.h:58
SigMatchCtx * ctx
Definition: detect.h:327
#define SCMalloc(a)
Definition: util-mem.h:174
#define PARSE_REGEX
Regex for parsing the softwareversion string.
#define SCFree(a)
Definition: util-mem.h:236
PoolThreadReserved res
uint16_t tx_id
const char * url
Definition: detect.h:1163
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
#define STREAM_TOSERVER
Definition: stream.h:31
SCMutex m
Definition: flow-hash.h:105
#define PKT_HAS_FLOW
Definition: decode.h:1101
#define SCStrdup(a)
Definition: util-mem.h:220
#define DOC_URL
Definition: suricata.h:86
void DetectSshSoftwareVersionRegister(void)
Registration function for keyword: ssh.softwareversion.
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:226
Per thread variable structure.
Definition: threadvars.h:57
AppProto alproto
application level protocol
Definition: flow.h:407
uint32_t flags
Definition: decode.h:442
#define DOC_VERSION
Definition: suricata.h:91
uint16_t flags
Definition: detect.h:1154
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself...
Flow data structure.
Definition: flow.h:327
#define PKT_STREAM_EST
Definition: decode.h:1099
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback)
register inspect engine at start up time
void(* RegisterTests)(void)
Definition: detect.h:1152
a single match condition for a signature
Definition: detect.h:324
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, uint8_t *input, uint32_t input_len)
DetectEngineCtx * DetectEngineCtxInit(void)