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