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