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 (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;
101 
102  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study);
103 
104  g_ssh_banner_list_id = DetectBufferTypeRegister("ssh_banner");
105 
108  InspectSshBanner);
111  InspectSshBanner);
112 }
113 
114 /**
115  * \brief match the specified version on a ssh session
116  *
117  * \param t pointer to thread vars
118  * \param det_ctx pointer to the pattern matcher thread
119  * \param p pointer to the current packet
120  * \param m pointer to the sigmatch that we will cast into DetectSshSoftwareVersionData
121  *
122  * \retval 0 no match
123  * \retval 1 match
124  */
125 static int DetectSshSoftwareVersionMatch (DetectEngineThreadCtx *det_ctx,
126  Flow *f, uint8_t flags, void *state, void *txv,
127  const Signature *s, const SigMatchCtx *m)
128 {
129  SCEnter();
130 
132  SshState *ssh_state = (SshState *)state;
133  if (ssh_state == NULL) {
134  SCLogDebug("no ssh state, no match");
135  SCReturnInt(0);
136  }
137 
138  int ret = 0;
139  if ((flags & STREAM_TOCLIENT) && (ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
140  SCLogDebug("looking for ssh server softwareversion %s length %"PRIu16" on %s", ssh->software_ver, ssh->len, ssh_state->srv_hdr.software_version);
141  ret = (strncmp((char *) ssh_state->srv_hdr.software_version, (char *) ssh->software_ver, ssh->len) == 0)? 1 : 0;
142  } else if ((flags & STREAM_TOSERVER) && (ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
143  SCLogDebug("looking for ssh client softwareversion %s length %"PRIu16" on %s", ssh->software_ver, ssh->len, ssh_state->cli_hdr.software_version);
144  ret = (strncmp((char *) ssh_state->cli_hdr.software_version, (char *) ssh->software_ver, ssh->len) == 0)? 1 : 0;
145  }
146  SCReturnInt(ret);
147 }
148 
149 /**
150  * \brief This function is used to parse IPV4 ip_id passed via keyword: "id"
151  *
152  * \param idstr Pointer to the user provided id option
153  *
154  * \retval id_d pointer to DetectSshSoftwareVersionData on success
155  * \retval NULL on failure
156  */
157 static DetectSshSoftwareVersionData *DetectSshSoftwareVersionParse (const char *str)
158 {
159  DetectSshSoftwareVersionData *ssh = NULL;
160 #define MAX_SUBSTRINGS 30
161  int ret = 0, res = 0;
162  int ov[MAX_SUBSTRINGS];
163 
164  ret = pcre_exec(parse_regex, parse_regex_study, str, strlen(str), 0, 0,
165  ov, MAX_SUBSTRINGS);
166 
167  if (ret < 1 || ret > 3) {
168  SCLogError(SC_ERR_PCRE_MATCH, "invalid ssh.softwareversion option");
169  goto error;
170  }
171 
172  if (ret > 1) {
173  const char *str_ptr = NULL;
174  res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
175  if (res < 0) {
176  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
177  goto error;
178  }
179 
180  /* We have a correct id option */
181  ssh = SCMalloc(sizeof(DetectSshSoftwareVersionData));
182  if (unlikely(ssh == NULL))
183  goto error;
184 
185  ssh->software_ver = (uint8_t *)SCStrdup((char *)str_ptr);
186  if (ssh->software_ver == NULL) {
187  goto error;
188  }
189  pcre_free_substring(str_ptr);
190 
191  ssh->len = strlen((char *)ssh->software_ver);
192 
193  SCLogDebug("will look for ssh %s", ssh->software_ver);
194  }
195 
196  return ssh;
197 
198 error:
199  if (ssh != NULL)
200  DetectSshSoftwareVersionFree(ssh);
201  return NULL;
202 
203 }
204 
205 /**
206  * \brief this function is used to add the parsed "id" option
207  * \brief into the current signature
208  *
209  * \param de_ctx pointer to the Detection Engine Context
210  * \param s pointer to the Current Signature
211  * \param idstr pointer to the user provided "id" option
212  *
213  * \retval 0 on Success
214  * \retval -1 on Failure
215  */
216 static int DetectSshSoftwareVersionSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
217 {
218  DetectSshSoftwareVersionData *ssh = NULL;
219  SigMatch *sm = NULL;
220 
222  return -1;
223 
224  ssh = DetectSshSoftwareVersionParse(str);
225  if (ssh == NULL)
226  goto error;
227 
228  /* Okay so far so good, lets get this into a SigMatch
229  * and put it in the Signature. */
230  sm = SigMatchAlloc();
231  if (sm == NULL)
232  goto error;
233 
235  sm->ctx = (void *)ssh;
236 
237  SigMatchAppendSMToList(s, sm, g_ssh_banner_list_id);
238  return 0;
239 
240 error:
241  if (ssh != NULL)
242  DetectSshSoftwareVersionFree(ssh);
243  if (sm != NULL)
244  SCFree(sm);
245  return -1;
246 
247 }
248 
249 /**
250  * \brief this function will free memory associated with DetectSshSoftwareVersionData
251  *
252  * \param id_d pointer to DetectSshSoftwareVersionData
253  */
254 static void DetectSshSoftwareVersionFree(void *ptr)
255 {
256  if (ptr == NULL)
257  return;
258 
260  if (ssh->software_ver != NULL)
261  SCFree(ssh->software_ver);
262  SCFree(ssh);
263 }
264 
265 #ifdef UNITTESTS /* UNITTESTS */
266 
267 /**
268  * \test DetectSshSoftwareVersionTestParse01 is a test to make sure that we parse
269  * a software version correctly
270  */
271 static int DetectSshSoftwareVersionTestParse01 (void)
272 {
273  DetectSshSoftwareVersionData *ssh = NULL;
274  ssh = DetectSshSoftwareVersionParse("PuTTY_1.0");
275  if (ssh != NULL && strncmp((char *) ssh->software_ver, "PuTTY_1.0", 9) == 0) {
276  DetectSshSoftwareVersionFree(ssh);
277  return 1;
278  }
279 
280  return 0;
281 }
282 
283 /**
284  * \test DetectSshSoftwareVersionTestParse02 is a test to make sure that we parse
285  * the software version correctly
286  */
287 static int DetectSshSoftwareVersionTestParse02 (void)
288 {
289  DetectSshSoftwareVersionData *ssh = NULL;
290  ssh = DetectSshSoftwareVersionParse("\"SecureCRT-4.0\"");
291  if (ssh != NULL && strncmp((char *) ssh->software_ver, "SecureCRT-4.0", 13) == 0) {
292  DetectSshSoftwareVersionFree(ssh);
293  return 1;
294  }
295 
296  return 0;
297 }
298 
299 /**
300  * \test DetectSshSoftwareVersionTestParse03 is a test to make sure that we
301  * don't return a ssh_data with an empty value specified
302  */
303 static int DetectSshSoftwareVersionTestParse03 (void)
304 {
305  DetectSshSoftwareVersionData *ssh = NULL;
306  ssh = DetectSshSoftwareVersionParse("");
307  if (ssh != NULL) {
308  DetectSshSoftwareVersionFree(ssh);
309  return 0;
310  }
311 
312  return 1;
313 }
314 
315 
316 #include "stream-tcp-reassemble.h"
317 
318 /** \test Send a get request in three chunks + more data. */
319 static int DetectSshSoftwareVersionTestDetect01(void)
320 {
321  int result = 0;
322  Flow f;
323  uint8_t sshbuf1[] = "SSH-1.";
324  uint32_t sshlen1 = sizeof(sshbuf1) - 1;
325  uint8_t sshbuf2[] = "10-PuTTY_2.123" ;
326  uint32_t sshlen2 = sizeof(sshbuf2) - 1;
327  uint8_t sshbuf3[] = "\n";
328  uint32_t sshlen3 = sizeof(sshbuf3) - 1;
329  uint8_t sshbuf4[] = "whatever...";
330  uint32_t sshlen4 = sizeof(sshbuf4) - 1;
331  TcpSession ssn;
332  Packet *p = NULL;
333  Signature *s = NULL;
334  ThreadVars th_v;
335  DetectEngineThreadCtx *det_ctx = NULL;
337 
338  memset(&th_v, 0, sizeof(th_v));
339  memset(&f, 0, sizeof(f));
340  memset(&ssn, 0, sizeof(ssn));
341 
342  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
343 
344  FLOW_INITIALIZE(&f);
345  f.protoctx = (void *)&ssn;
346  p->flow = &f;
350  f.alproto = ALPROTO_SSH;
351  f.proto = IPPROTO_TCP;
352 
354 
356  if (de_ctx == NULL) {
357  goto end;
358  }
359 
360  de_ctx->flags |= DE_QUIET;
361 
362  s = de_ctx->sig_list = SigInit(de_ctx,"alert ssh any any -> any any (msg:\"SSH\"; ssh.softwareversion:PuTTY_2.123; sid:1;)");
363  if (s == NULL) {
364  goto end;
365  }
366 
367  SigGroupBuild(de_ctx);
368  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
369 
370  FLOWLOCK_WRLOCK(&f);
371  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
372  STREAM_TOSERVER, sshbuf1, sshlen1);
373  if (r != 0) {
374  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
375  FLOWLOCK_UNLOCK(&f);
376  goto end;
377  }
378 
379  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
380  sshbuf2, sshlen2);
381  if (r != 0) {
382  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
383  FLOWLOCK_UNLOCK(&f);
384  goto end;
385  }
386 
387  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
388  sshbuf3, sshlen3);
389  if (r != 0) {
390  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
391  FLOWLOCK_UNLOCK(&f);
392  goto end;
393  }
394 
395  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
396  sshbuf4, sshlen4);
397  if (r != 0) {
398  printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
399  FLOWLOCK_UNLOCK(&f);
400  goto end;
401  }
402  FLOWLOCK_UNLOCK(&f);
403 
404  SshState *ssh_state = f.alstate;
405  if (ssh_state == NULL) {
406  printf("no ssh state: ");
407  goto end;
408  }
409 
410  /* do detect */
411  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
412 
413  if ( !(PacketAlertCheck(p, 1))) {
414  printf("Error, the sig should match: ");
415  goto end;
416  }
417 
418  result = 1;
419 end:
420  SigGroupCleanup(de_ctx);
421  SigCleanSignatures(de_ctx);
422 
423  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
424  DetectEngineCtxFree(de_ctx);
425 
427  FLOW_DESTROY(&f);
428 
429  UTHFreePackets(&p, 1);
430 
431  if (alp_tctx != NULL)
432  AppLayerParserThreadCtxFree(alp_tctx);
433  return result;
434 }
435 
436 /** \test Send a get request in three chunks + more data. */
437 static int DetectSshSoftwareVersionTestDetect02(void)
438 {
439  int result = 0;
440  Flow f;
441  uint8_t sshbuf1[] = "SSH-1.99-Pu";
442  uint32_t sshlen1 = sizeof(sshbuf1) - 1;
443  uint8_t sshbuf2[] = "TTY_2.123" ;
444  uint32_t sshlen2 = sizeof(sshbuf2) - 1;
445  uint8_t sshbuf3[] = "\n";
446  uint32_t sshlen3 = sizeof(sshbuf3) - 1;
447  uint8_t sshbuf4[] = "whatever...";
448  uint32_t sshlen4 = sizeof(sshbuf4) - 1;
449  TcpSession ssn;
450  Packet *p = NULL;
451  Signature *s = NULL;
452  ThreadVars th_v;
453  DetectEngineThreadCtx *det_ctx = NULL;
455 
456  memset(&th_v, 0, sizeof(th_v));
457  memset(&f, 0, sizeof(f));
458  memset(&ssn, 0, sizeof(ssn));
459 
460  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
461 
462  FLOW_INITIALIZE(&f);
463  f.protoctx = (void *)&ssn;
464  p->flow = &f;
468  f.alproto = ALPROTO_SSH;
469  f.proto = IPPROTO_TCP;
470 
472 
474  if (de_ctx == NULL) {
475  goto end;
476  }
477 
478  de_ctx->flags |= DE_QUIET;
479 
480  s = de_ctx->sig_list = SigInit(de_ctx,"alert ssh any any -> any any (msg:\"SSH\"; ssh.softwareversion:PuTTY_2.123; sid:1;)");
481  if (s == NULL) {
482  goto end;
483  }
484 
485  SigGroupBuild(de_ctx);
486  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
487 
488  FLOWLOCK_WRLOCK(&f);
489  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
490  STREAM_TOSERVER, sshbuf1, sshlen1);
491  if (r != 0) {
492  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
493  FLOWLOCK_UNLOCK(&f);
494  goto end;
495  }
496 
497  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
498  sshbuf2, sshlen2);
499  if (r != 0) {
500  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
501  FLOWLOCK_UNLOCK(&f);
502  goto end;
503  }
504 
505  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
506  sshbuf3, sshlen3);
507  if (r != 0) {
508  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
509  FLOWLOCK_UNLOCK(&f);
510  goto end;
511  }
512 
513  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
514  sshbuf4, sshlen4);
515  if (r != 0) {
516  printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
517  FLOWLOCK_UNLOCK(&f);
518  goto end;
519  }
520  FLOWLOCK_UNLOCK(&f);
521 
522  SshState *ssh_state = f.alstate;
523  if (ssh_state == NULL) {
524  printf("no ssh state: ");
525  goto end;
526  }
527 
528  /* do detect */
529  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
530 
531  if ( !(PacketAlertCheck(p, 1))) {
532  printf("Error, the sig should match: ");
533  goto end;
534  }
535 
536  result = 1;
537 end:
538  SigGroupCleanup(de_ctx);
539  SigCleanSignatures(de_ctx);
540 
541  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
542  DetectEngineCtxFree(de_ctx);
543 
545  FLOW_DESTROY(&f);
546 
547  UTHFreePackets(&p, 1);
548  if (alp_tctx != NULL)
549  AppLayerParserThreadCtxFree(alp_tctx);
550  return result;
551 }
552 
553 /** \test Send a get request in three chunks + more data. */
554 static int DetectSshSoftwareVersionTestDetect03(void)
555 {
556  int result = 0;
557  Flow f;
558  uint8_t sshbuf1[] = "SSH-1.";
559  uint32_t sshlen1 = sizeof(sshbuf1) - 1;
560  uint8_t sshbuf2[] = "7-PuTTY_2.123" ;
561  uint32_t sshlen2 = sizeof(sshbuf2) - 1;
562  uint8_t sshbuf3[] = "\n";
563  uint32_t sshlen3 = sizeof(sshbuf3) - 1;
564  uint8_t sshbuf4[] = "whatever...";
565  uint32_t sshlen4 = sizeof(sshbuf4) - 1;
566  TcpSession ssn;
567  Packet *p = NULL;
568  Signature *s = NULL;
569  ThreadVars th_v;
570  DetectEngineThreadCtx *det_ctx = NULL;
572 
573  memset(&th_v, 0, sizeof(th_v));
574  memset(&f, 0, sizeof(f));
575  memset(&ssn, 0, sizeof(ssn));
576 
577  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
578 
579  FLOW_INITIALIZE(&f);
580  f.protoctx = (void *)&ssn;
581  p->flow = &f;
585  f.alproto = ALPROTO_SSH;
586  f.proto = IPPROTO_TCP;
587 
589 
591  if (de_ctx == NULL) {
592  goto end;
593  }
594 
595  de_ctx->flags |= DE_QUIET;
596 
597  s = de_ctx->sig_list = SigInit(de_ctx,"alert ssh any any -> any any (msg:\"SSH\"; ssh.softwareversion:lalala-3.1.4; sid:1;)");
598  if (s == NULL) {
599  goto end;
600  }
601 
602  SigGroupBuild(de_ctx);
603  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
604 
605  FLOWLOCK_WRLOCK(&f);
606  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
607  STREAM_TOSERVER, sshbuf1, sshlen1);
608  if (r != 0) {
609  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
610  FLOWLOCK_UNLOCK(&f);
611  goto end;
612  }
613 
614  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
615  sshbuf2, sshlen2);
616  if (r != 0) {
617  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
618  FLOWLOCK_UNLOCK(&f);
619  goto end;
620  }
621 
622  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
623  sshbuf3, sshlen3);
624  if (r != 0) {
625  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
626  FLOWLOCK_UNLOCK(&f);
627  goto end;
628  }
629 
630  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
631  sshbuf4, sshlen4);
632  if (r != 0) {
633  printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
634  FLOWLOCK_UNLOCK(&f);
635  goto end;
636  }
637  FLOWLOCK_UNLOCK(&f);
638 
639  SshState *ssh_state = f.alstate;
640  if (ssh_state == NULL) {
641  printf("no ssh state: ");
642  goto end;
643  }
644 
645  /* do detect */
646  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
647 
648  if (PacketAlertCheck(p, 1)) {
649  printf("Error, 1.7 version is not 2 compat, so the sig should not match: ");
650  goto end;
651  }
652 
653  result = 1;
654 end:
655  SigGroupCleanup(de_ctx);
656  SigCleanSignatures(de_ctx);
657 
658  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
659  DetectEngineCtxFree(de_ctx);
660 
662  FLOW_DESTROY(&f);
663 
664  UTHFreePackets(&p, 1);
665  if (alp_tctx != NULL)
666  AppLayerParserThreadCtxFree(alp_tctx);
667  return result;
668 }
669 
670 #endif /* UNITTESTS */
671 
672 /**
673  * \brief this function registers unit tests for DetectSshSoftwareVersion
674  */
675 static void DetectSshSoftwareVersionRegisterTests(void)
676 {
677 #ifdef UNITTESTS /* UNITTESTS */
678  UtRegisterTest("DetectSshSoftwareVersionTestParse01",
679  DetectSshSoftwareVersionTestParse01);
680  UtRegisterTest("DetectSshSoftwareVersionTestParse02",
681  DetectSshSoftwareVersionTestParse02);
682  UtRegisterTest("DetectSshSoftwareVersionTestParse03",
683  DetectSshSoftwareVersionTestParse03);
684  UtRegisterTest("DetectSshSoftwareVersionTestDetect01",
685  DetectSshSoftwareVersionTestDetect01);
686  UtRegisterTest("DetectSshSoftwareVersionTestDetect02",
687  DetectSshSoftwareVersionTestDetect02);
688  UtRegisterTest("DetectSshSoftwareVersionTestDetect03",
689  DetectSshSoftwareVersionTestDetect03);
690 #endif /* UNITTESTS */
691 }
692 
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1439
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1179
#define SIGMATCH_INFO_DEPRECATED
Definition: detect.h:1388
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:445
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:344
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:243
#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:762
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:203
Data needed for Match()
Definition: detect.h:322
void SigCleanSignatures(DetectEngineCtx *de_ctx)
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:240
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
const char * name
Definition: detect.h:1193
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:517
#define TRUE
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:308
#define MAX_SUBSTRINGS
void * protoctx
Definition: flow.h:400
main detection engine ctx
Definition: detect.h:756
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
void * alstate
Definition: flow.h:438
#define DE_QUIET
Definition: detect.h:287
#define str(s)
#define SSH_FLAG_VERSION_PARSED
Definition: app-layer-ssh.h:29
#define SIG_FLAG_TOCLIENT
Definition: detect.h:233
uint8_t flags
Definition: detect.h:757
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:1184
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define FLOW_DESTROY(f)
Definition: flow-util.h:119
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:1670
void DetectSetupParseRegexes(const char *parse_str, pcre **parse_regex, pcre_extra **parse_regex_study)
#define SIGMATCH_QUOTES_OPTIONAL
Definition: detect.h:1374
#define SIG_FLAG_TOSERVER
Definition: detect.h:232
#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:439
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.
uint16_t alternative
Definition: detect.h:1191
uint8_t * software_version
Definition: app-layer-ssh.h:61
#define STREAM_TOCLIENT
Definition: stream.h:32
#define FLOW_PKT_TOSERVER
Definition: flow.h:201
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:314
#define SCReturnInt(x)
Definition: util-debug.h:341
const char * desc
Definition: detect.h:1195
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:288
int DetectBufferTypeRegister(const char *name)
uint8_t flags
Definition: app-layer-ssh.h:58
SigMatchCtx * ctx
Definition: detect.h:316
#define SCMalloc(a)
Definition: util-mem.h:222
#define PARSE_REGEX
Regex for parsing the softwareversion string.
#define SCFree(a)
Definition: util-mem.h:322
PoolThreadReserved res
uint16_t tx_id
const char * url
Definition: detect.h:1196
int(* AppLayerTxMatch)(DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition: detect.h:1166
#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:1090
#define SCStrdup(a)
Definition: util-mem.h:268
#define DOC_URL
Definition: suricata.h:86
void DetectSshSoftwareVersionRegister(void)
Registration function for keyword: ssh.softwareversion.
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:232
Per thread variable structure.
Definition: threadvars.h:57
AppProto alproto
application level protocol
Definition: flow.h:409
uint32_t flags
Definition: decode.h:443
#define DOC_VERSION
Definition: suricata.h:91
uint16_t flags
Definition: detect.h:1187
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:325
#define PKT_STREAM_EST
Definition: decode.h:1088
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:1185
a single match condition for a signature
Definition: detect.h:313
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, uint8_t *input, uint32_t input_len)
DetectEngineCtx * DetectEngineCtxInit(void)