suricata
app-layer-ssh.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2014 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  * \author Victor Julien <victor@inliniac.net>
23  *
24  * App-layer parser for SSH protocol
25  *
26  */
27 
28 #include "suricata-common.h"
29 #include "decode.h"
30 #include "threads.h"
31 
32 #include "util-print.h"
33 #include "util-pool.h"
34 
35 #include "stream-tcp-private.h"
36 #include "stream-tcp-reassemble.h"
37 #include "stream-tcp.h"
38 #include "stream.h"
39 
40 #include "app-layer-detect-proto.h"
41 #include "app-layer-protos.h"
42 #include "app-layer-parser.h"
43 #include "app-layer-ssh.h"
44 #include "rust.h"
45 
46 #include "conf.h"
47 
48 #include "util-spm.h"
49 #include "util-unittest.h"
50 #include "util-debug.h"
51 #include "flow-private.h"
52 
53 #include "util-byte.h"
54 #include "util-memcmp.h"
55 
56 /* HASSH fingerprints are disabled by default */
57 #define SSH_CONFIG_DEFAULT_HASSH false
58 /* Bypassing the encrypted part of the connections */
59 #define SSH_CONFIG_DEFAULT_ENCRYPTION_BYPASS SSH_HANDLE_ENCRYPTION_TRACK_ONLY
60 
61 static int SSHRegisterPatternsForProtocolDetection(void)
62 {
64  IPPROTO_TCP, ALPROTO_SSH, "SSH-", 4, 0, STREAM_TOSERVER) < 0) {
65  return -1;
66  }
68  IPPROTO_TCP, ALPROTO_SSH, "SSH-", 4, 0, STREAM_TOCLIENT) < 0) {
69  return -1;
70  }
71  return 0;
72 }
73 
74 bool SSHTxLogCondition(ThreadVars *tv, const Packet *p, void *state, void *tx, uint64_t tx_id)
75 {
76  return SCSshTxGetLogCondition(tx);
77 }
78 
79 /** \brief Function to register the SSH protocol parsers and other functions
80  */
82 {
83  const char *proto_name = "ssh";
84 
85  if (SCAppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
87  if (SSHRegisterPatternsForProtocolDetection() < 0)
88  return;
89 
90  /* Check if we should generate Hassh fingerprints */
91  int enable_hassh = SSH_CONFIG_DEFAULT_HASSH;
92  const char *strval = NULL;
93  if (SCConfGet("app-layer.protocols.ssh.hassh", &strval) != 1) {
94  enable_hassh = SSH_CONFIG_DEFAULT_HASSH;
95  } else if (strcmp(strval, "auto") == 0) {
96  enable_hassh = SSH_CONFIG_DEFAULT_HASSH;
97  } else if (SCConfValIsFalse(strval)) {
98  enable_hassh = SSH_CONFIG_DEFAULT_HASSH;
99  } else if (SCConfValIsTrue(strval)) {
100  enable_hassh = true;
101  }
102 
103  if (RunmodeIsUnittests() || enable_hassh) {
104  SCSshEnableHassh();
105  }
106 
107  SshEncryptionHandling encryption_bypass = SSH_CONFIG_DEFAULT_ENCRYPTION_BYPASS;
108  SCConfNode *encryption_node = SCConfGetNode("app-layer.protocols.ssh.encryption-handling");
109  if (encryption_node != NULL && encryption_node->val != NULL) {
110  if (strcmp(encryption_node->val, "full") == 0) {
111  encryption_bypass = SSH_HANDLE_ENCRYPTION_FULL;
112  } else if (strcmp(encryption_node->val, "track-only") == 0) {
113  encryption_bypass = SSH_HANDLE_ENCRYPTION_TRACK_ONLY;
114  } else if (strcmp(encryption_node->val, "bypass") == 0) {
115  encryption_bypass = SSH_HANDLE_ENCRYPTION_BYPASS;
116  } else {
117  encryption_bypass = SSH_CONFIG_DEFAULT_ENCRYPTION_BYPASS;
118  }
119  }
120 
121  if (encryption_bypass) {
122  SCLogConfig("ssh: bypass on the start of encryption enabled");
123  SCSshEnableBypass(encryption_bypass);
124  }
125  }
126 
127  SCLogDebug("Registering Rust SSH parser.");
128  SCRegisterSshParser();
129 
130 #ifdef UNITTESTS
132 #endif
133 }
134 
135 /* UNITTESTS */
136 #ifdef UNITTESTS
137 #include "flow-util.h"
138 #include "stream-tcp-util.h"
139 #include "util-unittest-helper.h"
140 
141 static int SSHParserTestUtilCheck(const char *protoexp, const char *softexp, void *tx, uint8_t flags) {
142  const uint8_t *protocol = NULL;
143  uint32_t p_len = 0;
144  const uint8_t *software = NULL;
145  uint32_t s_len = 0;
146 
147  if (SCSshTxGetProtocol(tx, &protocol, &p_len, flags) != 1) {
148  printf("Version string not parsed correctly return: ");
149  return 1;
150  }
151  if (protocol == NULL) {
152  printf("Version string not parsed correctly NULL: ");
153  return 1;
154  }
155 
156  if (p_len != strlen(protoexp)) {
157  printf("Version string not parsed correctly length: ");
158  return 1;
159  }
160  if (memcmp(protocol, protoexp, strlen(protoexp)) != 0) {
161  printf("Version string not parsed correctly: ");
162  return 1;
163  }
164 
165  if (softexp != NULL) {
166  if (SCSshTxGetSoftware(tx, &software, &s_len, flags) != 1)
167  return 1;
168  if (software == NULL)
169  return 1;
170  if (s_len != strlen(softexp)) {
171  printf("Software string not parsed correctly length: ");
172  return 1;
173  }
174  if (memcmp(software, softexp, strlen(softexp)) != 0) {
175  printf("Software string not parsed correctly: ");
176  return 1;
177  }
178  }
179  return 0;
180 }
181 
182 /** \test Send a version string in one chunk (client version str). */
183 static int SSHParserTest01(void)
184 {
185  int result = 0;
186  Flow f;
187  uint8_t sshbuf[] = "SSH-2.0-MySSHClient-0.5.1\n";
188  uint32_t sshlen = sizeof(sshbuf) - 1;
189  TcpSession ssn;
191 
192  memset(&f, 0, sizeof(f));
193  memset(&ssn, 0, sizeof(ssn));
194  FLOW_INITIALIZE(&f);
195  f.protoctx = (void *)&ssn;
196  f.alproto = ALPROTO_SSH;
197 
198  StreamTcpInitConfig(true);
199 
200  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
201  STREAM_TOSERVER | STREAM_EOF, sshbuf, sshlen);
202  if (r != 0) {
203  printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
204  goto end;
205  }
206 
207  void *ssh_state = f.alstate;
208  if (ssh_state == NULL) {
209  printf("no ssh state: ");
210  goto end;
211  }
212 
213  void *tx = SCSshStateGetTx(ssh_state, 0);
214  if (SCSshTxGetAlStateProgress(tx, STREAM_TOSERVER) != SshStateBannerDone) {
215  printf("Client version string not parsed: ");
216  goto end;
217  }
218 
219  if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER))
220  goto end;
221 
222  result = 1;
223 end:
224  if (alp_tctx != NULL)
226  StreamTcpFreeConfig(true);
227  FLOW_DESTROY(&f);
228  return result;
229 }
230 
231 /** \test Send a version string in one chunk but multiple lines and comments.
232  * (client version str)
233  */
234 static int SSHParserTest02(void)
235 {
236  int result = 0;
237  Flow f;
238  uint8_t sshbuf[] = "SSH-2.0-MySSHClient-0.5.1 some comments...\n";
239  uint32_t sshlen = sizeof(sshbuf) - 1;
240  TcpSession ssn;
242 
243  memset(&f, 0, sizeof(f));
244  memset(&ssn, 0, sizeof(ssn));
245  FLOW_INITIALIZE(&f);
246  f.protoctx = (void *)&ssn;
247  f.alproto = ALPROTO_SSH;
248 
249  StreamTcpInitConfig(true);
250 
251  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
252  STREAM_TOSERVER | STREAM_EOF, sshbuf, sshlen);
253  if (r != 0) {
254  printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
255  goto end;
256  }
257 
258  void *ssh_state = f.alstate;
259  if (ssh_state == NULL) {
260  printf("no ssh state: ");
261  goto end;
262  }
263  void *tx = SCSshStateGetTx(ssh_state, 0);
264 
265  if (SCSshTxGetAlStateProgress(tx, STREAM_TOSERVER) != SshStateBannerDone) {
266  printf("Client version string not parsed: ");
267  goto end;
268  }
269  if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER))
270  goto end;
271 
272  result = 1;
273 end:
274  if (alp_tctx != NULL)
276  StreamTcpFreeConfig(true);
277  FLOW_DESTROY(&f);
278  return result;
279 }
280 
281 /** \test Send a invalid version string in one chunk but multiple lines and comments.
282  * (client version str)
283  */
284 static int SSHParserTest03(void)
285 {
286  int result = 0;
287  Flow f;
288  uint8_t sshbuf[] = "SSH-2.0 some comments...\n";
289  uint32_t sshlen = sizeof(sshbuf) - 1;
290  TcpSession ssn;
292 
293  memset(&f, 0, sizeof(f));
294  memset(&ssn, 0, sizeof(ssn));
295  FLOW_INITIALIZE(&f);
296  f.protoctx = (void *)&ssn;
297  f.alproto = ALPROTO_SSH;
298 
299  StreamTcpInitConfig(true);
300 
301  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
302  STREAM_TOSERVER | STREAM_EOF, sshbuf, sshlen);
303  if (r == 0) {
304  printf("toclient chunk 1 returned %" PRId32 ", expected != 0: ", r);
305  goto end;
306  }
307 
308  void *ssh_state = f.alstate;
309  if (ssh_state == NULL) {
310  printf("no ssh state: ");
311  goto end;
312  }
313  void *tx = SCSshStateGetTx(ssh_state, 0);
314 
315  if (SCSshTxGetAlStateProgress(tx, STREAM_TOSERVER) == SshStateBannerDone) {
316  printf("Client version string parsed? It's not a valid string: ");
317  goto end;
318  }
319  const uint8_t *dummy = NULL;
320  uint32_t dummy_len = 0;
321  if (SCSshTxGetProtocol(tx, &dummy, &dummy_len, STREAM_TOSERVER) != 0)
322  goto end;
323  if (SCSshTxGetSoftware(tx, &dummy, &dummy_len, STREAM_TOSERVER) != 0)
324  goto end;
325 
326  result = 1;
327 end:
328  if (alp_tctx != NULL)
330  StreamTcpFreeConfig(true);
331  FLOW_DESTROY(&f);
332  return result;
333 }
334 
335 /** \test Send a version string in one chunk (server version str). */
336 static int SSHParserTest04(void)
337 {
338  int result = 0;
339  Flow f;
340  uint8_t sshbuf[] = "SSH-2.0-MySSHClient-0.5.1\n";
341  uint32_t sshlen = sizeof(sshbuf) - 1;
342  TcpSession ssn;
344 
345  memset(&f, 0, sizeof(f));
346  memset(&ssn, 0, sizeof(ssn));
347  FLOW_INITIALIZE(&f);
348  f.protoctx = (void *)&ssn;
349  f.alproto = ALPROTO_SSH;
350 
351  StreamTcpInitConfig(true);
352 
353  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
354  STREAM_TOCLIENT | STREAM_EOF, sshbuf, sshlen);
355  if (r != 0) {
356  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
357  goto end;
358  }
359 
360  void *ssh_state = f.alstate;
361  if (ssh_state == NULL) {
362  printf("no ssh state: ");
363  goto end;
364  }
365  void *tx = SCSshStateGetTx(ssh_state, 0);
366 
367  if (SCSshTxGetAlStateProgress(tx, STREAM_TOCLIENT) != SshStateBannerDone) {
368  printf("Client version string not parsed: ");
369  goto end;
370  }
371  if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT))
372  goto end;
373 
374  result = 1;
375 
376 end:
377  if (alp_tctx != NULL)
379  StreamTcpFreeConfig(true);
380  FLOW_DESTROY(&f);
381  return result;
382 }
383 
384 /** \test Send a version string in one chunk (server version str)
385  */
386 static int SSHParserTest05(void)
387 {
388  int result = 0;
389  Flow f;
390  uint8_t sshbuf[] = "SSH-2.0-MySSHClient-0.5.1 some comments...\n";
391  uint32_t sshlen = sizeof(sshbuf) - 1;
392  TcpSession ssn;
394 
395  memset(&f, 0, sizeof(f));
396  memset(&ssn, 0, sizeof(ssn));
397  FLOW_INITIALIZE(&f);
398  f.protoctx = (void *)&ssn;
399  f.alproto = ALPROTO_SSH;
400 
401  StreamTcpInitConfig(true);
402 
403  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
404  STREAM_TOCLIENT | STREAM_EOF, sshbuf, sshlen);
405  if (r != 0) {
406  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
407  goto end;
408  }
409 
410  void *ssh_state = f.alstate;
411  if (ssh_state == NULL) {
412  printf("no ssh state: ");
413  goto end;
414  }
415  void *tx = SCSshStateGetTx(ssh_state, 0);
416 
417  if (SCSshTxGetAlStateProgress(tx, STREAM_TOCLIENT) != SshStateBannerDone) {
418  printf("Client version string not parsed: ");
419  goto end;
420  }
421  if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT))
422  goto end;
423 
424  result = 1;
425 end:
426  if (alp_tctx != NULL)
428  StreamTcpFreeConfig(true);
429  FLOW_DESTROY(&f);
430  return result;
431 }
432 
433 /** \test Send a invalid version string in one chunk (server version str)
434  */
435 static int SSHParserTest06(void)
436 {
437  int result = 0;
438  Flow f;
439  uint8_t sshbuf[] = "SSH-2.0 some comments...\n";
440  uint32_t sshlen = sizeof(sshbuf) - 1;
441  TcpSession ssn;
443 
444  memset(&f, 0, sizeof(f));
445  memset(&ssn, 0, sizeof(ssn));
446  FLOW_INITIALIZE(&f);
447  f.protoctx = (void *)&ssn;
448  f.alproto = ALPROTO_SSH;
449 
450  StreamTcpInitConfig(true);
451 
452  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
453  STREAM_TOCLIENT | STREAM_EOF, sshbuf, sshlen);
454  if (r == 0) {
455  printf("toserver chunk 1 returned %" PRId32 ", expected != 0: ", r);
456  goto end;
457  }
458  /* Ok, it returned an error. Let's make sure we didn't parse the string at all */
459 
460  void *ssh_state = f.alstate;
461  if (ssh_state == NULL) {
462  printf("no ssh state: ");
463  goto end;
464  }
465  void *tx = SCSshStateGetTx(ssh_state, 0);
466 
467  if (SCSshTxGetAlStateProgress(tx, STREAM_TOCLIENT) == SshStateBannerDone) {
468  printf("Client version string parsed? It's not a valid string: ");
469  goto end;
470  }
471  const uint8_t *dummy = NULL;
472  uint32_t dummy_len = 0;
473  if (SCSshTxGetProtocol(tx, &dummy, &dummy_len, STREAM_TOCLIENT) != 0)
474  goto end;
475  if (SCSshTxGetSoftware(tx, &dummy, &dummy_len, STREAM_TOCLIENT) != 0)
476  goto end;
477 
478 
479  result = 1;
480 end:
481  if (alp_tctx != NULL)
483  StreamTcpFreeConfig(true);
484  FLOW_DESTROY(&f);
485  return result;
486 }
487 
488 #define MAX_SSH_TEST_SIZE 512
489 
490 static int SSHParserTest07(void)
491 {
492  TcpReassemblyThreadCtx *ra_ctx = NULL;
493  ThreadVars tv;
494  TcpSession ssn;
495  Flow *f = NULL;
496  Packet *p = NULL;
497 
498  char sshbufs[2][MAX_SSH_TEST_SIZE] = {"SSH-2.", "0-MySSHClient-0.5.1\r\n"};
499 
500  memset(&tv, 0x00, sizeof(tv));
501 
502  StreamTcpUTInit(&ra_ctx);
507 
508  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
509  FAIL_IF_NULL(f);
510  f->protoctx = &ssn;
511  f->proto = IPPROTO_TCP;
512  f->alproto = ALPROTO_SSH;
513 
514  p = PacketGetFromAlloc();
515  FAIL_IF(unlikely(p == NULL));
516  p->proto = IPPROTO_TCP;
517  p->flow = f;
518 
519  uint32_t seq = 2;
520  for (int i=0; i<2; i++) {
521  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, (uint8_t *) sshbufs[i], strlen(sshbufs[i])) == -1);
522  seq += strlen(sshbufs[i]);
523  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
524  }
525 
526  void *ssh_state = f->alstate;
527  FAIL_IF_NULL(ssh_state);
528  void *tx = SCSshStateGetTx(ssh_state, 0);
529  FAIL_IF(SCSshTxGetAlStateProgress(tx, STREAM_TOSERVER) != SshStateBannerDone);
530 
531  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
532 
533  UTHFreePacket(p);
535  StreamTcpUTDeinit(ra_ctx);
536  UTHFreeFlow(f);
537  PASS;
538 }
539 
540 /** \test Send a version banner in three chunks. */
541 static int SSHParserTest08(void)
542 {
543  TcpReassemblyThreadCtx *ra_ctx = NULL;
544  ThreadVars tv;
545  TcpSession ssn;
546  Flow *f = NULL;
547  Packet *p = NULL;
548 
549  char sshbufs[3][MAX_SSH_TEST_SIZE] = {"SSH-", "2.", "0-MySSHClient-0.5.1\r\n"};
550 
551  memset(&tv, 0x00, sizeof(tv));
552 
553  StreamTcpUTInit(&ra_ctx);
558 
559  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
560  FAIL_IF_NULL(f);
561  f->protoctx = &ssn;
562  f->proto = IPPROTO_TCP;
563  f->alproto = ALPROTO_SSH;
564 
565  p = PacketGetFromAlloc();
566  FAIL_IF(unlikely(p == NULL));
567  p->proto = IPPROTO_TCP;
568  p->flow = f;
569 
570  uint32_t seq = 2;
571  for (int i=0; i<3; i++) {
572  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, (uint8_t *) sshbufs[i], strlen(sshbufs[i])) == -1);
573  seq += strlen(sshbufs[i]);
574  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
575  }
576 
577  void *ssh_state = f->alstate;
578  FAIL_IF_NULL(ssh_state);
579  void *tx = SCSshStateGetTx(ssh_state, 0);
580  FAIL_IF(SCSshTxGetAlStateProgress(tx, STREAM_TOSERVER) != SshStateBannerDone);
581 
582  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
583 
584  UTHFreePacket(p);
586  StreamTcpUTDeinit(ra_ctx);
587  UTHFreeFlow(f);
588  PASS;
589 }
590 
591 static int SSHParserTest09(void)
592 {
593  TcpReassemblyThreadCtx *ra_ctx = NULL;
594  ThreadVars tv;
595  TcpSession ssn;
596  Flow *f = NULL;
597  Packet *p = NULL;
598 
599  char sshbufs[2][MAX_SSH_TEST_SIZE] = {"SSH-2.", "0-MySSHClient-0.5.1\r\n"};
600 
601  memset(&tv, 0x00, sizeof(tv));
602 
603  StreamTcpUTInit(&ra_ctx);
608 
609  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
610  FAIL_IF_NULL(f);
611  f->protoctx = &ssn;
612  f->proto = IPPROTO_TCP;
613  f->alproto = ALPROTO_SSH;
614 
615  p = PacketGetFromAlloc();
616  FAIL_IF(unlikely(p == NULL));
617  p->proto = IPPROTO_TCP;
618  p->flow = f;
619 
620  uint32_t seq = 2;
621  for (int i=0; i<2; i++) {
622  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, (uint8_t *) sshbufs[i], strlen(sshbufs[i])) == -1);
623  seq += strlen(sshbufs[i]);
624  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
625  }
626 
627  void *ssh_state = f->alstate;
628  FAIL_IF_NULL(ssh_state);
629  void *tx = SCSshStateGetTx(ssh_state, 0);
630  FAIL_IF(SCSshTxGetAlStateProgress(tx, STREAM_TOCLIENT) != SshStateBannerDone);
631 
632  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT));
633 
634  UTHFreePacket(p);
636  StreamTcpUTDeinit(ra_ctx);
637  UTHFreeFlow(f);
638  PASS;
639 }
640 
641 /** \test Send a version banner in three chunks. */
642 static int SSHParserTest10(void)
643 {
644  TcpReassemblyThreadCtx *ra_ctx = NULL;
645  ThreadVars tv;
646  TcpSession ssn;
647  Flow *f = NULL;
648  Packet *p = NULL;
649 
650  char sshbufs[3][MAX_SSH_TEST_SIZE] = {"SSH-", "2.", "0-MySSHClient-0.5.1\r\n"};
651 
652  memset(&tv, 0x00, sizeof(tv));
653 
654  StreamTcpUTInit(&ra_ctx);
659 
660  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
661  FAIL_IF_NULL(f);
662  f->protoctx = &ssn;
663  f->proto = IPPROTO_TCP;
664  f->alproto = ALPROTO_SSH;
665 
666  p = PacketGetFromAlloc();
667  FAIL_IF(unlikely(p == NULL));
668  p->proto = IPPROTO_TCP;
669  p->flow = f;
670 
671  uint32_t seq = 2;
672  for (int i=0; i<3; i++) {
673  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, (uint8_t *) sshbufs[i], strlen(sshbufs[i])) == -1);
674  seq += strlen(sshbufs[i]);
675  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
676  }
677 
678  void *ssh_state = f->alstate;
679  FAIL_IF_NULL(ssh_state);
680  void *tx = SCSshStateGetTx(ssh_state, 0);
681  FAIL_IF(SCSshTxGetAlStateProgress(tx, STREAM_TOCLIENT) != SshStateBannerDone);
682 
683  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT));
684 
685  UTHFreePacket(p);
687  StreamTcpUTDeinit(ra_ctx);
688  UTHFreeFlow(f);
689  PASS;
690 }
691 
692 /** \test Send a banner and record in three chunks. */
693 static int SSHParserTest11(void)
694 {
695  int result = 0;
696  Flow f;
697  uint8_t sshbuf1[] = "SSH-2.0-MySSHClient-0.5.1\r\n";
698  uint32_t sshlen1 = sizeof(sshbuf1) - 1;
699  uint8_t sshbuf2[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00};
700  uint32_t sshlen2 = sizeof(sshbuf2);
701  TcpSession ssn;
703 
704  memset(&f, 0, sizeof(f));
705  memset(&ssn, 0, sizeof(ssn));
706  FLOW_INITIALIZE(&f);
707  f.protoctx = (void *)&ssn;
708  f.alproto = ALPROTO_SSH;
709 
710  StreamTcpInitConfig(true);
711 
712  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
713  STREAM_TOSERVER, sshbuf1, sshlen1);
714  if (r != 0) {
715  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
716  goto end;
717  }
718  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
719  sshbuf2, sshlen2);
720  if (r != 0) {
721  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
722  goto end;
723  }
724 
725  void *ssh_state = f.alstate;
726  if (ssh_state == NULL) {
727  printf("no ssh state: ");
728  goto end;
729  }
730  void *tx = SCSshStateGetTx(ssh_state, 0);
731  if (SCSshTxGetFlags(tx, STREAM_TOSERVER) != SshStateFinished) {
732  printf("Didn't detect the msg code of new keys (ciphered data starts): ");
733  goto end;
734  }
735  if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER))
736  goto end;
737 
738  result = 1;
739 end:
740  if (alp_tctx != NULL)
742  StreamTcpFreeConfig(true);
743  FLOW_DESTROY(&f);
744  return result;
745 }
746 
747 /** \test Send a banner and 2 records record in four chunks. */
748 static int SSHParserTest12(void)
749 {
750  int result = 0;
751  Flow f;
752  uint8_t sshbuf1[] = "SSH-2.0-MySSHClient-0.5.1\r\n";
753  uint32_t sshlen1 = sizeof(sshbuf1) - 1;
754  uint8_t sshbuf2[] = { 0x00, 0x00, 0x00, 0x03,0x01, 17, 0x00};
755  uint32_t sshlen2 = sizeof(sshbuf2);
756  uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x03,0x01, 21, 0x00};
757  uint32_t sshlen3 = sizeof(sshbuf3);
758  TcpSession ssn;
760 
761  memset(&f, 0, sizeof(f));
762  memset(&ssn, 0, sizeof(ssn));
763  FLOW_INITIALIZE(&f);
764  f.protoctx = (void *)&ssn;
765  f.alproto = ALPROTO_SSH;
766 
767  StreamTcpInitConfig(true);
768 
769  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
770  STREAM_TOSERVER, sshbuf1, sshlen1);
771  if (r != 0) {
772  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
773  goto end;
774  }
775  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
776  sshbuf2, sshlen2);
777  if (r != 0) {
778  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
779  goto end;
780  }
781  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
782  sshbuf3, sshlen3);
783  if (r != 0) {
784  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
785  goto end;
786  }
787 
788  void *ssh_state = f.alstate;
789  if (ssh_state == NULL) {
790  printf("no ssh state: ");
791  goto end;
792  }
793  void *tx = SCSshStateGetTx(ssh_state, 0);
794  if (SCSshTxGetFlags(tx, STREAM_TOSERVER) != SshStateFinished) {
795  printf("Didn't detect the msg code of new keys (ciphered data starts): ");
796  goto end;
797  }
798  if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER))
799  goto end;
800 
801  result = 1;
802 end:
803  if (alp_tctx != NULL)
805  StreamTcpFreeConfig(true);
806  FLOW_DESTROY(&f);
807  return result;
808 }
809 
810 /** \test Send a banner and 2 records record in four chunks. */
811 static int SSHParserTest13(void)
812 {
813  TcpReassemblyThreadCtx *ra_ctx = NULL;
814  ThreadVars tv;
815  TcpSession ssn;
816  Flow *f = NULL;
817  Packet *p = NULL;
818 
819  uint8_t sshbuf1[] = "SSH-2.0-MySSHClient-0.5.1\r\n";
820  uint8_t sshbuf2[] = { 0x00, 0x00, 0x00, 0x02, 0x01, 17};
821  uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x02, 0x01, 21};
822 
823  uint8_t* sshbufs[3] = {sshbuf1, sshbuf2, sshbuf3};
824  uint32_t sshlens[3] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2), sizeof(sshbuf3)};
825 
826  memset(&tv, 0x00, sizeof(tv));
827 
828  StreamTcpUTInit(&ra_ctx);
833 
834  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
835  FAIL_IF_NULL(f);
836  f->protoctx = &ssn;
837  f->proto = IPPROTO_TCP;
838  f->alproto = ALPROTO_SSH;
839 
840  p = PacketGetFromAlloc();
841  FAIL_IF(unlikely(p == NULL));
842  p->proto = IPPROTO_TCP;
843  p->flow = f;
844 
845  uint32_t seq = 2;
846  for (int i=0; i<3; i++) {
847  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, sshbufs[i], sshlens[i]) == -1);
848  seq += sshlens[i];
849  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
850  }
851 
852  void *ssh_state = f->alstate;
853  FAIL_IF_NULL(ssh_state);
854  void *tx = SCSshStateGetTx(ssh_state, 0);
855  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOSERVER) != SshStateFinished);
856 
857  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
858 
859  UTHFreePacket(p);
861  StreamTcpUTDeinit(ra_ctx);
862  UTHFreeFlow(f);
863  PASS;
864 }
865 
866 /** \test Send a banner and 2 records record in four chunks. */
867 static int SSHParserTest14(void)
868 {
869  TcpReassemblyThreadCtx *ra_ctx = NULL;
870  ThreadVars tv;
871  TcpSession ssn;
872  Flow *f = NULL;
873  Packet *p = NULL;
874 
875  uint8_t sshbuf1[] = "SSH-2.0-MySSHClient-0.5.1\r\n";
876  uint8_t sshbuf2[] = { 0x00, 0x00, 0x00, 0x10, 0x01, 17, 0x00};
877  uint8_t sshbuf3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
878  uint8_t sshbuf4[] = { 0x09, 0x10, 0x11, 0x12, 0x13, 0x00};
879  /* first byte of this record in sshbuf4 */
880  uint8_t sshbuf5[] = { 0x00, 0x00, 0x02, 0x01, 21};
881 
882  uint8_t* sshbufs[5] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4, sshbuf5};
883  uint32_t sshlens[5] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2), sizeof(sshbuf3), sizeof(sshbuf4), sizeof(sshbuf5)};
884 
885  memset(&tv, 0x00, sizeof(tv));
886 
887  StreamTcpUTInit(&ra_ctx);
892 
893  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
894  FAIL_IF_NULL(f);
895  f->protoctx = &ssn;
896  f->proto = IPPROTO_TCP;
897  f->alproto = ALPROTO_SSH;
898 
899  p = PacketGetFromAlloc();
900  FAIL_IF(unlikely(p == NULL));
901  p->proto = IPPROTO_TCP;
902  p->flow = f;
903 
904  uint32_t seq = 2;
905  for (int i=0; i<5; i++) {
906  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, sshbufs[i], sshlens[i]) == -1);
907  seq += sshlens[i];
908  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
909  }
910 
911  void *ssh_state = f->alstate;
912  FAIL_IF_NULL(ssh_state);
913  void *tx = SCSshStateGetTx(ssh_state, 0);
914  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOSERVER) != SshStateFinished);
915 
916  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
917 
918  UTHFreePacket(p);
920  StreamTcpUTDeinit(ra_ctx);
921  UTHFreeFlow(f);
922  PASS;
923 }
924 
925 /** \test Send a banner and 2 records record in four chunks. */
926 static int SSHParserTest15(void)
927 {
928  TcpReassemblyThreadCtx *ra_ctx = NULL;
929  ThreadVars tv;
930  TcpSession ssn;
931  Flow *f = NULL;
932  Packet *p = NULL;
933 
934  uint8_t sshbuf1[] = "SSH-2.0-MySSHClient-0.5.1\r\n";
935  uint8_t sshbuf2[] = { 0x00, 0x00, 0x00, 0x10, 0x01, 17, 0x00};
936  uint8_t sshbuf3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
937  uint8_t sshbuf4[] = { 0x09, 0x10, 0x11, 0x12, 0x13, 0x00};
938  uint8_t sshbuf5[] = { 0x00, 0x00, 0x02, 0x01, 20, 0x00, 0x00, 0x00, 0x02, 0x01, 21};
939 
940  uint8_t* sshbufs[5] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4, sshbuf5};
941  uint32_t sshlens[5] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2), sizeof(sshbuf3), sizeof(sshbuf4), sizeof(sshbuf5)};
942 
943  memset(&tv, 0x00, sizeof(tv));
944 
945  StreamTcpUTInit(&ra_ctx);
950 
951  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
952  FAIL_IF_NULL(f);
953  f->protoctx = &ssn;
954  f->proto = IPPROTO_TCP;
955  f->alproto = ALPROTO_SSH;
956 
957  p = PacketGetFromAlloc();
958  FAIL_IF(unlikely(p == NULL));
959  p->proto = IPPROTO_TCP;
960  p->flow = f;
961 
962  uint32_t seq = 2;
963  for (int i=0; i<5; i++) {
964  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, sshbufs[i], sshlens[i]) == -1);
965  seq += sshlens[i];
966  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
967  }
968 
969  void *ssh_state = f->alstate;
970  FAIL_IF_NULL(ssh_state);
971  void *tx = SCSshStateGetTx(ssh_state, 0);
972  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOSERVER) != SshStateFinished);
973 
974  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
975 
976  UTHFreePacket(p);
978  StreamTcpUTDeinit(ra_ctx);
979  UTHFreeFlow(f);
980  PASS;
981 }
982 
983 /** \test Send toserver a banner and record in three chunks. */
984 static int SSHParserTest16(void)
985 {
986  TcpReassemblyThreadCtx *ra_ctx = NULL;
987  ThreadVars tv;
988  TcpSession ssn;
989  Flow *f = NULL;
990  Packet *p = NULL;
991 
992  uint8_t sshbuf1[] = "SSH-";
993  uint8_t sshbuf2[] = "2.0-MySSHClient-0.5.1\r\n";
994  uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x03,0x01, 21, 0x00};
995 
996  uint8_t* sshbufs[3] = {sshbuf1, sshbuf2, sshbuf3};
997  uint32_t sshlens[3] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3)};
998 
999  memset(&tv, 0x00, sizeof(tv));
1000 
1001  StreamTcpUTInit(&ra_ctx);
1004  StreamTcpUTSetupStream(&ssn.server, 1);
1005  StreamTcpUTSetupStream(&ssn.client, 1);
1006 
1007  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1008  FAIL_IF_NULL(f);
1009  f->protoctx = &ssn;
1010  f->proto = IPPROTO_TCP;
1011  f->alproto = ALPROTO_SSH;
1012 
1013  p = PacketGetFromAlloc();
1014  FAIL_IF(unlikely(p == NULL));
1015  p->proto = IPPROTO_TCP;
1016  p->flow = f;
1017 
1018  uint32_t seq = 2;
1019  for (int i=0; i<3; i++) {
1020  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
1021  seq += sshlens[i];
1022  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
1023  }
1024 
1025  void *ssh_state = f->alstate;
1026  FAIL_IF_NULL(ssh_state);
1027  void *tx = SCSshStateGetTx(ssh_state, 0);
1028  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1029 
1030  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT));
1031 
1032  UTHFreePacket(p);
1034  StreamTcpUTDeinit(ra_ctx);
1035  UTHFreeFlow(f);
1036  PASS;
1037 }
1038 
1039 /** \test Send toserver a banner and 2 records record in four chunks. */
1040 static int SSHParserTest17(void)
1041 {
1042  TcpReassemblyThreadCtx *ra_ctx = NULL;
1043  ThreadVars tv;
1044  TcpSession ssn;
1045  Flow *f = NULL;
1046  Packet *p = NULL;
1047 
1048  uint8_t sshbuf1[] = "SSH-";
1049  uint8_t sshbuf2[] = "2.0-MySSHClient-0.5.1\r\n";
1050  uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 17, 0x00};
1051  uint8_t sshbuf4[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00};
1052 
1053  uint8_t* sshbufs[4] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4};
1054  uint32_t sshlens[4] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3), sizeof(sshbuf4)};
1055 
1056  memset(&tv, 0x00, sizeof(tv));
1057 
1058  StreamTcpUTInit(&ra_ctx);
1061  StreamTcpUTSetupStream(&ssn.server, 1);
1062  StreamTcpUTSetupStream(&ssn.client, 1);
1063 
1064  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1065  FAIL_IF_NULL(f);
1066  f->protoctx = &ssn;
1067  f->proto = IPPROTO_TCP;
1068  f->alproto = ALPROTO_SSH;
1069 
1070  p = PacketGetFromAlloc();
1071  FAIL_IF(unlikely(p == NULL));
1072  p->proto = IPPROTO_TCP;
1073  p->flow = f;
1074 
1075  uint32_t seq = 2;
1076  for (int i=0; i<4; i++) {
1077  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
1078  seq += sshlens[i];
1079  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
1080  }
1081 
1082  void *ssh_state = f->alstate;
1083  FAIL_IF_NULL(ssh_state);
1084  void *tx = SCSshStateGetTx(ssh_state, 0);
1085  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1086 
1087  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT));
1088 
1089  UTHFreePacket(p);
1091  StreamTcpUTDeinit(ra_ctx);
1092  UTHFreeFlow(f);
1093  PASS;
1094 }
1095 
1096 /** \test 2 directional test */
1097 static int SSHParserTest18(void)
1098 {
1099  TcpReassemblyThreadCtx *ra_ctx = NULL;
1100  ThreadVars tv;
1101  TcpSession ssn;
1102  Flow *f = NULL;
1103  Packet *p = NULL;
1104 
1105  uint8_t server1[] = "SSH-2.0-OpenSSH_4.7p1 Debian-8ubuntu3\r\n";
1106  uint8_t sshbuf1[] = "SSH-";
1107  uint8_t sshbuf2[] = "2.0-MySSHClient-0.5.1\r\n";
1108  uint8_t server2[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00 };
1109  uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00 };
1110 
1111 
1112  memset(&tv, 0x00, sizeof(tv));
1113 
1114  StreamTcpUTInit(&ra_ctx);
1117  StreamTcpUTSetupStream(&ssn.server, 1);
1118  StreamTcpUTSetupStream(&ssn.client, 1);
1119 
1120  uint8_t* sshbufs[5] = {server1, sshbuf1, sshbuf2, server2, sshbuf3};
1121  uint32_t sshlens[5] = {sizeof(server1) - 1, sizeof(sshbuf1) - 1, sizeof(sshbuf2) -1, sizeof(server2) - 1, sizeof(sshbuf3)};
1122  bool sshdirs[5] = {true, false, false, true, false};
1123 
1124  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1125  FAIL_IF_NULL(f);
1126  f->protoctx = &ssn;
1127  f->proto = IPPROTO_TCP;
1128  f->alproto = ALPROTO_SSH;
1129 
1130  p = PacketGetFromAlloc();
1131  FAIL_IF(unlikely(p == NULL));
1132  p->proto = IPPROTO_TCP;
1133  p->flow = f;
1134 
1135  uint32_t seqcli = 2;
1136  uint32_t seqsrv = 2;
1137  for (int i=0; i<5; i++) {
1138  if (sshdirs[i]) {
1139  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seqsrv, sshbufs[i], sshlens[i]) == -1);
1140  seqsrv += sshlens[i];
1141  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
1142  } else {
1143  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seqcli, sshbufs[i], sshlens[i]) == -1);
1144  seqcli += sshlens[i];
1145  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
1146  }
1147  }
1148 
1149  void *ssh_state = f->alstate;
1150  FAIL_IF_NULL(ssh_state);
1151  void *tx = SCSshStateGetTx(ssh_state, 0);
1152  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1153 
1155 
1156  UTHFreePacket(p);
1158  StreamTcpUTDeinit(ra_ctx);
1159  UTHFreeFlow(f);
1160  PASS;
1161 }
1162 
1163 /** \test Really long banner handling: bannel exactly 255 */
1164 static int SSHParserTest19(void)
1165 {
1166  TcpReassemblyThreadCtx *ra_ctx = NULL;
1167  ThreadVars tv;
1168  TcpSession ssn;
1169  Flow *f = NULL;
1170  Packet *p = NULL;
1171 
1172  uint8_t sshbuf1[] = "SSH-";
1173  uint8_t sshbuf2[] = "2.0-";
1174  uint8_t sshbuf3[] = "abcdefghijklmnopqrstuvwxyz"
1175  "abcdefghijklmnopqrstuvwxyz"//60
1176  "abcdefghijklmnopqrstuvwxyz"
1177  "abcdefghijklmnopqrstuvwxyz"//112
1178  "abcdefghijklmnopqrstuvwxyz"
1179  "abcdefghijklmnopqrstuvwxyz"//164
1180  "abcdefghijklmnopqrstuvwxyz"
1181  "abcdefghijklmnopqrstuvwxyz"//216
1182  "abcdefghijklmnopqrstuvwxyz"//242
1183  "abcdefghijkl\r";//255
1184  uint8_t sshbuf4[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00};
1185 
1186  uint8_t* sshbufs[4] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4};
1187  uint32_t sshlens[4] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3) - 1, sizeof(sshbuf4)};
1188 
1189  memset(&tv, 0x00, sizeof(tv));
1190 
1191  StreamTcpUTInit(&ra_ctx);
1194  StreamTcpUTSetupStream(&ssn.server, 1);
1195  StreamTcpUTSetupStream(&ssn.client, 1);
1196 
1197  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1198  FAIL_IF_NULL(f);
1199  f->protoctx = &ssn;
1200  f->proto = IPPROTO_TCP;
1201  f->alproto = ALPROTO_SSH;
1202 
1203  p = PacketGetFromAlloc();
1204  FAIL_IF(unlikely(p == NULL));
1205  p->proto = IPPROTO_TCP;
1206  p->flow = f;
1207 
1208  uint32_t seq = 2;
1209  for (int i=0; i<4; i++) {
1210  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
1211  seq += sshlens[i];
1212  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
1213  }
1214 
1215  void *ssh_state = f->alstate;
1216  FAIL_IF_NULL(ssh_state);
1217  void *tx = SCSshStateGetTx(ssh_state, 0);
1218  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1219 
1220  sshbuf3[sizeof(sshbuf3) - 2] = 0;
1221  FAIL_IF(SSHParserTestUtilCheck("2.0", (char *)sshbuf3, tx, STREAM_TOCLIENT));
1222 
1223  UTHFreePacket(p);
1225  StreamTcpUTDeinit(ra_ctx);
1226  UTHFreeFlow(f);
1227  PASS;
1228 }
1229 
1230 /** \test Really long banner handling: banner exactly 255,
1231  * followed by malformed record */
1232 static int SSHParserTest20(void)
1233 {
1234  TcpReassemblyThreadCtx *ra_ctx = NULL;
1235  ThreadVars tv;
1236  TcpSession ssn;
1237  Flow *f = NULL;
1238  Packet *p = NULL;
1239 
1240  uint8_t sshbuf1[] = "SSH-";
1241  uint8_t sshbuf2[] = "2.0-";
1242  uint8_t sshbuf3[] = "abcdefghijklmnopqrstuvwxyz"
1243  "abcdefghijklmnopqrstuvwxyz"//60
1244  "abcdefghijklmnopqrstuvwxyz"
1245  "abcdefghijklmnopqrstuvwxyz"//112
1246  "abcdefghijklmnopqrstuvwxyz"
1247  "abcdefghijklmnopqrstuvwxyz"//164
1248  "abcdefghijklmnopqrstuvwxyz"
1249  "abcdefghijklmnopqrstuvwxyz"//216
1250  "abcdefghijklmnopqrstuvwxyz"//242
1251  "abcdefghijklm\r";//256
1252  uint8_t sshbuf4[] = {'a','b','c','d','e','f', '\r',
1253  0x00, 0x00, 0x00, 0x06, 0x01, 21, 0x00, 0x00, 0x00};
1254 
1255  uint8_t* sshbufs[4] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4};
1256  uint32_t sshlens[4] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3) - 1, sizeof(sshbuf4) - 1};
1257 
1258  memset(&tv, 0x00, sizeof(tv));
1259 
1260  StreamTcpUTInit(&ra_ctx);
1263  StreamTcpUTSetupStream(&ssn.server, 1);
1264  StreamTcpUTSetupStream(&ssn.client, 1);
1265 
1266  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1267  FAIL_IF_NULL(f);
1268  f->protoctx = &ssn;
1269  f->proto = IPPROTO_TCP;
1270  f->alproto = ALPROTO_SSH;
1271 
1272  p = PacketGetFromAlloc();
1273  FAIL_IF(unlikely(p == NULL));
1274  p->proto = IPPROTO_TCP;
1275  p->flow = f;
1276 
1277  uint32_t seq = 2;
1278  for (int i=0; i<4; i++) {
1279  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
1280  seq += sshlens[i];
1281  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
1282  }
1283 
1284  void *ssh_state = f->alstate;
1285  FAIL_IF_NULL(ssh_state);
1286  void *tx = SCSshStateGetTx(ssh_state, 0);
1287  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1288 
1289  FAIL_IF(SSHParserTestUtilCheck("2.0", NULL, tx, STREAM_TOCLIENT));
1290 
1291  UTHFreePacket(p);
1293  StreamTcpUTDeinit(ra_ctx);
1294  UTHFreeFlow(f);
1295  PASS;
1296 }
1297 
1298 /** \test Fragmented banner handling: chunk has final part of bannel plus
1299  * a record. */
1300 static int SSHParserTest21(void)
1301 {
1302  TcpReassemblyThreadCtx *ra_ctx = NULL;
1303  ThreadVars tv;
1304  TcpSession ssn;
1305  Flow *f = NULL;
1306  Packet *p = NULL;
1307 
1308  uint8_t sshbuf1[] = "SSH-";
1309  uint8_t sshbuf2[] = "2.0-";
1310  uint8_t sshbuf3[] = "abcdefghijklmnopqrstuvwxyz"
1311  "abcdefghijklmnopqrstuvwxyz"//60
1312  "abcdefghijklmnopqrstuvwxyz"
1313  "abcdefghijklmnopqrstuvwxyz"//112
1314  "abcdefghijklmnopqrstuvwxyz"
1315  "abcdefghijklmnopqrstuvwxyz"//164
1316  "abcdefghijklmnopqrstuvwxyz"
1317  "abcdefghijklmnopqrstuvwxyz"//216
1318  "abcdefghijklmnopqrstuvwxy";//241
1319  uint8_t sshbuf4[] = {'l','i','b','s','s','h', '\r',
1320  0x00, 0x00, 0x00, 0x06, 0x01, 21, 0x00, 0x00, 0x00};
1321 
1322  uint8_t* sshbufs[4] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4};
1323  uint32_t sshlens[4] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3) - 1, sizeof(sshbuf4)};
1324 
1325  memset(&tv, 0x00, sizeof(tv));
1326 
1327  StreamTcpUTInit(&ra_ctx);
1330  StreamTcpUTSetupStream(&ssn.server, 1);
1331  StreamTcpUTSetupStream(&ssn.client, 1);
1332 
1333  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1334  FAIL_IF_NULL(f);
1335  f->protoctx = &ssn;
1336  f->proto = IPPROTO_TCP;
1337  f->alproto = ALPROTO_SSH;
1338 
1339  p = PacketGetFromAlloc();
1340  FAIL_IF(unlikely(p == NULL));
1341  p->proto = IPPROTO_TCP;
1342  p->flow = f;
1343 
1344  uint32_t seq = 2;
1345  for (int i=0; i<4; i++) {
1346  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
1347  seq += sshlens[i];
1348  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
1349  }
1350 
1351  void *ssh_state = f->alstate;
1352  FAIL_IF_NULL(ssh_state);
1353  void *tx = SCSshStateGetTx(ssh_state, 0);
1354  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1355 
1356  FAIL_IF(SSHParserTestUtilCheck("2.0", NULL, tx, STREAM_TOCLIENT));
1357 
1358  UTHFreePacket(p);
1360  StreamTcpUTDeinit(ra_ctx);
1361  UTHFreeFlow(f);
1362  PASS;
1363 }
1364 
1365 /** \test Fragmented banner handling: chunk has final part of bannel plus
1366  * a record. */
1367 static int SSHParserTest22(void)
1368 {
1369  TcpReassemblyThreadCtx *ra_ctx = NULL;
1370  ThreadVars tv;
1371  TcpSession ssn;
1372  Flow *f = NULL;
1373  Packet *p = NULL;
1374 
1375  uint8_t sshbuf1[] = "SSH-";
1376  uint8_t sshbuf2[] = "2.0-";
1377  uint8_t sshbuf3[] = {
1378  'l', 'i', 'b', 's', 's', 'h', '\r', //7
1379 
1380  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1381  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1382  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1383  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1384  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, //50
1385 
1386  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1387  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1388  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1389  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1390  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, //100
1391 
1392  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1393  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1394  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1395  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1396  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, //150
1397 
1398  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1399  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1400  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1401  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1402  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, //200
1403 
1404  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1405  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1406  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1407  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1408  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, //250
1409 
1410  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1411  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1412  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1413  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
1414  0x00, 0x00, 0x00, 0x06, 0x01, 21, 0x00, 0x00, 0x00, 0x00, //300
1415  };
1416 
1417 
1418  uint8_t* sshbufs[3] = {sshbuf1, sshbuf2, sshbuf3};
1419  uint32_t sshlens[3] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3) - 1};
1420 
1421  memset(&tv, 0x00, sizeof(tv));
1422 
1423  StreamTcpUTInit(&ra_ctx);
1426  StreamTcpUTSetupStream(&ssn.server, 1);
1427  StreamTcpUTSetupStream(&ssn.client, 1);
1428 
1429  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1430  FAIL_IF_NULL(f);
1431  f->protoctx = &ssn;
1432  f->proto = IPPROTO_TCP;
1433  f->alproto = ALPROTO_SSH;
1434 
1435  p = PacketGetFromAlloc();
1436  FAIL_IF(unlikely(p == NULL));
1437  p->proto = IPPROTO_TCP;
1438  p->flow = f;
1439 
1440  uint32_t seq = 2;
1441  for (int i=0; i<3; i++) {
1442  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
1443  seq += sshlens[i];
1444  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
1445  }
1446 
1447  void *ssh_state = f->alstate;
1448  FAIL_IF_NULL(ssh_state);
1449  void *tx = SCSshStateGetTx(ssh_state, 0);
1450  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1451 
1452  FAIL_IF(SSHParserTestUtilCheck("2.0", "libssh", tx, STREAM_TOCLIENT));
1453 
1454  UTHFreePacket(p);
1456  StreamTcpUTDeinit(ra_ctx);
1457  UTHFreeFlow(f);
1458  PASS;
1459 }
1460 
1461 /** \test Send a version string in one chunk (client version str). */
1462 static int SSHParserTest23(void)
1463 {
1464  int result = 0;
1465  Flow f;
1466  uint8_t sshbuf[] = "SSH-2.0\r-MySSHClient-0.5.1\n";
1467  uint32_t sshlen = sizeof(sshbuf) - 1;
1468  TcpSession ssn;
1470 
1471  memset(&f, 0, sizeof(f));
1472  memset(&ssn, 0, sizeof(ssn));
1473  FLOW_INITIALIZE(&f);
1474  f.protoctx = (void *)&ssn;
1475  f.alproto = ALPROTO_SSH;
1476 
1477  StreamTcpInitConfig(true);
1478 
1479  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
1480  STREAM_TOSERVER | STREAM_EOF, sshbuf, sshlen);
1481  if (r == 0) {
1482  printf("toclient chunk 1 returned 0 expected non null: ");
1483  goto end;
1484  }
1485 
1486  result = 1;
1487 end:
1488  if (alp_tctx != NULL)
1490  StreamTcpFreeConfig(true);
1491  FLOW_DESTROY(&f);
1492  return result;
1493 }
1494 
1495 /** \test Send a version string in one chunk (client version str). */
1496 static int SSHParserTest24(void)
1497 {
1498  int result = 0;
1499  Flow f;
1500  uint8_t sshbuf[] = "SSH-2.0-\rMySSHClient-0.5.1\n";
1501  uint32_t sshlen = sizeof(sshbuf) - 1;
1502  TcpSession ssn;
1504 
1505  memset(&f, 0, sizeof(f));
1506  memset(&ssn, 0, sizeof(ssn));
1507  FLOW_INITIALIZE(&f);
1508  f.protoctx = (void *)&ssn;
1509  f.alproto = ALPROTO_SSH;
1510 
1511  StreamTcpInitConfig(true);
1512 
1513  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
1514  STREAM_TOSERVER | STREAM_EOF, sshbuf, sshlen);
1515  if (r != 0) {
1516  printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
1517  goto end;
1518  }
1519 
1520  void *ssh_state = f.alstate;
1521  if (ssh_state == NULL) {
1522  printf("no ssh state: ");
1523  goto end;
1524  }
1525  void *tx = SCSshStateGetTx(ssh_state, 0);
1526  if (SCSshTxGetFlags(tx, STREAM_TOSERVER) != SshStateBannerDone) {
1527  printf("Didn't detect the msg code of new keys (ciphered data starts): ");
1528  goto end;
1529  }
1530  if (SSHParserTestUtilCheck("2.0", NULL, tx, STREAM_TOSERVER))
1531  goto end;
1532 
1533  result = 1;
1534 end:
1535  if (alp_tctx != NULL)
1537  StreamTcpFreeConfig(true);
1538  FLOW_DESTROY(&f);
1539  return result;
1540 }
1541 
1542 /** \test Send a malformed banner */
1543 static int SSHParserTest25(void)
1544 {
1545  Flow f;
1546  uint8_t sshbuf[] = "\n";
1547  uint32_t sshlen = sizeof(sshbuf) - 1;
1548  TcpSession ssn;
1551 
1552  memset(&f, 0, sizeof(f));
1553  memset(&ssn, 0, sizeof(ssn));
1554  FLOW_INITIALIZE(&f);
1555  f.protoctx = (void *)&ssn;
1556  f.alproto = ALPROTO_SSH;
1557 
1558  StreamTcpInitConfig(true);
1559 
1560  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
1561  STREAM_TOSERVER | STREAM_EOF, sshbuf, sshlen);
1562  FAIL_IF(r != -1);
1563 
1564  void *ssh_state = f.alstate;
1565  FAIL_IF_NULL(ssh_state);
1566  void *tx = SCSshStateGetTx(ssh_state, 0);
1567  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOSERVER) == SshStateBannerDone);
1568  const uint8_t *dummy = NULL;
1569  uint32_t dummy_len = 0;
1570  FAIL_IF(SCSshTxGetSoftware(tx, &dummy, &dummy_len, STREAM_TOCLIENT) != 0);
1571 
1573  StreamTcpFreeConfig(true);
1574  FLOW_DESTROY(&f);
1575  PASS;
1576 }
1577 
1578 #endif /* UNITTESTS */
1579 
1581 {
1582 #ifdef UNITTESTS
1583  UtRegisterTest("SSHParserTest01 - ToServer", SSHParserTest01);
1584  UtRegisterTest("SSHParserTest02 - ToServer", SSHParserTest02);
1585  UtRegisterTest("SSHParserTest03 - ToServer", SSHParserTest03);
1586  UtRegisterTest("SSHParserTest04 - ToClient", SSHParserTest04);
1587  UtRegisterTest("SSHParserTest05 - ToClient", SSHParserTest05);
1588  UtRegisterTest("SSHParserTest06 - ToClient", SSHParserTest06);
1589  UtRegisterTest("SSHParserTest07 - ToServer 2 chunks", SSHParserTest07);
1590  UtRegisterTest("SSHParserTest08 - ToServer 3 chunks", SSHParserTest08);
1591  UtRegisterTest("SSHParserTest09 - ToClient 2 chunks", SSHParserTest09);
1592  UtRegisterTest("SSHParserTest10 - ToClient 3 chunks", SSHParserTest10);
1593  UtRegisterTest("SSHParserTest11 - ToClient 4 chunks", SSHParserTest11);
1594  UtRegisterTest("SSHParserTest12 - ToClient 4 chunks", SSHParserTest12);
1595  UtRegisterTest("SSHParserTest13 - ToClient 4 chunks", SSHParserTest13);
1596  UtRegisterTest("SSHParserTest14 - ToClient 4 chunks", SSHParserTest14);
1597  UtRegisterTest("SSHParserTest15", SSHParserTest15);
1598  UtRegisterTest("SSHParserTest16", SSHParserTest16);
1599  UtRegisterTest("SSHParserTest17", SSHParserTest17);
1600  UtRegisterTest("SSHParserTest18", SSHParserTest18);
1601  UtRegisterTest("SSHParserTest19", SSHParserTest19);
1602  UtRegisterTest("SSHParserTest20", SSHParserTest20);
1603  UtRegisterTest("SSHParserTest21", SSHParserTest21);
1604  UtRegisterTest("SSHParserTest22", SSHParserTest22);
1605  UtRegisterTest("SSHParserTest23", SSHParserTest23);
1606  UtRegisterTest("SSHParserTest24", SSHParserTest24);
1607  UtRegisterTest("SSHParserTest25", SSHParserTest25);
1608 #endif /* UNITTESTS */
1609 }
1610 
UPDATE_DIR_PACKET
@ UPDATE_DIR_PACKET
Definition: stream-tcp-reassemble.h:56
util-byte.h
Packet_::proto
uint8_t proto
Definition: decode.h:523
SCAppLayerParserStateIssetFlag
uint16_t SCAppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint16_t flag)
Definition: app-layer-parser.c:1829
SCConfValIsTrue
int SCConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:551
StreamTcpUTDeinit
void StreamTcpUTDeinit(TcpReassemblyThreadCtx *ra_ctx)
Definition: stream-tcp-util.c:51
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
app-layer-ssh.h
flow-util.h
stream-tcp.h
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
RegisterSSHParsers
void RegisterSSHParsers(void)
Function to register the SSH protocol parsers and other functions.
Definition: app-layer-ssh.c:81
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:275
seq
uint32_t seq
Definition: stream-tcp-private.h:2
Flow_::proto
uint8_t proto
Definition: flow.h:378
SCAppLayerProtoDetectPMRegisterPatternCI
int SCAppLayerProtoDetectPMRegisterPatternCI(uint8_t ipproto, AppProto alproto, const char *pattern, uint16_t depth, uint16_t offset, uint8_t direction)
Registers a case-insensitive pattern for protocol detection.
Definition: app-layer-detect-proto.c:1649
threads.h
flow-private.h
Flow_
Flow data structure.
Definition: flow.h:356
SCConfGet
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:350
StreamTcpReassembleAppLayer
int StreamTcpReassembleAppLayer(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, TcpSession *ssn, TcpStream *stream, Packet *p, enum StreamUpdateDir app_update_dir)
Update the stream reassembly upon receiving a packet.
Definition: stream-tcp-reassemble.c:1398
SSHTxLogCondition
bool SSHTxLogCondition(ThreadVars *tv, const Packet *p, void *state, void *tx, uint64_t tx_id)
Definition: app-layer-ssh.c:74
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:324
rust.h
SCConfValIsFalse
int SCConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:576
stream-tcp-reassemble.h
ALPROTO_SSH
@ ALPROTO_SSH
Definition: app-layer-protos.h:40
Flow_::protoctx
void * protoctx
Definition: flow.h:441
StreamTcpUTInitInline
void StreamTcpUTInitInline(void)
Definition: stream-tcp-util.c:58
util-unittest.h
util-unittest-helper.h
util-memcmp.h
SCAppLayerProtoDetectConfProtoDetectionEnabled
int SCAppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
Definition: app-layer-detect-proto.c:1942
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:478
StreamTcpUTInit
void StreamTcpUTInit(TcpReassemblyThreadCtx **ra_ctx)
Definition: stream-tcp-util.c:44
app-layer-detect-proto.h
StreamTcpInitConfig
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition: stream-tcp.c:488
UTHBuildFlow
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
Definition: util-unittest-helper.c:488
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
protocol
uint16_t protocol
Definition: decode-ppp.h:2
decode.h
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:23
util-print.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
StreamTcpUTSetupStream
void StreamTcpUTSetupStream(TcpStream *s, uint32_t isn)
Definition: stream-tcp-util.c:79
app-layer-parser.h
stream.h
AppLayerParserRegisterProtocolUnittests
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
Definition: app-layer-parser.c:1840
Packet_
Definition: decode.h:501
stream-tcp-private.h
conf.h
AppLayerProtoDetectRegisterProtocol
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
Definition: app-layer-detect-proto.c:1742
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:270
APP_LAYER_PARSER_NO_INSPECTION
#define APP_LAYER_PARSER_NO_INSPECTION
Definition: app-layer-parser.h:49
UTHFreeFlow
void UTHFreeFlow(Flow *flow)
Definition: util-unittest-helper.c:493
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:297
StreamTcpUTClearSession
void StreamTcpUTClearSession(TcpSession *ssn)
Definition: stream-tcp-util.c:71
Packet_::flow
struct Flow_ * flow
Definition: decode.h:546
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
SSH_CONFIG_DEFAULT_ENCRYPTION_BYPASS
#define SSH_CONFIG_DEFAULT_ENCRYPTION_BYPASS
Definition: app-layer-ssh.c:59
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:859
flags
uint8_t flags
Definition: decode-gre.h:0
AppLayerParserParse
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
Definition: app-layer-parser.c:1291
suricata-common.h
util-spm.h
TcpSession_::client
TcpStream client
Definition: stream-tcp-private.h:297
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
StreamTcpUTAddSegmentWithPayload
int StreamTcpUTAddSegmentWithPayload(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, TcpStream *stream, uint32_t seq, uint8_t *payload, uint16_t len)
Definition: stream-tcp-util.c:113
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:258
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
StreamTcpUTSetupSession
void StreamTcpUTSetupSession(TcpSession *ssn)
Definition: stream-tcp-util.c:62
TcpSession_::server
TcpStream server
Definition: stream-tcp-private.h:296
SCConfGetNode
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition: conf.c:181
UTHFreePacket
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:473
Flow_::alstate
void * alstate
Definition: flow.h:479
MAX_SSH_TEST_SIZE
#define MAX_SSH_TEST_SIZE
Definition: app-layer-ssh.c:488
stream-tcp-util.h
TcpReassemblyThreadCtx_
Definition: stream-tcp-reassemble.h:61
app-layer-protos.h
SSHParserRegisterTests
void SSHParserRegisterTests(void)
Definition: app-layer-ssh.c:1580
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:60
TcpSession_
Definition: stream-tcp-private.h:283
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:450
util-pool.h
SCConfNode_
Definition: conf.h:37
SCConfNode_::val
char * val
Definition: conf.h:39
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:119
SSH_CONFIG_DEFAULT_HASSH
#define SSH_CONFIG_DEFAULT_HASSH
Definition: app-layer-ssh.c:57