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