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  Flow f;
186  uint8_t sshbuf[] = "SSH-2.0-MySSHClient-0.5.1\n";
187  uint32_t sshlen = sizeof(sshbuf) - 1;
188  TcpSession ssn;
190 
191  memset(&f, 0, sizeof(f));
192  memset(&ssn, 0, sizeof(ssn));
193  FLOW_INITIALIZE(&f);
194  f.protoctx = (void *)&ssn;
195  f.proto = IPPROTO_TCP;
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  FAIL_IF_NOT(r == 0);
203 
204  void *ssh_state = f.alstate;
205  FAIL_IF_NULL(ssh_state);
206 
207  void *tx = SCSshStateGetTx(ssh_state, 0);
208  FAIL_IF_NULL(tx);
209  FAIL_IF(SCSshTxGetAlStateProgress(tx, STREAM_TOSERVER) != SshStateBannerDone);
210  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
211 
212  FLOW_DESTROY(&f);
214  StreamTcpFreeConfig(true);
215  PASS;
216 }
217 
218 /** \test Send a version string in one chunk but multiple lines and comments.
219  * (client version str)
220  */
221 static int SSHParserTest02(void)
222 {
223  int result = 0;
224  Flow f;
225  uint8_t sshbuf[] = "SSH-2.0-MySSHClient-0.5.1 some comments...\n";
226  uint32_t sshlen = sizeof(sshbuf) - 1;
227  TcpSession ssn;
229 
230  memset(&f, 0, sizeof(f));
231  memset(&ssn, 0, sizeof(ssn));
232  FLOW_INITIALIZE(&f);
233  f.protoctx = (void *)&ssn;
234  f.proto = IPPROTO_TCP;
235  f.alproto = ALPROTO_SSH;
236 
237  StreamTcpInitConfig(true);
238 
239  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
240  STREAM_TOSERVER | STREAM_EOF, sshbuf, sshlen);
241  if (r != 0) {
242  printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
243  goto end;
244  }
245 
246  void *ssh_state = f.alstate;
247  if (ssh_state == NULL) {
248  printf("no ssh state: ");
249  goto end;
250  }
251  void *tx = SCSshStateGetTx(ssh_state, 0);
252 
253  if (SCSshTxGetAlStateProgress(tx, STREAM_TOSERVER) != SshStateBannerDone) {
254  printf("Client version string not parsed: ");
255  goto end;
256  }
257  if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER))
258  goto end;
259 
260  result = 1;
261 end:
262  FLOW_DESTROY(&f);
263  if (alp_tctx != NULL)
265  StreamTcpFreeConfig(true);
266  return result;
267 }
268 
269 /** \test Send a invalid version string in one chunk but multiple lines and comments.
270  * (client version str)
271  */
272 static int SSHParserTest03(void)
273 {
274  int result = 0;
275  Flow f;
276  uint8_t sshbuf[] = "SSH-2.0 some comments...\n";
277  uint32_t sshlen = sizeof(sshbuf) - 1;
278  TcpSession ssn;
280 
281  memset(&f, 0, sizeof(f));
282  memset(&ssn, 0, sizeof(ssn));
283  FLOW_INITIALIZE(&f);
284  f.protoctx = (void *)&ssn;
285  f.proto = IPPROTO_TCP;
286  f.alproto = ALPROTO_SSH;
287 
288  StreamTcpInitConfig(true);
289 
290  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
291  STREAM_TOSERVER | STREAM_EOF, sshbuf, sshlen);
292  if (r == 0) {
293  printf("toclient chunk 1 returned %" PRId32 ", expected != 0: ", r);
294  goto end;
295  }
296 
297  void *ssh_state = f.alstate;
298  if (ssh_state == NULL) {
299  printf("no ssh state: ");
300  goto end;
301  }
302  void *tx = SCSshStateGetTx(ssh_state, 0);
303 
304  if (SCSshTxGetAlStateProgress(tx, STREAM_TOSERVER) == SshStateBannerDone) {
305  printf("Client version string parsed? It's not a valid string: ");
306  goto end;
307  }
308  const uint8_t *dummy = NULL;
309  uint32_t dummy_len = 0;
310  if (SCSshTxGetProtocol(tx, &dummy, &dummy_len, STREAM_TOSERVER) != 0)
311  goto end;
312  if (SCSshTxGetSoftware(tx, &dummy, &dummy_len, STREAM_TOSERVER) != 0)
313  goto end;
314 
315  result = 1;
316 end:
317  FLOW_DESTROY(&f);
318  if (alp_tctx != NULL)
320  StreamTcpFreeConfig(true);
321  return result;
322 }
323 
324 /** \test Send a version string in one chunk (server version str). */
325 static int SSHParserTest04(void)
326 {
327  int result = 0;
328  Flow f;
329  uint8_t sshbuf[] = "SSH-2.0-MySSHClient-0.5.1\n";
330  uint32_t sshlen = sizeof(sshbuf) - 1;
331  TcpSession ssn;
333 
334  memset(&f, 0, sizeof(f));
335  memset(&ssn, 0, sizeof(ssn));
336  FLOW_INITIALIZE(&f);
337  f.protoctx = (void *)&ssn;
338  f.proto = IPPROTO_TCP;
339  f.alproto = ALPROTO_SSH;
340 
341  StreamTcpInitConfig(true);
342 
343  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
344  STREAM_TOCLIENT | STREAM_EOF, sshbuf, sshlen);
345  if (r != 0) {
346  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
347  goto end;
348  }
349 
350  void *ssh_state = f.alstate;
351  if (ssh_state == NULL) {
352  printf("no ssh state: ");
353  goto end;
354  }
355  void *tx = SCSshStateGetTx(ssh_state, 0);
356 
357  if (SCSshTxGetAlStateProgress(tx, STREAM_TOCLIENT) != SshStateBannerDone) {
358  printf("Client version string not parsed: ");
359  goto end;
360  }
361  if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT))
362  goto end;
363 
364  result = 1;
365 
366 end:
367  FLOW_DESTROY(&f);
368  if (alp_tctx != NULL)
370  StreamTcpFreeConfig(true);
371  return result;
372 }
373 
374 /** \test Send a version string in one chunk (server version str)
375  */
376 static int SSHParserTest05(void)
377 {
378  int result = 0;
379  Flow f;
380  uint8_t sshbuf[] = "SSH-2.0-MySSHClient-0.5.1 some comments...\n";
381  uint32_t sshlen = sizeof(sshbuf) - 1;
382  TcpSession ssn;
384 
385  memset(&f, 0, sizeof(f));
386  memset(&ssn, 0, sizeof(ssn));
387  FLOW_INITIALIZE(&f);
388  f.protoctx = (void *)&ssn;
389  f.proto = IPPROTO_TCP;
390  f.alproto = ALPROTO_SSH;
391 
392  StreamTcpInitConfig(true);
393 
394  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
395  STREAM_TOCLIENT | STREAM_EOF, sshbuf, sshlen);
396  if (r != 0) {
397  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
398  goto end;
399  }
400 
401  void *ssh_state = f.alstate;
402  if (ssh_state == NULL) {
403  printf("no ssh state: ");
404  goto end;
405  }
406  void *tx = SCSshStateGetTx(ssh_state, 0);
407 
408  if (SCSshTxGetAlStateProgress(tx, STREAM_TOCLIENT) != SshStateBannerDone) {
409  printf("Client version string not parsed: ");
410  goto end;
411  }
412  if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT))
413  goto end;
414 
415  result = 1;
416 end:
417  FLOW_DESTROY(&f);
418  if (alp_tctx != NULL)
420  StreamTcpFreeConfig(true);
421  return result;
422 }
423 
424 /** \test Send a invalid version string in one chunk (server version str)
425  */
426 static int SSHParserTest06(void)
427 {
428  int result = 0;
429  Flow f;
430  uint8_t sshbuf[] = "SSH-2.0 some comments...\n";
431  uint32_t sshlen = sizeof(sshbuf) - 1;
432  TcpSession ssn;
434 
435  memset(&f, 0, sizeof(f));
436  memset(&ssn, 0, sizeof(ssn));
437  FLOW_INITIALIZE(&f);
438  f.protoctx = (void *)&ssn;
439  f.proto = IPPROTO_TCP;
440  f.alproto = ALPROTO_SSH;
441 
442  StreamTcpInitConfig(true);
443 
444  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
445  STREAM_TOCLIENT | STREAM_EOF, sshbuf, sshlen);
446  if (r == 0) {
447  printf("toserver chunk 1 returned %" PRId32 ", expected != 0: ", r);
448  goto end;
449  }
450  /* Ok, it returned an error. Let's make sure we didn't parse the string at all */
451 
452  void *ssh_state = f.alstate;
453  if (ssh_state == NULL) {
454  printf("no ssh state: ");
455  goto end;
456  }
457  void *tx = SCSshStateGetTx(ssh_state, 0);
458 
459  if (SCSshTxGetAlStateProgress(tx, STREAM_TOCLIENT) == SshStateBannerDone) {
460  printf("Client version string parsed? It's not a valid string: ");
461  goto end;
462  }
463  const uint8_t *dummy = NULL;
464  uint32_t dummy_len = 0;
465  if (SCSshTxGetProtocol(tx, &dummy, &dummy_len, STREAM_TOCLIENT) != 0)
466  goto end;
467  if (SCSshTxGetSoftware(tx, &dummy, &dummy_len, STREAM_TOCLIENT) != 0)
468  goto end;
469 
470  result = 1;
471 end:
472  FLOW_DESTROY(&f);
473  if (alp_tctx != NULL)
475  StreamTcpFreeConfig(true);
476  return result;
477 }
478 
479 #define MAX_SSH_TEST_SIZE 512
480 
481 static int SSHParserTest07(void)
482 {
483  TcpReassemblyThreadCtx *ra_ctx = NULL;
484  ThreadVars tv;
485  TcpSession ssn;
486  Flow *f = NULL;
487  Packet *p = NULL;
488 
489  char sshbufs[2][MAX_SSH_TEST_SIZE] = {"SSH-2.", "0-MySSHClient-0.5.1\r\n"};
490 
491  memset(&tv, 0x00, sizeof(tv));
492 
493  StreamTcpUTInit(&ra_ctx);
498 
499  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
500  FAIL_IF_NULL(f);
501  f->protoctx = &ssn;
502  f->proto = IPPROTO_TCP;
503  f->alproto = ALPROTO_SSH;
504 
505  p = PacketGetFromAlloc();
506  FAIL_IF(unlikely(p == NULL));
507  p->proto = IPPROTO_TCP;
508  p->flow = f;
509 
510  uint32_t seq = 2;
511  for (int i=0; i<2; i++) {
512  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, (uint8_t *) sshbufs[i], strlen(sshbufs[i])) == -1);
513  seq += strlen(sshbufs[i]);
514  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
515  }
516 
517  void *ssh_state = f->alstate;
518  FAIL_IF_NULL(ssh_state);
519  void *tx = SCSshStateGetTx(ssh_state, 0);
520  FAIL_IF(SCSshTxGetAlStateProgress(tx, STREAM_TOSERVER) != SshStateBannerDone);
521 
522  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
523 
524  UTHFreePacket(p);
525  UTHFreeFlow(f);
527  StreamTcpUTDeinit(ra_ctx);
528  PASS;
529 }
530 
531 /** \test Send a version banner in three chunks. */
532 static int SSHParserTest08(void)
533 {
534  TcpReassemblyThreadCtx *ra_ctx = NULL;
535  ThreadVars tv;
536  TcpSession ssn;
537  Flow *f = NULL;
538  Packet *p = NULL;
539 
540  char sshbufs[3][MAX_SSH_TEST_SIZE] = {"SSH-", "2.", "0-MySSHClient-0.5.1\r\n"};
541 
542  memset(&tv, 0x00, sizeof(tv));
543 
544  StreamTcpUTInit(&ra_ctx);
549 
550  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
551  FAIL_IF_NULL(f);
552  f->protoctx = &ssn;
553  f->proto = IPPROTO_TCP;
554  f->alproto = ALPROTO_SSH;
555 
556  p = PacketGetFromAlloc();
557  FAIL_IF(unlikely(p == NULL));
558  p->proto = IPPROTO_TCP;
559  p->flow = f;
560 
561  uint32_t seq = 2;
562  for (int i=0; i<3; i++) {
563  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, (uint8_t *) sshbufs[i], strlen(sshbufs[i])) == -1);
564  seq += strlen(sshbufs[i]);
565  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
566  }
567 
568  void *ssh_state = f->alstate;
569  FAIL_IF_NULL(ssh_state);
570  void *tx = SCSshStateGetTx(ssh_state, 0);
571  FAIL_IF(SCSshTxGetAlStateProgress(tx, STREAM_TOSERVER) != SshStateBannerDone);
572 
573  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
574 
575  UTHFreePacket(p);
576  UTHFreeFlow(f);
578  StreamTcpUTDeinit(ra_ctx);
579  PASS;
580 }
581 
582 static int SSHParserTest09(void)
583 {
584  TcpReassemblyThreadCtx *ra_ctx = NULL;
585  ThreadVars tv;
586  TcpSession ssn;
587  Flow *f = NULL;
588  Packet *p = NULL;
589 
590  char sshbufs[2][MAX_SSH_TEST_SIZE] = {"SSH-2.", "0-MySSHClient-0.5.1\r\n"};
591 
592  memset(&tv, 0x00, sizeof(tv));
593 
594  StreamTcpUTInit(&ra_ctx);
599 
600  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
601  FAIL_IF_NULL(f);
602  f->protoctx = &ssn;
603  f->proto = IPPROTO_TCP;
604  f->alproto = ALPROTO_SSH;
605 
606  p = PacketGetFromAlloc();
607  FAIL_IF(unlikely(p == NULL));
608  p->proto = IPPROTO_TCP;
609  p->flow = f;
610 
611  uint32_t seq = 2;
612  for (int i=0; i<2; i++) {
613  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, (uint8_t *) sshbufs[i], strlen(sshbufs[i])) == -1);
614  seq += strlen(sshbufs[i]);
615  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
616  }
617 
618  void *ssh_state = f->alstate;
619  FAIL_IF_NULL(ssh_state);
620  void *tx = SCSshStateGetTx(ssh_state, 0);
621  FAIL_IF(SCSshTxGetAlStateProgress(tx, STREAM_TOCLIENT) != SshStateBannerDone);
622 
623  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT));
624 
625  UTHFreePacket(p);
626  UTHFreeFlow(f);
628  StreamTcpUTDeinit(ra_ctx);
629  PASS;
630 }
631 
632 /** \test Send a version banner in three chunks. */
633 static int SSHParserTest10(void)
634 {
635  TcpReassemblyThreadCtx *ra_ctx = NULL;
636  ThreadVars tv;
637  TcpSession ssn;
638  Flow *f = NULL;
639  Packet *p = NULL;
640 
641  char sshbufs[3][MAX_SSH_TEST_SIZE] = {"SSH-", "2.", "0-MySSHClient-0.5.1\r\n"};
642 
643  memset(&tv, 0x00, sizeof(tv));
644 
645  StreamTcpUTInit(&ra_ctx);
650 
651  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
652  FAIL_IF_NULL(f);
653  f->protoctx = &ssn;
654  f->proto = IPPROTO_TCP;
655  f->alproto = ALPROTO_SSH;
656 
657  p = PacketGetFromAlloc();
658  FAIL_IF(unlikely(p == NULL));
659  p->proto = IPPROTO_TCP;
660  p->flow = f;
661 
662  uint32_t seq = 2;
663  for (int i=0; i<3; i++) {
664  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, (uint8_t *) sshbufs[i], strlen(sshbufs[i])) == -1);
665  seq += strlen(sshbufs[i]);
666  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
667  }
668 
669  void *ssh_state = f->alstate;
670  FAIL_IF_NULL(ssh_state);
671  void *tx = SCSshStateGetTx(ssh_state, 0);
672  FAIL_IF(SCSshTxGetAlStateProgress(tx, STREAM_TOCLIENT) != SshStateBannerDone);
673 
674  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT));
675 
676  UTHFreePacket(p);
677  UTHFreeFlow(f);
679  StreamTcpUTDeinit(ra_ctx);
680  PASS;
681 }
682 
683 /** \test Send a banner and record in three chunks. */
684 static int SSHParserTest11(void)
685 {
686  int result = 0;
687  Flow f;
688  uint8_t sshbuf1[] = "SSH-2.0-MySSHClient-0.5.1\r\n";
689  uint32_t sshlen1 = sizeof(sshbuf1) - 1;
690  uint8_t sshbuf2[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00};
691  uint32_t sshlen2 = sizeof(sshbuf2);
692  TcpSession ssn;
694 
695  memset(&f, 0, sizeof(f));
696  memset(&ssn, 0, sizeof(ssn));
697  FLOW_INITIALIZE(&f);
698  f.protoctx = (void *)&ssn;
699  f.proto = IPPROTO_TCP;
700  f.alproto = ALPROTO_SSH;
701 
702  StreamTcpInitConfig(true);
703 
704  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
705  STREAM_TOSERVER, sshbuf1, sshlen1);
706  if (r != 0) {
707  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
708  goto end;
709  }
710  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
711  sshbuf2, sshlen2);
712  if (r != 0) {
713  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
714  goto end;
715  }
716 
717  void *ssh_state = f.alstate;
718  if (ssh_state == NULL) {
719  printf("no ssh state: ");
720  goto end;
721  }
722  void *tx = SCSshStateGetTx(ssh_state, 0);
723  if (SCSshTxGetFlags(tx, STREAM_TOSERVER) != SshStateFinished) {
724  printf("Didn't detect the msg code of new keys (ciphered data starts): ");
725  goto end;
726  }
727  if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER))
728  goto end;
729 
730  result = 1;
731 end:
732  FLOW_DESTROY(&f);
733  if (alp_tctx != NULL)
735  StreamTcpFreeConfig(true);
736  return result;
737 }
738 
739 /** \test Send a banner and 2 records record in four chunks. */
740 static int SSHParserTest12(void)
741 {
742  int result = 0;
743  Flow f;
744  uint8_t sshbuf1[] = "SSH-2.0-MySSHClient-0.5.1\r\n";
745  uint32_t sshlen1 = sizeof(sshbuf1) - 1;
746  uint8_t sshbuf2[] = { 0x00, 0x00, 0x00, 0x03,0x01, 17, 0x00};
747  uint32_t sshlen2 = sizeof(sshbuf2);
748  uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x03,0x01, 21, 0x00};
749  uint32_t sshlen3 = sizeof(sshbuf3);
750  TcpSession ssn;
752 
753  memset(&f, 0, sizeof(f));
754  memset(&ssn, 0, sizeof(ssn));
755  FLOW_INITIALIZE(&f);
756  f.protoctx = (void *)&ssn;
757  f.proto = IPPROTO_TCP;
758  f.alproto = ALPROTO_SSH;
759 
760  StreamTcpInitConfig(true);
761 
762  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
763  STREAM_TOSERVER, sshbuf1, sshlen1);
764  if (r != 0) {
765  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
766  goto end;
767  }
768  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
769  sshbuf2, sshlen2);
770  if (r != 0) {
771  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
772  goto end;
773  }
774  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
775  sshbuf3, sshlen3);
776  if (r != 0) {
777  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
778  goto end;
779  }
780 
781  void *ssh_state = f.alstate;
782  if (ssh_state == NULL) {
783  printf("no ssh state: ");
784  goto end;
785  }
786  void *tx = SCSshStateGetTx(ssh_state, 0);
787  if (SCSshTxGetFlags(tx, STREAM_TOSERVER) != SshStateFinished) {
788  printf("Didn't detect the msg code of new keys (ciphered data starts): ");
789  goto end;
790  }
791  if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER))
792  goto end;
793 
794  result = 1;
795 end:
796  FLOW_DESTROY(&f);
797  if (alp_tctx != NULL)
799  StreamTcpFreeConfig(true);
800  return result;
801 }
802 
803 /** \test Send a banner and 2 records record in four chunks. */
804 static int SSHParserTest13(void)
805 {
806  TcpReassemblyThreadCtx *ra_ctx = NULL;
807  ThreadVars tv;
808  TcpSession ssn;
809  Flow *f = NULL;
810  Packet *p = NULL;
811 
812  uint8_t sshbuf1[] = "SSH-2.0-MySSHClient-0.5.1\r\n";
813  uint8_t sshbuf2[] = { 0x00, 0x00, 0x00, 0x02, 0x01, 17};
814  uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x02, 0x01, 21};
815 
816  uint8_t* sshbufs[3] = {sshbuf1, sshbuf2, sshbuf3};
817  uint32_t sshlens[3] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2), sizeof(sshbuf3)};
818 
819  memset(&tv, 0x00, sizeof(tv));
820 
821  StreamTcpUTInit(&ra_ctx);
826 
827  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
828  FAIL_IF_NULL(f);
829  f->protoctx = &ssn;
830  f->proto = IPPROTO_TCP;
831  f->alproto = ALPROTO_SSH;
832 
833  p = PacketGetFromAlloc();
834  FAIL_IF(unlikely(p == NULL));
835  p->proto = IPPROTO_TCP;
836  p->flow = f;
837 
838  uint32_t seq = 2;
839  for (int i=0; i<3; i++) {
840  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, sshbufs[i], sshlens[i]) == -1);
841  seq += sshlens[i];
842  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
843  }
844 
845  void *ssh_state = f->alstate;
846  FAIL_IF_NULL(ssh_state);
847  void *tx = SCSshStateGetTx(ssh_state, 0);
848  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOSERVER) != SshStateFinished);
849 
850  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
851 
852  UTHFreePacket(p);
853  UTHFreeFlow(f);
855  StreamTcpUTDeinit(ra_ctx);
856  PASS;
857 }
858 
859 /** \test Send a banner and 2 records record in four chunks. */
860 static int SSHParserTest14(void)
861 {
862  TcpReassemblyThreadCtx *ra_ctx = NULL;
863  ThreadVars tv;
864  TcpSession ssn;
865  Flow *f = NULL;
866  Packet *p = NULL;
867 
868  uint8_t sshbuf1[] = "SSH-2.0-MySSHClient-0.5.1\r\n";
869  uint8_t sshbuf2[] = { 0x00, 0x00, 0x00, 0x10, 0x01, 17, 0x00};
870  uint8_t sshbuf3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
871  uint8_t sshbuf4[] = { 0x09, 0x10, 0x11, 0x12, 0x13, 0x00};
872  /* first byte of this record in sshbuf4 */
873  uint8_t sshbuf5[] = { 0x00, 0x00, 0x02, 0x01, 21};
874 
875  uint8_t* sshbufs[5] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4, sshbuf5};
876  uint32_t sshlens[5] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2), sizeof(sshbuf3), sizeof(sshbuf4), sizeof(sshbuf5)};
877 
878  memset(&tv, 0x00, sizeof(tv));
879 
880  StreamTcpUTInit(&ra_ctx);
885 
886  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
887  FAIL_IF_NULL(f);
888  f->protoctx = &ssn;
889  f->proto = IPPROTO_TCP;
890  f->alproto = ALPROTO_SSH;
891 
892  p = PacketGetFromAlloc();
893  FAIL_IF(unlikely(p == NULL));
894  p->proto = IPPROTO_TCP;
895  p->flow = f;
896 
897  uint32_t seq = 2;
898  for (int i=0; i<5; i++) {
899  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, sshbufs[i], sshlens[i]) == -1);
900  seq += sshlens[i];
901  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
902  }
903 
904  void *ssh_state = f->alstate;
905  FAIL_IF_NULL(ssh_state);
906  void *tx = SCSshStateGetTx(ssh_state, 0);
907  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOSERVER) != SshStateFinished);
908 
909  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
910 
911  UTHFreePacket(p);
912  UTHFreeFlow(f);
914  StreamTcpUTDeinit(ra_ctx);
915  PASS;
916 }
917 
918 /** \test Send a banner and 2 records record in four chunks. */
919 static int SSHParserTest15(void)
920 {
921  TcpReassemblyThreadCtx *ra_ctx = NULL;
922  ThreadVars tv;
923  TcpSession ssn;
924  Flow *f = NULL;
925  Packet *p = NULL;
926 
927  uint8_t sshbuf1[] = "SSH-2.0-MySSHClient-0.5.1\r\n";
928  uint8_t sshbuf2[] = { 0x00, 0x00, 0x00, 0x10, 0x01, 17, 0x00};
929  uint8_t sshbuf3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
930  uint8_t sshbuf4[] = { 0x09, 0x10, 0x11, 0x12, 0x13, 0x00};
931  uint8_t sshbuf5[] = { 0x00, 0x00, 0x02, 0x01, 20, 0x00, 0x00, 0x00, 0x02, 0x01, 21};
932 
933  uint8_t* sshbufs[5] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4, sshbuf5};
934  uint32_t sshlens[5] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2), sizeof(sshbuf3), sizeof(sshbuf4), sizeof(sshbuf5)};
935 
936  memset(&tv, 0x00, sizeof(tv));
937 
938  StreamTcpUTInit(&ra_ctx);
943 
944  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
945  FAIL_IF_NULL(f);
946  f->protoctx = &ssn;
947  f->proto = IPPROTO_TCP;
948  f->alproto = ALPROTO_SSH;
949 
950  p = PacketGetFromAlloc();
951  FAIL_IF(unlikely(p == NULL));
952  p->proto = IPPROTO_TCP;
953  p->flow = f;
954 
955  uint32_t seq = 2;
956  for (int i=0; i<5; i++) {
957  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, sshbufs[i], sshlens[i]) == -1);
958  seq += sshlens[i];
959  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
960  }
961 
962  void *ssh_state = f->alstate;
963  FAIL_IF_NULL(ssh_state);
964  void *tx = SCSshStateGetTx(ssh_state, 0);
965  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOSERVER) != SshStateFinished);
966 
967  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
968 
969  UTHFreePacket(p);
970  UTHFreeFlow(f);
972  StreamTcpUTDeinit(ra_ctx);
973  PASS;
974 }
975 
976 /** \test Send toserver a banner and record in three chunks. */
977 static int SSHParserTest16(void)
978 {
979  TcpReassemblyThreadCtx *ra_ctx = NULL;
980  ThreadVars tv;
981  TcpSession ssn;
982  Flow *f = NULL;
983  Packet *p = NULL;
984 
985  uint8_t sshbuf1[] = "SSH-";
986  uint8_t sshbuf2[] = "2.0-MySSHClient-0.5.1\r\n";
987  uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x03,0x01, 21, 0x00};
988 
989  uint8_t* sshbufs[3] = {sshbuf1, sshbuf2, sshbuf3};
990  uint32_t sshlens[3] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3)};
991 
992  memset(&tv, 0x00, sizeof(tv));
993 
994  StreamTcpUTInit(&ra_ctx);
999 
1000  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1001  FAIL_IF_NULL(f);
1002  f->protoctx = &ssn;
1003  f->proto = IPPROTO_TCP;
1004  f->alproto = ALPROTO_SSH;
1005 
1006  p = PacketGetFromAlloc();
1007  FAIL_IF(unlikely(p == NULL));
1008  p->proto = IPPROTO_TCP;
1009  p->flow = f;
1010 
1011  uint32_t seq = 2;
1012  for (int i=0; i<3; i++) {
1013  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
1014  seq += sshlens[i];
1015  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
1016  }
1017 
1018  void *ssh_state = f->alstate;
1019  FAIL_IF_NULL(ssh_state);
1020  void *tx = SCSshStateGetTx(ssh_state, 0);
1021  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1022 
1023  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT));
1024 
1025  UTHFreePacket(p);
1026  UTHFreeFlow(f);
1028  StreamTcpUTDeinit(ra_ctx);
1029  PASS;
1030 }
1031 
1032 /** \test Send toserver a banner and 2 records record in four chunks. */
1033 static int SSHParserTest17(void)
1034 {
1035  TcpReassemblyThreadCtx *ra_ctx = NULL;
1036  ThreadVars tv;
1037  TcpSession ssn;
1038  Flow *f = NULL;
1039  Packet *p = NULL;
1040 
1041  uint8_t sshbuf1[] = "SSH-";
1042  uint8_t sshbuf2[] = "2.0-MySSHClient-0.5.1\r\n";
1043  uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 17, 0x00};
1044  uint8_t sshbuf4[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00};
1045 
1046  uint8_t* sshbufs[4] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4};
1047  uint32_t sshlens[4] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3), sizeof(sshbuf4)};
1048 
1049  memset(&tv, 0x00, sizeof(tv));
1050 
1051  StreamTcpUTInit(&ra_ctx);
1054  StreamTcpUTSetupStream(&ssn.server, 1);
1055  StreamTcpUTSetupStream(&ssn.client, 1);
1056 
1057  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1058  FAIL_IF_NULL(f);
1059  f->protoctx = &ssn;
1060  f->proto = IPPROTO_TCP;
1061  f->alproto = ALPROTO_SSH;
1062 
1063  p = PacketGetFromAlloc();
1064  FAIL_IF(unlikely(p == NULL));
1065  p->proto = IPPROTO_TCP;
1066  p->flow = f;
1067 
1068  uint32_t seq = 2;
1069  for (int i=0; i<4; i++) {
1070  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
1071  seq += sshlens[i];
1072  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
1073  }
1074 
1075  void *ssh_state = f->alstate;
1076  FAIL_IF_NULL(ssh_state);
1077  void *tx = SCSshStateGetTx(ssh_state, 0);
1078  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1079 
1080  FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT));
1081 
1082  UTHFreePacket(p);
1083  UTHFreeFlow(f);
1085  StreamTcpUTDeinit(ra_ctx);
1086  PASS;
1087 }
1088 
1089 /** \test 2 directional test */
1090 static int SSHParserTest18(void)
1091 {
1092  TcpReassemblyThreadCtx *ra_ctx = NULL;
1093  ThreadVars tv;
1094  TcpSession ssn;
1095  Flow *f = NULL;
1096  Packet *p = NULL;
1097 
1098  uint8_t server1[] = "SSH-2.0-OpenSSH_4.7p1 Debian-8ubuntu3\r\n";
1099  uint8_t sshbuf1[] = "SSH-";
1100  uint8_t sshbuf2[] = "2.0-MySSHClient-0.5.1\r\n";
1101  uint8_t server2[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00 };
1102  uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00 };
1103 
1104 
1105  memset(&tv, 0x00, sizeof(tv));
1106 
1107  StreamTcpUTInit(&ra_ctx);
1110  StreamTcpUTSetupStream(&ssn.server, 1);
1111  StreamTcpUTSetupStream(&ssn.client, 1);
1112 
1113  uint8_t* sshbufs[5] = {server1, sshbuf1, sshbuf2, server2, sshbuf3};
1114  uint32_t sshlens[5] = {sizeof(server1) - 1, sizeof(sshbuf1) - 1, sizeof(sshbuf2) -1, sizeof(server2) - 1, sizeof(sshbuf3)};
1115  bool sshdirs[5] = {true, false, false, true, false};
1116 
1117  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1118  FAIL_IF_NULL(f);
1119  f->protoctx = &ssn;
1120  f->proto = IPPROTO_TCP;
1121  f->alproto = ALPROTO_SSH;
1122 
1123  p = PacketGetFromAlloc();
1124  FAIL_IF(unlikely(p == NULL));
1125  p->proto = IPPROTO_TCP;
1126  p->flow = f;
1127 
1128  uint32_t seqcli = 2;
1129  uint32_t seqsrv = 2;
1130  for (int i=0; i<5; i++) {
1131  if (sshdirs[i]) {
1132  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seqsrv, sshbufs[i], sshlens[i]) == -1);
1133  seqsrv += sshlens[i];
1134  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
1135  } else {
1136  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seqcli, sshbufs[i], sshlens[i]) == -1);
1137  seqcli += sshlens[i];
1138  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
1139  }
1140  }
1141 
1142  void *ssh_state = f->alstate;
1143  FAIL_IF_NULL(ssh_state);
1144  void *tx = SCSshStateGetTx(ssh_state, 0);
1145  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1146 
1148 
1149  UTHFreePacket(p);
1150  UTHFreeFlow(f);
1152  StreamTcpUTDeinit(ra_ctx);
1153  PASS;
1154 }
1155 
1156 /** \test Really long banner handling: bannel exactly 255 */
1157 static int SSHParserTest19(void)
1158 {
1159  TcpReassemblyThreadCtx *ra_ctx = NULL;
1160  ThreadVars tv;
1161  TcpSession ssn;
1162  Flow *f = NULL;
1163  Packet *p = NULL;
1164 
1165  uint8_t sshbuf1[] = "SSH-";
1166  uint8_t sshbuf2[] = "2.0-";
1167  uint8_t sshbuf3[] = "abcdefghijklmnopqrstuvwxyz"
1168  "abcdefghijklmnopqrstuvwxyz"//60
1169  "abcdefghijklmnopqrstuvwxyz"
1170  "abcdefghijklmnopqrstuvwxyz"//112
1171  "abcdefghijklmnopqrstuvwxyz"
1172  "abcdefghijklmnopqrstuvwxyz"//164
1173  "abcdefghijklmnopqrstuvwxyz"
1174  "abcdefghijklmnopqrstuvwxyz"//216
1175  "abcdefghijklmnopqrstuvwxyz"//242
1176  "abcdefghijkl\r";//255
1177  uint8_t sshbuf4[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00};
1178 
1179  uint8_t* sshbufs[4] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4};
1180  uint32_t sshlens[4] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3) - 1, sizeof(sshbuf4)};
1181 
1182  memset(&tv, 0x00, sizeof(tv));
1183 
1184  StreamTcpUTInit(&ra_ctx);
1187  StreamTcpUTSetupStream(&ssn.server, 1);
1188  StreamTcpUTSetupStream(&ssn.client, 1);
1189 
1190  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1191  FAIL_IF_NULL(f);
1192  f->protoctx = &ssn;
1193  f->proto = IPPROTO_TCP;
1194  f->alproto = ALPROTO_SSH;
1195 
1196  p = PacketGetFromAlloc();
1197  FAIL_IF(unlikely(p == NULL));
1198  p->proto = IPPROTO_TCP;
1199  p->flow = f;
1200 
1201  uint32_t seq = 2;
1202  for (int i=0; i<4; i++) {
1203  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
1204  seq += sshlens[i];
1205  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
1206  }
1207 
1208  void *ssh_state = f->alstate;
1209  FAIL_IF_NULL(ssh_state);
1210  void *tx = SCSshStateGetTx(ssh_state, 0);
1211  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1212 
1213  sshbuf3[sizeof(sshbuf3) - 2] = 0;
1214  FAIL_IF(SSHParserTestUtilCheck("2.0", (char *)sshbuf3, tx, STREAM_TOCLIENT));
1215 
1216  UTHFreePacket(p);
1217  UTHFreeFlow(f);
1219  StreamTcpUTDeinit(ra_ctx);
1220  PASS;
1221 }
1222 
1223 /** \test Really long banner handling: banner exactly 255,
1224  * followed by malformed record */
1225 static int SSHParserTest20(void)
1226 {
1227  TcpReassemblyThreadCtx *ra_ctx = NULL;
1228  ThreadVars tv;
1229  TcpSession ssn;
1230  Flow *f = NULL;
1231  Packet *p = NULL;
1232 
1233  uint8_t sshbuf1[] = "SSH-";
1234  uint8_t sshbuf2[] = "2.0-";
1235  uint8_t sshbuf3[] = "abcdefghijklmnopqrstuvwxyz"
1236  "abcdefghijklmnopqrstuvwxyz"//60
1237  "abcdefghijklmnopqrstuvwxyz"
1238  "abcdefghijklmnopqrstuvwxyz"//112
1239  "abcdefghijklmnopqrstuvwxyz"
1240  "abcdefghijklmnopqrstuvwxyz"//164
1241  "abcdefghijklmnopqrstuvwxyz"
1242  "abcdefghijklmnopqrstuvwxyz"//216
1243  "abcdefghijklmnopqrstuvwxyz"//242
1244  "abcdefghijklm\r";//256
1245  uint8_t sshbuf4[] = {'a','b','c','d','e','f', '\r',
1246  0x00, 0x00, 0x00, 0x06, 0x01, 21, 0x00, 0x00, 0x00};
1247 
1248  uint8_t* sshbufs[4] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4};
1249  uint32_t sshlens[4] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3) - 1, sizeof(sshbuf4) - 1};
1250 
1251  memset(&tv, 0x00, sizeof(tv));
1252 
1253  StreamTcpUTInit(&ra_ctx);
1256  StreamTcpUTSetupStream(&ssn.server, 1);
1257  StreamTcpUTSetupStream(&ssn.client, 1);
1258 
1259  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1260  FAIL_IF_NULL(f);
1261  f->protoctx = &ssn;
1262  f->proto = IPPROTO_TCP;
1263  f->alproto = ALPROTO_SSH;
1264 
1265  p = PacketGetFromAlloc();
1266  FAIL_IF(unlikely(p == NULL));
1267  p->proto = IPPROTO_TCP;
1268  p->flow = f;
1269 
1270  uint32_t seq = 2;
1271  for (int i=0; i<4; i++) {
1272  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
1273  seq += sshlens[i];
1274  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
1275  }
1276 
1277  void *ssh_state = f->alstate;
1278  FAIL_IF_NULL(ssh_state);
1279  void *tx = SCSshStateGetTx(ssh_state, 0);
1280  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1281 
1282  FAIL_IF(SSHParserTestUtilCheck("2.0", NULL, tx, STREAM_TOCLIENT));
1283 
1284  UTHFreePacket(p);
1285  UTHFreeFlow(f);
1287  StreamTcpUTDeinit(ra_ctx);
1288  PASS;
1289 }
1290 
1291 /** \test Fragmented banner handling: chunk has final part of bannel plus
1292  * a record. */
1293 static int SSHParserTest21(void)
1294 {
1295  TcpReassemblyThreadCtx *ra_ctx = NULL;
1296  ThreadVars tv;
1297  TcpSession ssn;
1298  Flow *f = NULL;
1299  Packet *p = NULL;
1300 
1301  uint8_t sshbuf1[] = "SSH-";
1302  uint8_t sshbuf2[] = "2.0-";
1303  uint8_t sshbuf3[] = "abcdefghijklmnopqrstuvwxyz"
1304  "abcdefghijklmnopqrstuvwxyz"//60
1305  "abcdefghijklmnopqrstuvwxyz"
1306  "abcdefghijklmnopqrstuvwxyz"//112
1307  "abcdefghijklmnopqrstuvwxyz"
1308  "abcdefghijklmnopqrstuvwxyz"//164
1309  "abcdefghijklmnopqrstuvwxyz"
1310  "abcdefghijklmnopqrstuvwxyz"//216
1311  "abcdefghijklmnopqrstuvwxy";//241
1312  uint8_t sshbuf4[] = {'l','i','b','s','s','h', '\r',
1313  0x00, 0x00, 0x00, 0x06, 0x01, 21, 0x00, 0x00, 0x00};
1314 
1315  uint8_t* sshbufs[4] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4};
1316  uint32_t sshlens[4] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3) - 1, sizeof(sshbuf4)};
1317 
1318  memset(&tv, 0x00, sizeof(tv));
1319 
1320  StreamTcpUTInit(&ra_ctx);
1323  StreamTcpUTSetupStream(&ssn.server, 1);
1324  StreamTcpUTSetupStream(&ssn.client, 1);
1325 
1326  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1327  FAIL_IF_NULL(f);
1328  f->protoctx = &ssn;
1329  f->proto = IPPROTO_TCP;
1330  f->alproto = ALPROTO_SSH;
1331 
1332  p = PacketGetFromAlloc();
1333  FAIL_IF(unlikely(p == NULL));
1334  p->proto = IPPROTO_TCP;
1335  p->flow = f;
1336 
1337  uint32_t seq = 2;
1338  for (int i=0; i<4; i++) {
1339  FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
1340  seq += sshlens[i];
1341  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
1342  }
1343 
1344  void *ssh_state = f->alstate;
1345  FAIL_IF_NULL(ssh_state);
1346  void *tx = SCSshStateGetTx(ssh_state, 0);
1347  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1348 
1349  FAIL_IF(SSHParserTestUtilCheck("2.0", NULL, tx, STREAM_TOCLIENT));
1350 
1351  UTHFreePacket(p);
1352  UTHFreeFlow(f);
1354  StreamTcpUTDeinit(ra_ctx);
1355  PASS;
1356 }
1357 
1358 /** \test Fragmented banner handling: chunk has final part of bannel plus
1359  * a record. */
1360 static int SSHParserTest22(void)
1361 {
1362  TcpReassemblyThreadCtx *ra_ctx = NULL;
1363  ThreadVars tv;
1364  TcpSession ssn;
1365  Flow *f = NULL;
1366  Packet *p = NULL;
1367 
1368  uint8_t sshbuf1[] = "SSH-";
1369  uint8_t sshbuf2[] = "2.0-";
1370  uint8_t sshbuf3[] = {
1371  'l', 'i', 'b', 's', 's', 'h', '\r', // 7
1372 
1373  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17,
1374  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00,
1375  0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00,
1376  0x00, 0x00, 0x00, // 50
1377 
1378  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17,
1379  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00,
1380  0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00,
1381  0x00, 0x00, 0x00, // 100
1382 
1383  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17,
1384  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00,
1385  0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00,
1386  0x00, 0x00, 0x00, // 150
1387 
1388  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17,
1389  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00,
1390  0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00,
1391  0x00, 0x00, 0x00, // 200
1392 
1393  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17,
1394  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00,
1395  0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00,
1396  0x00, 0x00, 0x00, // 250
1397 
1398  0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17,
1399  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00,
1400  0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 21, 0x00,
1401  0x00, 0x00, 0x00, // 300
1402  };
1403 
1404  uint8_t *sshbufs[3] = { sshbuf1, sshbuf2, sshbuf3 };
1405  uint32_t sshlens[3] = { sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3) - 1 };
1406 
1407  memset(&tv, 0x00, sizeof(tv));
1408 
1409  StreamTcpUTInit(&ra_ctx);
1412  StreamTcpUTSetupStream(&ssn.server, 1);
1413  StreamTcpUTSetupStream(&ssn.client, 1);
1414 
1415  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
1416  FAIL_IF_NULL(f);
1417  f->protoctx = &ssn;
1418  f->proto = IPPROTO_TCP;
1419  f->alproto = ALPROTO_SSH;
1420 
1421  p = PacketGetFromAlloc();
1422  FAIL_IF(unlikely(p == NULL));
1423  p->proto = IPPROTO_TCP;
1424  p->flow = f;
1425 
1426  uint32_t seq = 2;
1427  for (int i = 0; i < 3; i++) {
1429  &tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
1430  seq += sshlens[i];
1431  FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) <
1432  0);
1433  }
1434 
1435  void *ssh_state = f->alstate;
1436  FAIL_IF_NULL(ssh_state);
1437  void *tx = SCSshStateGetTx(ssh_state, 0);
1438  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOCLIENT) != SshStateFinished);
1439 
1440  FAIL_IF(SSHParserTestUtilCheck("2.0", "libssh", tx, STREAM_TOCLIENT));
1441 
1442  UTHFreePacket(p);
1443  UTHFreeFlow(f);
1445  StreamTcpUTDeinit(ra_ctx);
1446  PASS;
1447 }
1448 
1449 /** \test Send a version string in one chunk (client version str). */
1450 static int SSHParserTest23(void)
1451 {
1452  int result = 0;
1453  Flow f;
1454  uint8_t sshbuf[] = "SSH-2.0\r-MySSHClient-0.5.1\n";
1455  uint32_t sshlen = sizeof(sshbuf) - 1;
1456  TcpSession ssn;
1458 
1459  memset(&f, 0, sizeof(f));
1460  memset(&ssn, 0, sizeof(ssn));
1461  FLOW_INITIALIZE(&f);
1462  f.protoctx = (void *)&ssn;
1463  f.proto = IPPROTO_TCP;
1464  f.alproto = ALPROTO_SSH;
1465 
1466  StreamTcpInitConfig(true);
1467 
1468  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
1469  STREAM_TOSERVER | STREAM_EOF, sshbuf, sshlen);
1470  if (r == 0) {
1471  printf("toclient chunk 1 returned 0 expected non null: ");
1472  goto end;
1473  }
1474 
1475  result = 1;
1476 end:
1477  if (alp_tctx != NULL)
1479  StreamTcpFreeConfig(true);
1480  FLOW_DESTROY(&f);
1481  return result;
1482 }
1483 
1484 /** \test Send a version string in one chunk (client version str). */
1485 static int SSHParserTest24(void)
1486 {
1487  int result = 0;
1488  Flow f;
1489  uint8_t sshbuf[] = "SSH-2.0-\rMySSHClient-0.5.1\n";
1490  uint32_t sshlen = sizeof(sshbuf) - 1;
1491  TcpSession ssn;
1493 
1494  memset(&f, 0, sizeof(f));
1495  memset(&ssn, 0, sizeof(ssn));
1496  FLOW_INITIALIZE(&f);
1497  f.protoctx = (void *)&ssn;
1498  f.proto = IPPROTO_TCP;
1499  f.alproto = ALPROTO_SSH;
1500 
1501  StreamTcpInitConfig(true);
1502 
1503  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
1504  STREAM_TOSERVER | STREAM_EOF, sshbuf, sshlen);
1505  if (r != 0) {
1506  printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
1507  goto end;
1508  }
1509 
1510  void *ssh_state = f.alstate;
1511  if (ssh_state == NULL) {
1512  printf("no ssh state: ");
1513  goto end;
1514  }
1515  void *tx = SCSshStateGetTx(ssh_state, 0);
1516  if (SCSshTxGetFlags(tx, STREAM_TOSERVER) != SshStateBannerDone) {
1517  printf("Didn't detect the msg code of new keys (ciphered data starts): ");
1518  goto end;
1519  }
1520  if (SSHParserTestUtilCheck("2.0", NULL, tx, STREAM_TOSERVER))
1521  goto end;
1522 
1523  result = 1;
1524 end:
1525  FLOW_DESTROY(&f);
1526  if (alp_tctx != NULL)
1528  StreamTcpFreeConfig(true);
1529  return result;
1530 }
1531 
1532 /** \test Send a malformed banner */
1533 static int SSHParserTest25(void)
1534 {
1535  Flow f;
1536  uint8_t sshbuf[] = "\n";
1537  uint32_t sshlen = sizeof(sshbuf) - 1;
1538  TcpSession ssn;
1541 
1542  memset(&f, 0, sizeof(f));
1543  memset(&ssn, 0, sizeof(ssn));
1544  FLOW_INITIALIZE(&f);
1545  f.protoctx = (void *)&ssn;
1546  f.proto = IPPROTO_TCP;
1547  f.alproto = ALPROTO_SSH;
1548 
1549  StreamTcpInitConfig(true);
1550 
1551  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
1552  STREAM_TOSERVER | STREAM_EOF, sshbuf, sshlen);
1553  FAIL_IF(r != -1);
1554 
1555  void *ssh_state = f.alstate;
1556  FAIL_IF_NULL(ssh_state);
1557  void *tx = SCSshStateGetTx(ssh_state, 0);
1558  FAIL_IF(SCSshTxGetFlags(tx, STREAM_TOSERVER) == SshStateBannerDone);
1559  const uint8_t *dummy = NULL;
1560  uint32_t dummy_len = 0;
1561  FAIL_IF(SCSshTxGetSoftware(tx, &dummy, &dummy_len, STREAM_TOCLIENT) != 0);
1562 
1563  FLOW_DESTROY(&f);
1565  StreamTcpFreeConfig(true);
1566  PASS;
1567 }
1568 
1569 #endif /* UNITTESTS */
1570 
1572 {
1573 #ifdef UNITTESTS
1574  UtRegisterTest("SSHParserTest01 - ToServer", SSHParserTest01);
1575  UtRegisterTest("SSHParserTest02 - ToServer", SSHParserTest02);
1576  UtRegisterTest("SSHParserTest03 - ToServer", SSHParserTest03);
1577  UtRegisterTest("SSHParserTest04 - ToClient", SSHParserTest04);
1578  UtRegisterTest("SSHParserTest05 - ToClient", SSHParserTest05);
1579  UtRegisterTest("SSHParserTest06 - ToClient", SSHParserTest06);
1580  UtRegisterTest("SSHParserTest07 - ToServer 2 chunks", SSHParserTest07);
1581  UtRegisterTest("SSHParserTest08 - ToServer 3 chunks", SSHParserTest08);
1582  UtRegisterTest("SSHParserTest09 - ToClient 2 chunks", SSHParserTest09);
1583  UtRegisterTest("SSHParserTest10 - ToClient 3 chunks", SSHParserTest10);
1584  UtRegisterTest("SSHParserTest11 - ToClient 4 chunks", SSHParserTest11);
1585  UtRegisterTest("SSHParserTest12 - ToClient 4 chunks", SSHParserTest12);
1586  UtRegisterTest("SSHParserTest13 - ToClient 4 chunks", SSHParserTest13);
1587  UtRegisterTest("SSHParserTest14 - ToClient 4 chunks", SSHParserTest14);
1588  UtRegisterTest("SSHParserTest15", SSHParserTest15);
1589  UtRegisterTest("SSHParserTest16", SSHParserTest16);
1590  UtRegisterTest("SSHParserTest17", SSHParserTest17);
1591  UtRegisterTest("SSHParserTest18", SSHParserTest18);
1592  UtRegisterTest("SSHParserTest19", SSHParserTest19);
1593  UtRegisterTest("SSHParserTest20", SSHParserTest20);
1594  UtRegisterTest("SSHParserTest21", SSHParserTest21);
1595  UtRegisterTest("SSHParserTest22", SSHParserTest22);
1596  UtRegisterTest("SSHParserTest23", SSHParserTest23);
1597  UtRegisterTest("SSHParserTest24", SSHParserTest24);
1598  UtRegisterTest("SSHParserTest25", SSHParserTest25);
1599 #endif /* UNITTESTS */
1600 }
1601 
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:279
seq
uint32_t seq
Definition: stream-tcp-private.h:2
Flow_::proto
uint8_t proto
Definition: flow.h:370
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:1648
threads.h
flow-private.h
Flow_
Flow data structure.
Definition: flow.h:348
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:1396
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:433
StreamTcpUTInitInline
void StreamTcpUTInitInline(void)
Definition: stream-tcp-util.c:59
util-unittest.h
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
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:1941
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:470
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:497
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
decode.h
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
protocol
uint16_t protocol
Definition: decode-etag.h:4
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:80
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:1741
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:502
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:72
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:114
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:63
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:471
MAX_SSH_TEST_SIZE
#define MAX_SSH_TEST_SIZE
Definition: app-layer-ssh.c:479
stream-tcp-util.h
TcpReassemblyThreadCtx_
Definition: stream-tcp-reassemble.h:61
app-layer-protos.h
SSHParserRegisterTests
void SSHParserRegisterTests(void)
Definition: app-layer-ssh.c:1571
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:60
TcpSession_
Definition: stream-tcp-private.h:283
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:442
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