#include "app-layer-protos.h"
#include "app-layer-parser.h"
#include "app-layer-ssh.h"
+#include "rust.h"
#include "conf.h"
#include "util-byte.h"
#include "util-memcmp.h"
-/** \internal
- * \brief Function to parse the SSH version string of the client
- *
- * The input to this function is a byte buffer starting with SSH-
- *
- * \param ssh_state Pointer the state in which the value to be stored
- * \param input Pointer the received input data
- * \param input_len Length in bytes of the received data
- *
- * \retval len remaining length in input
- */
-static int SSHParseBanner(SshState *state, SshHeader *header, const uint8_t *input, uint32_t input_len)
-{
- const uint8_t *line_ptr = input;
- uint32_t line_len = input_len;
-
- /* is it the version line? */
- if (line_len < 4) {
- SCReturnInt(-1);
- }
- if (SCMemcmp("SSH-", line_ptr, 4) != 0) {
- SCReturnInt(-1);
- }
-
- const uint8_t *banner_end = BasicSearch(line_ptr, line_len, (uint8_t*)"\r", 1);
- if (banner_end == NULL) {
- banner_end = BasicSearch(line_ptr, line_len, (uint8_t*)"\n", 1);
- if (banner_end == NULL) {
- SCLogDebug("No EOL at the end of banner buffer");
- SCReturnInt(-1);
- }
- }
-
- if ((banner_end - line_ptr) > 255) {
- SCLogDebug("Invalid version string, it should be less than 255 "
- "characters including <CR><NL>, input value is %"PRIuMAX,
- (uintmax_t)(banner_end - line_ptr));
- SCReturnInt(-1);
- }
-
- /* don't search things behind the end of banner */
- line_len = banner_end - line_ptr;
-
- /* ok, we have found the version line/string, skip it and parse proto version */
- line_ptr += 4;
- line_len -= 4;
-
- uint8_t *proto_end = BasicSearch(line_ptr, line_len, (uint8_t*)"-", 1);
- if (proto_end == NULL) {
- /* Strings starting with SSH- are not allowed
- * if they are not the real version string */
- SCLogDebug("Info Version String for SSH (invalid usage of SSH- prefix)");
- SCReturnInt(-1);
- }
- uint64_t proto_ver_len = (uint64_t)(proto_end - line_ptr);
- header->proto_version = SCMalloc(proto_ver_len + 1);
- if (header->proto_version == NULL) {
- SCReturnInt(-1);
- }
- memcpy(header->proto_version, line_ptr, proto_ver_len);
- header->proto_version[proto_ver_len] = '\0';
-
- /* Now lets parse the software & version */
- line_ptr += proto_ver_len + 1;
- line_len -= proto_ver_len + 1;
- if (line_len < 1) {
- SCLogDebug("No software version specified (weird)");
- header->flags |= SSH_FLAG_VERSION_PARSED;
- /* Return the remaining length */
- SCReturnInt(0);
- }
-
- uint64_t sw_ver_len = (uint64_t)(banner_end - line_ptr);
- /* sanity check on this arithmetic */
- if ((sw_ver_len <= 1) || (sw_ver_len >= input_len)) {
- SCLogDebug("Should not have sw version length '%" PRIu64 "'", sw_ver_len);
- header->flags |= SSH_FLAG_VERSION_PARSED;
- SCReturnInt(-1);
- }
-
- header->software_version = SCMalloc(sw_ver_len + 1);
- if (header->software_version == NULL) {
- header->flags |= SSH_FLAG_VERSION_PARSED;
- SCReturnInt(-1);
- }
- memcpy(header->software_version, line_ptr, sw_ver_len);
- header->software_version[sw_ver_len] = '\0';
- if (header->software_version[sw_ver_len - 1] == 0x0d)
- header->software_version[sw_ver_len - 1] = '\0';
-
- header->flags |= SSH_FLAG_VERSION_PARSED;
-
- /* Return the remaining length */
- int len = input_len - (banner_end - input);
- SCReturnInt(len);
-}
-
-static int SSHParseRecordHeader(SshState *state, SshHeader *header,
- const uint8_t *input, uint32_t input_len)
-{
-#ifdef DEBUG
- BUG_ON(input_len != 6);
-#else
- if (input_len < 6)
- SCReturnInt(-1);
-#endif
- /* input and input_len now point past initial line */
- uint32_t pkt_len = 0;
- int r = ByteExtractUint32(&pkt_len, BYTE_BIG_ENDIAN,
- 4, input);
- if (r != 4) {
- SCLogDebug("xtract 4 bytes failed %d", r);
- SCReturnInt(-1);
- }
- if (pkt_len < 2) {
- SCReturnInt(-1);
- }
-
- header->pkt_len = pkt_len;
- SCLogDebug("pkt len: %"PRIu32, pkt_len);
-
- input += 4;
- //input_len -= 4;
-
- header->padding_len = *input;
-
- input += 1;
- //input_len -= 1;
-
- SCLogDebug("padding: %u", header->padding_len);
-
- header->msg_code = *input;
-
- SCLogDebug("msg code: %u", header->msg_code);
-
- if (header->msg_code == SSH_MSG_NEWKEYS) {
- /* done */
- SCLogDebug("done");
- header->flags |= SSH_FLAG_PARSER_DONE;
- } else {
- /* not yet done */
- SCLogDebug("not done");
- }
- SCReturnInt(0);
-}
-
-/** \internal
- * \brief Function to parse the SSH field in packet received from the client
- *
- * Input to this function is a byte buffer starting with SSH- up to at least
- * a \r or \n character.
- *
- * \param ssh_state Pointer the state in which the value to be stored
- * \param input Pointer the received input data
- * \param input_len Length in bytes of the received data
- */
-static int SSHParseRecord(SshState *state, SshHeader *header, const uint8_t *input, uint32_t input_len)
-{
- SCEnter();
- int ret = 0;
-
- if (header->flags & SSH_FLAG_PARSER_DONE) {
- SCReturnInt(0);
- }
-
- SCLogDebug("state %p, input %p,input_len %" PRIu32,
- state, input, input_len);
- //PrintRawDataFp(stdout, input, input_len);
-
- if (!(header->flags & SSH_FLAG_VERSION_PARSED)) {
- ret = SSHParseBanner(state, header, input, input_len);
- if (ret < 0) {
- SCLogDebug("Invalid version string");
- SCReturnInt(-1);
- } else if (header->flags & SSH_FLAG_VERSION_PARSED) {
- SCLogDebug("Version string parsed, remaining length %d", ret);
- input += input_len - ret;
- input_len -= (input_len - ret);
-
- uint32_t u = 0;
- while (u < input_len && (input[u] == '\r' || input[u] == '\n')) {
- u++;
- }
- SCLogDebug("skipping %u EOL bytes", u);
- input += u;
- input_len -= u;
-
- if (input_len == 0)
- SCReturnInt(0);
-
- } else {
- BUG_ON(1);// we only call this when we have enough data
- SCLogDebug("Version string not parsed yet");
- //pstate->parse_field = 0;
- SCReturnInt(0);
- }
- } else {
- SCLogDebug("Version string already parsed");
- }
-
- /* skip bytes from the current record if we have to */
- if (header->record_left > 0) {
- SCLogDebug("skipping bytes part of the current record");
- if (header->record_left > input_len) {
- header->record_left -= input_len;
- SCLogDebug("all input skipped, %u left in record", header->record_left);
- SCReturnInt(0);
- } else {
- input_len -= header->record_left;
- input += header->record_left;
- header->record_left = 0;
-
- if (input_len == 0) {
- SCLogDebug("all input skipped");
- SCReturnInt(0);
- }
- }
- }
-
-again:
- /* input is too small, even when combined with stored bytes */
- if (header->buf_offset + input_len < 6) {
- memcpy(header->buf + header->buf_offset, input, input_len);
- header->buf_offset += input_len;
- SCReturnInt(0);
-
- /* we have enough bytes to parse 6 bytes, lets see if we have
- * previously stored some */
- } else if (header->buf_offset > 0) {
- uint8_t needed = 6 - header->buf_offset;
-
- SCLogDebug("parse stored");
- memcpy(header->buf + header->buf_offset, input, needed);
- header->buf_offset = 6;
-
- // parse the 6
- if (SSHParseRecordHeader(state, header, header->buf, 6) < 0)
- SCReturnInt(-1);
- header->buf_offset = 0;
-
- uint32_t record_left = header->pkt_len - 2;
- input_len -= needed;
- input += needed;
-
- if (record_left > input_len) {
- header->record_left = record_left - input_len;
- } else {
- input_len -= record_left;
- if (input_len == 0)
- SCReturnInt(0);
-
- input += record_left;
-
- SCLogDebug("we have %u left to parse", input_len);
- goto again;
-
- }
-
- /* nothing stored, lets parse this directly */
- } else {
- SCLogDebug("parse direct");
- //PrintRawDataFp(stdout, input, input_len);
- if (SSHParseRecordHeader(state, header, input, 6) < 0)
- SCReturnInt(-1);
-
- uint32_t record_left = header->pkt_len - 2;
- SCLogDebug("record left %u", record_left);
- input_len -= 6;
- input += 6;
-
- if (record_left > input_len) {
- header->record_left = record_left - input_len;
- } else {
- input_len -= record_left;
- if (input_len == 0)
- SCReturnInt(0);
- input += record_left;
- //PrintRawDataFp(stdout, input, input_len);
-
- SCLogDebug("we have %u left to parse", input_len);
- goto again;
- }
- }
-
- SCReturnInt(0);
-}
-
-static int EnoughData(const uint8_t *input, uint32_t input_len)
-{
- uint32_t u;
- for (u = 0; u < input_len; u++) {
- if (input[u] == '\r' || input[u] == '\n')
- return TRUE;
- }
- return FALSE;
-}
-
-#define MAX_BANNER_LEN 256
-
-static int SSHParseData(SshState *state, SshHeader *header,
- const uint8_t *input, uint32_t input_len)
-{
- /* we're looking for the banner */
- if (!(header->flags & SSH_FLAG_VERSION_PARSED))
- {
- int banner_eol = EnoughData(input, input_len);
-
- /* fast track normal case: no buffering */
- if (header->banner_buffer == NULL && banner_eol)
- {
- SCLogDebug("enough data, parse now");
- // parse now
- int r = SSHParseRecord(state, header, input, input_len);
- SCReturnInt(r);
-
- /* banner EOL with existing buffer present. Time for magic. */
- } else if (banner_eol) {
- SCLogDebug("banner EOL with existing buffer");
-
- uint32_t tocopy = MAX_BANNER_LEN - header->banner_len;
- if (tocopy > input_len)
- tocopy = input_len;
-
- SCLogDebug("tocopy %u input_len %u", tocopy, input_len);
- memcpy(header->banner_buffer + header->banner_len, input, tocopy);
- header->banner_len += tocopy;
-
- SCLogDebug("header->banner_len %u", header->banner_len);
- int r = SSHParseRecord(state, header,
- header->banner_buffer, header->banner_len);
- if (r == 0) {
- input += tocopy;
- input_len -= tocopy;
- if (input_len > 0) {
- SCLogDebug("handling remaining data %u", input_len);
- r = SSHParseRecord(state, header, input, input_len);
- }
- }
- SCReturnInt(r);
-
- /* no banner EOL, so we need to buffer */
- } else if (!banner_eol) {
- if (header->banner_buffer == NULL) {
- header->banner_buffer = SCMalloc(MAX_BANNER_LEN);
- if (header->banner_buffer == NULL)
- SCReturnInt(-1);
- }
-
- uint32_t tocopy = MAX_BANNER_LEN - header->banner_len;
- if (tocopy > input_len)
- tocopy = input_len;
- SCLogDebug("tocopy %u", tocopy);
-
- memcpy(header->banner_buffer + header->banner_len, input, tocopy);
- header->banner_len += tocopy;
- SCLogDebug("header->banner_len %u", header->banner_len);
- }
-
- /* we have a banner, the rest is just records */
- } else {
- int r = SSHParseRecord(state, header, input, input_len);
- SCReturnInt(r);
- }
-
- //PrintRawDataFp(stdout, input, input_len);
- return 0;
-}
-
-static AppLayerResult SSHParseRequest(Flow *f, void *state, AppLayerParserState *pstate,
- const uint8_t *input, uint32_t input_len,
- void *local_data, const uint8_t flags)
-{
- SshState *ssh_state = (SshState *)state;
- SshHeader *ssh_header = &ssh_state->cli_hdr;
-
- if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
- SCReturnStruct(APP_LAYER_OK);
- } else if (input == NULL || input_len == 0) {
- SCReturnStruct(APP_LAYER_ERROR);
- }
-
- int r = SSHParseData(ssh_state, ssh_header, input, input_len);
-
- if (ssh_state->cli_hdr.flags & SSH_FLAG_PARSER_DONE &&
- ssh_state->srv_hdr.flags & SSH_FLAG_PARSER_DONE) {
- AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_NO_INSPECTION);
- AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_NO_REASSEMBLY);
- AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_BYPASS_READY);
- }
-
- if (r < 0) {
- SCReturnStruct(APP_LAYER_ERROR);
- }
- SCReturnStruct(APP_LAYER_OK);
-}
-
-static AppLayerResult SSHParseResponse(Flow *f, void *state, AppLayerParserState *pstate,
- const uint8_t *input, uint32_t input_len,
- void *local_data, const uint8_t flags)
-{
- SshState *ssh_state = (SshState *)state;
- SshHeader *ssh_header = &ssh_state->srv_hdr;
-
- if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
- SCReturnStruct(APP_LAYER_OK);
- } else if (input == NULL || input_len == 0) {
- SCReturnStruct(APP_LAYER_ERROR);
- }
-
- int r = SSHParseData(ssh_state, ssh_header, input, input_len);
-
- if (ssh_state->cli_hdr.flags & SSH_FLAG_PARSER_DONE &&
- ssh_state->srv_hdr.flags & SSH_FLAG_PARSER_DONE) {
- AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_NO_INSPECTION);
- AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_NO_REASSEMBLY);
- AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_BYPASS_READY);
- }
-
- if (r < 0) {
- SCReturnStruct(APP_LAYER_ERROR);
- }
- SCReturnStruct(APP_LAYER_OK);
-}
-
-/** \brief Function to allocates the SSH state memory
- */
-static void *SSHStateAlloc(void)
-{
- void *s = SCMalloc(sizeof(SshState));
- if (unlikely(s == NULL))
- return NULL;
-
- memset(s, 0, sizeof(SshState));
- return s;
-}
-
-/** \brief Function to free the SSH state memory
- */
-static void SSHStateFree(void *state)
-{
- SshState *s = (SshState *)state;
- if (s->cli_hdr.proto_version != NULL)
- SCFree(s->cli_hdr.proto_version);
- if (s->cli_hdr.software_version != NULL)
- SCFree(s->cli_hdr.software_version);
- if (s->cli_hdr.banner_buffer != NULL)
- SCFree(s->cli_hdr.banner_buffer);
-
- if (s->srv_hdr.proto_version != NULL)
- SCFree(s->srv_hdr.proto_version);
- if (s->srv_hdr.software_version != NULL)
- SCFree(s->srv_hdr.software_version);
- if (s->srv_hdr.banner_buffer != NULL)
- SCFree(s->srv_hdr.banner_buffer);
-
- //AppLayerDecoderEventsFreeEvents(&s->decoder_events);
-
- if (s->de_state != NULL) {
- DetectEngineStateFree(s->de_state);
- }
-
- SCFree(s);
-}
-
-static int SSHSetTxDetectState(void *vtx, DetectEngineState *de_state)
-{
- SshState *ssh_state = (SshState *)vtx;
- ssh_state->de_state = de_state;
- return 0;
-}
-
-static DetectEngineState *SSHGetTxDetectState(void *vtx)
-{
- SshState *ssh_state = (SshState *)vtx;
- return ssh_state->de_state;
-}
-
-static void SSHStateTransactionFree(void *state, uint64_t tx_id)
-{
- /* do nothing */
-}
-
-static void *SSHGetTx(void *state, uint64_t tx_id)
-{
- SshState *ssh_state = (SshState *)state;
- return ssh_state;
-}
-
-static uint64_t SSHGetTxCnt(void *state)
-{
- /* single tx */
- return 1;
-}
-
-static void SSHSetTxLogged(void *state, void *tx, LoggerId logged)
-{
- SshState *ssh_state = (SshState *)state;
- if (ssh_state)
- ssh_state->logged = logged;
-}
-
-static LoggerId SSHGetTxLogged(void *state, void *tx)
-{
- SshState *ssh_state = (SshState *)state;
- if (ssh_state) {
- return ssh_state->logged;
- }
- return 0;
-}
-
-static uint64_t SSHGetTxDetectFlags(void *vtx, uint8_t dir)
-{
- SshState *ssh_state = (SshState *)vtx;
- if (dir & STREAM_TOSERVER) {
- return ssh_state->detect_flags_ts;
- } else {
- return ssh_state->detect_flags_tc;
- }
-}
-
-static void SSHSetTxDetectFlags(void *vtx, uint8_t dir, uint64_t flags)
-{
- SshState *ssh_state = (SshState *)vtx;
- if (dir & STREAM_TOSERVER) {
- ssh_state->detect_flags_ts = flags;
- } else {
- ssh_state->detect_flags_tc = flags;
- }
-}
-
-static int SSHGetAlstateProgressCompletionStatus(uint8_t direction)
-{
- return SSH_STATE_FINISHED;
-}
-
-static int SSHGetAlstateProgress(void *tx, uint8_t direction)
-{
- SshState *ssh_state = (SshState *)tx;
-
- if (ssh_state->cli_hdr.flags & SSH_FLAG_PARSER_DONE &&
- ssh_state->srv_hdr.flags & SSH_FLAG_PARSER_DONE) {
- return SSH_STATE_FINISHED;
- }
-
- if (direction == STREAM_TOSERVER) {
- if (ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED) {
- return SSH_STATE_BANNER_DONE;
- }
- } else {
- if (ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED) {
- return SSH_STATE_BANNER_DONE;
- }
- }
-
- return SSH_STATE_IN_PROGRESS;
-}
static int SSHRegisterPatternsForProtocolDetection(void)
{
return;
}
- if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
- AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_SSH, STREAM_TOSERVER,
- SSHParseRequest);
- AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_SSH, STREAM_TOCLIENT,
- SSHParseResponse);
- AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_SSH, SSHStateAlloc, SSHStateFree);
- AppLayerParserRegisterParserAcceptableDataDirection(IPPROTO_TCP,
- ALPROTO_SSH, STREAM_TOSERVER|STREAM_TOCLIENT);
-
- AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_SSH, SSHStateTransactionFree);
-
- AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_SSH,
- SSHGetTxDetectState, SSHSetTxDetectState);
-
- AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_SSH, SSHGetTx);
+ SCLogDebug("Registering Rust SSH parser.");
+ rs_ssh_register_parser();
- AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_SSH, SSHGetTxCnt);
-
- AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_SSH, SSHGetAlstateProgress);
-
- AppLayerParserRegisterLoggerFuncs(IPPROTO_TCP, ALPROTO_SSH, SSHGetTxLogged, SSHSetTxLogged);
- AppLayerParserRegisterDetectFlagsFuncs(IPPROTO_TCP, ALPROTO_SSH,
- SSHGetTxDetectFlags, SSHSetTxDetectFlags);
-
- AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_SSH,
- SSHGetAlstateProgressCompletionStatus);
- } else {
-// SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
-// "still on.", proto_name);
- }
#ifdef UNITTESTS
AppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_SSH, SSHParserRegisterTests);
/* UNITTESTS */
#ifdef UNITTESTS
#include "flow-util.h"
+#include "stream-tcp-util.h"
+#include "util-unittest-helper.h"
+
+static int SSHParserTestUtilCheck(const char *protoexp, const char *softexp, void *tx, uint8_t flags) {
+ const uint8_t *protocol = NULL;
+ uint32_t p_len = 0;
+ const uint8_t *software = NULL;
+ uint32_t s_len = 0;
+
+ if (rs_ssh_tx_get_protocol(tx, &protocol, &p_len, flags) != 1) {
+ printf("Version string not parsed correctly return: ");
+ return 1;
+ }
+ if (protocol == NULL) {
+ printf("Version string not parsed correctly NULL: ");
+ return 1;
+ }
+
+ if (p_len != strlen(protoexp)) {
+ printf("Version string not parsed correctly length: ");
+ return 1;
+ }
+ if (memcmp(protocol, protoexp, strlen(protoexp)) != 0) {
+ printf("Version string not parsed correctly: ");
+ return 1;
+ }
+
+ if (softexp != NULL) {
+ if (rs_ssh_tx_get_software(tx, &software, &s_len, flags) != 1)
+ return 1;
+ if (software == NULL)
+ return 1;
+ if (s_len != strlen(softexp)) {
+ printf("Software string not parsed correctly length: ");
+ return 1;
+ }
+ if (memcmp(software, softexp, strlen(softexp)) != 0) {
+ printf("Software string not parsed correctly: ");
+ return 1;
+ }
+ }
+ return 0;
+}
/** \test Send a version string in one chunk (client version str). */
static int SSHParserTest01(void)
goto end;
}
- SshState *ssh_state = f.alstate;
+ void *ssh_state = f.alstate;
if (ssh_state == NULL) {
printf("no ssh state: ");
goto end;
}
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->cli_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->cli_hdr.proto_version == NULL) {
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ if ( rs_ssh_tx_get_alstate_progress(tx, STREAM_TOSERVER) != SshStateBannerDone ) {
printf("Client version string not parsed: ");
goto end;
}
- if (strncmp((char*)ssh_state->cli_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
-
- if (strncmp((char*)ssh_state->cli_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
+ if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER))
goto end;
- }
result = 1;
end:
goto end;
}
- SshState *ssh_state = f.alstate;
+ void *ssh_state = f.alstate;
if (ssh_state == NULL) {
printf("no ssh state: ");
goto end;
}
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->cli_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->cli_hdr.proto_version == NULL) {
+ if ( rs_ssh_tx_get_alstate_progress(tx, STREAM_TOSERVER) != SshStateBannerDone ) {
printf("Client version string not parsed: ");
goto end;
}
-
- if (strncmp((char*)ssh_state->cli_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
-
- if (strncmp((char*)ssh_state->cli_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
+ if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER))
goto end;
- }
result = 1;
end:
goto end;
}
- SshState *ssh_state = f.alstate;
+ void *ssh_state = f.alstate;
if (ssh_state == NULL) {
printf("no ssh state: ");
goto end;
}
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
- if (ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED) {
+ if ( rs_ssh_tx_get_alstate_progress(tx, STREAM_TOSERVER) == SshStateBannerDone ) {
printf("Client version string parsed? It's not a valid string: ");
goto end;
}
-
- if (ssh_state->cli_hdr.proto_version != NULL) {
+ const uint8_t *dummy = NULL;
+ uint32_t dummy_len = 0;
+ if (rs_ssh_tx_get_protocol(tx, &dummy, &dummy_len, STREAM_TOSERVER) != 0)
goto end;
- }
-
- if (ssh_state->cli_hdr.software_version != NULL) {
+ if (rs_ssh_tx_get_software(tx, &dummy, &dummy_len, STREAM_TOSERVER) != 0)
goto end;
- }
result = 1;
end:
goto end;
}
- SshState *ssh_state = f.alstate;
+ void *ssh_state = f.alstate;
if (ssh_state == NULL) {
printf("no ssh state: ");
goto end;
}
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
- if (!(ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->srv_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->srv_hdr.proto_version == NULL) {
+ if ( rs_ssh_tx_get_alstate_progress(tx, STREAM_TOCLIENT) != SshStateBannerDone ) {
printf("Client version string not parsed: ");
goto end;
}
-
- if (strncmp((char*)ssh_state->srv_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
-
- if (strncmp((char*)ssh_state->srv_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
+ if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT))
goto end;
- }
result = 1;
goto end;
}
- SshState *ssh_state = f.alstate;
+ void *ssh_state = f.alstate;
if (ssh_state == NULL) {
printf("no ssh state: ");
goto end;
}
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
- if (!(ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->srv_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->srv_hdr.proto_version == NULL) {
+ if ( rs_ssh_tx_get_alstate_progress(tx, STREAM_TOCLIENT) != SshStateBannerDone ) {
printf("Client version string not parsed: ");
goto end;
}
-
- if (strncmp((char*)ssh_state->srv_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
-
- if (strncmp((char*)ssh_state->srv_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
+ if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT))
goto end;
- }
result = 1;
end:
}
/* Ok, it returned an error. Let's make sure we didn't parse the string at all */
- SshState *ssh_state = f.alstate;
+ void *ssh_state = f.alstate;
if (ssh_state == NULL) {
printf("no ssh state: ");
goto end;
}
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
- if (ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED) {
+ if ( rs_ssh_tx_get_alstate_progress(tx, STREAM_TOCLIENT) == SshStateBannerDone ) {
printf("Client version string parsed? It's not a valid string: ");
goto end;
}
-
- if (ssh_state->srv_hdr.proto_version != NULL) {
+ const uint8_t *dummy = NULL;
+ uint32_t dummy_len = 0;
+ if (rs_ssh_tx_get_protocol(tx, &dummy, &dummy_len, STREAM_TOCLIENT) != 0)
goto end;
- }
-
- if (ssh_state->srv_hdr.software_version != NULL) {
+ if (rs_ssh_tx_get_software(tx, &dummy, &dummy_len, STREAM_TOCLIENT) != 0)
goto end;
- }
+
result = 1;
end:
return result;
}
+#define MAX_SSH_TEST_SIZE 512
+
static int SSHParserTest07(void)
{
- int result = 0;
- Flow f;
- uint8_t sshbuf1[] = "SSH-2.";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
- uint8_t sshbuf2[] = { "0-MySSHClient-0.5.1\r\n"};
- uint32_t sshlen2 = sizeof(sshbuf2) - 1;
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ Flow *f = NULL;
+ Packet *p = NULL;
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
+ char sshbufs[2][MAX_SSH_TEST_SIZE] = {"SSH-2.", "0-MySSHClient-0.5.1\r\n"};
- StreamTcpInitConfig(TRUE);
+ memset(&tv, 0x00, sizeof(tv));
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOSERVER, sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf2, sshlen2);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
-
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
-
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
- if (ssh_state->cli_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
- if (ssh_state->cli_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
- if (strncmp((char*)ssh_state->cli_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
+ uint32_t seq = 2;
+ for (int i=0; i<2; i++) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, (uint8_t *) sshbufs[i], strlen(sshbufs[i])) == -1);
+ seq += strlen(sshbufs[i]);
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
}
- if (strncmp((char*)ssh_state->cli_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_alstate_progress(tx, STREAM_TOSERVER) != SshStateBannerDone );
- result = 1;
+ FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
}
/** \test Send a version banner in three chunks. */
static int SSHParserTest08(void)
{
- int result = 0;
- Flow f;
- uint8_t sshbuf1[] = "SSH-";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
- uint8_t sshbuf2[] = "2.";
- uint32_t sshlen2 = sizeof(sshbuf2) - 1;
- uint8_t sshbuf3[] = { "0-MySSHClient-0.5.1\r\n"};
- uint32_t sshlen3 = sizeof(sshbuf3) - 1;
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ Flow *f = NULL;
+ Packet *p = NULL;
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
-
- StreamTcpInitConfig(TRUE);
+ char sshbufs[3][MAX_SSH_TEST_SIZE] = {"SSH-", "2.", "0-MySSHClient-0.5.1\r\n"};
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOSERVER, sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf2, sshlen2);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf3, sshlen3);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
+ memset(&tv, 0x00, sizeof(tv));
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
- if (ssh_state->cli_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
- if (ssh_state->cli_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
+ uint32_t seq = 2;
+ for (int i=0; i<3; i++) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, (uint8_t *) sshbufs[i], strlen(sshbufs[i])) == -1);
+ seq += strlen(sshbufs[i]);
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
}
- if (strncmp((char*)ssh_state->cli_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_alstate_progress(tx, STREAM_TOSERVER) != SshStateBannerDone );
- if (strncmp((char*)ssh_state->cli_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
- result = 1;
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
}
static int SSHParserTest09(void)
{
- int result = 0;
- Flow f;
- uint8_t sshbuf1[] = "SSH-2.";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
- uint8_t sshbuf2[] = { "0-MySSHClient-0.5.1\r\n"};
- uint32_t sshlen2 = sizeof(sshbuf2) - 1;
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
+ Flow *f = NULL;
+ Packet *p = NULL;
- StreamTcpInitConfig(TRUE);
-
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOCLIENT, sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf2, sshlen2);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
+ char sshbufs[2][MAX_SSH_TEST_SIZE] = {"SSH-2.", "0-MySSHClient-0.5.1\r\n"};
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
+ memset(&tv, 0x00, sizeof(tv));
- if (!(ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
- if (ssh_state->srv_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
- if (ssh_state->srv_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
- if (strncmp((char*)ssh_state->srv_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
+ uint32_t seq = 2;
+ for (int i=0; i<2; i++) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, (uint8_t *) sshbufs[i], strlen(sshbufs[i])) == -1);
+ seq += strlen(sshbufs[i]);
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
}
- if (strncmp((char*)ssh_state->srv_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_alstate_progress(tx, STREAM_TOCLIENT) != SshStateBannerDone );
- result = 1;
+ FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT));
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
}
/** \test Send a version banner in three chunks. */
static int SSHParserTest10(void)
{
- int result = 0;
- Flow f;
- uint8_t sshbuf1[] = "SSH-";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
- uint8_t sshbuf2[] = "2.";
- uint32_t sshlen2 = sizeof(sshbuf2) - 1;
- uint8_t sshbuf3[] = { "0-MySSHClient-0.5.1\r\n"};
- uint32_t sshlen3 = sizeof(sshbuf3) - 1;
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
+ Flow *f = NULL;
+ Packet *p = NULL;
- StreamTcpInitConfig(TRUE);
+ char sshbufs[3][MAX_SSH_TEST_SIZE] = {"SSH-", "2.", "0-MySSHClient-0.5.1\r\n"};
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOCLIENT, sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf2, sshlen2);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf3, sshlen3);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
+ memset(&tv, 0x00, sizeof(tv));
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
- if (!(ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
- if (ssh_state->srv_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
- if (ssh_state->srv_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
+ uint32_t seq = 2;
+ for (int i=0; i<3; i++) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, (uint8_t *) sshbufs[i], strlen(sshbufs[i])) == -1);
+ seq += strlen(sshbufs[i]);
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
}
- if (strncmp((char*)ssh_state->srv_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_alstate_progress(tx, STREAM_TOCLIENT) != SshStateBannerDone );
- if (strncmp((char*)ssh_state->srv_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT));
- result = 1;
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
}
/** \test Send a banner and record in three chunks. */
goto end;
}
- SshState *ssh_state = f.alstate;
+ void *ssh_state = f.alstate;
if (ssh_state == NULL) {
printf("no ssh state: ");
goto end;
}
-
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->cli_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->cli_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (strncmp((char*)ssh_state->cli_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
-
- if (strncmp((char*)ssh_state->cli_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
-
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_PARSER_DONE)) {
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ if ( rs_ssh_tx_get_flags(tx, STREAM_TOSERVER) != SshStateFinished ) {
printf("Didn't detect the msg code of new keys (ciphered data starts): ");
goto end;
}
+ if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER))
+ goto end;
result = 1;
end:
goto end;
}
- SshState *ssh_state = f.alstate;
+ void *ssh_state = f.alstate;
if (ssh_state == NULL) {
printf("no ssh state: ");
goto end;
}
-
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->cli_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->cli_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (strncmp((char*)ssh_state->cli_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
-
- if (strncmp((char*)ssh_state->cli_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
-
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_PARSER_DONE)) {
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ if ( rs_ssh_tx_get_flags(tx, STREAM_TOSERVER) != SshStateFinished ) {
printf("Didn't detect the msg code of new keys (ciphered data starts): ");
goto end;
}
+ if (SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER))
+ goto end;
result = 1;
end:
/** \test Send a banner and 2 records record in four chunks. */
static int SSHParserTest13(void)
{
- int result = 0;
- Flow f;
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
+ TcpSession ssn;
+ Flow *f = NULL;
+ Packet *p = NULL;
+
uint8_t sshbuf1[] = "SSH-2.0-MySSHClient-0.5.1\r\n";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
uint8_t sshbuf2[] = { 0x00, 0x00, 0x00, 0x02, 0x01, 17};
- uint32_t sshlen2 = sizeof(sshbuf2);
uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x02, 0x01, 21};
- uint32_t sshlen3 = sizeof(sshbuf3);
- TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
- uint32_t u;
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
+ uint8_t* sshbufs[3] = {sshbuf1, sshbuf2, sshbuf3};
+ uint32_t sshlens[3] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2), sizeof(sshbuf3)};
- StreamTcpInitConfig(TRUE);
+ memset(&tv, 0x00, sizeof(tv));
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOSERVER, sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- for (u = 0; u < sshlen2; u++) {
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOSERVER, &sshbuf2[u], 1);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- }
- for (u = 0; u < sshlen3; u++) {
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOSERVER, &sshbuf3[u], 1);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- }
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
-
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
+
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
+
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
+
+ uint32_t seq = 2;
+ for (int i=0; i<3; i++) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, sshbufs[i], sshlens[i]) == -1);
+ seq += sshlens[i];
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
}
- if (ssh_state->cli_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->cli_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (strncmp((char*)ssh_state->cli_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
-
- if (strncmp((char*)ssh_state->cli_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_flags(tx, STREAM_TOSERVER) != SshStateFinished );
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_PARSER_DONE)) {
- printf("Didn't detect the msg code of new keys (ciphered data starts): ");
- goto end;
- }
+ FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
- result = 1;
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
}
/** \test Send a banner and 2 records record in four chunks. */
static int SSHParserTest14(void)
{
- int result = 0;
- Flow f;
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
+ TcpSession ssn;
+ Flow *f = NULL;
+ Packet *p = NULL;
+
uint8_t sshbuf1[] = "SSH-2.0-MySSHClient-0.5.1\r\n";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
uint8_t sshbuf2[] = { 0x00, 0x00, 0x00, 0x10, 0x01, 17, 0x00};
- uint32_t sshlen2 = sizeof(sshbuf2);
-
uint8_t sshbuf3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
- uint32_t sshlen3 = sizeof(sshbuf3);
uint8_t sshbuf4[] = { 0x09, 0x10, 0x11, 0x12, 0x13, 0x00};
- uint32_t sshlen4 = sizeof(sshbuf4);
-
/* first byte of this record in sshbuf4 */
uint8_t sshbuf5[] = { 0x00, 0x00, 0x02, 0x01, 21};
- uint32_t sshlen5 = sizeof(sshbuf5);
- TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
+ uint8_t* sshbufs[5] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4, sshbuf5};
+ uint32_t sshlens[5] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2), sizeof(sshbuf3), sizeof(sshbuf4), sizeof(sshbuf5)};
- StreamTcpInitConfig(TRUE);
+ memset(&tv, 0x00, sizeof(tv));
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOSERVER, sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf2, sshlen2);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf3, sshlen3);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf4, sshlen4);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf5, sshlen5);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
- if (ssh_state->cli_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->cli_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (strncmp((char*)ssh_state->cli_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
+ uint32_t seq = 2;
+ for (int i=0; i<5; i++) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, sshbufs[i], sshlens[i]) == -1);
+ seq += sshlens[i];
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
}
- if (strncmp((char*)ssh_state->cli_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_flags(tx, STREAM_TOSERVER) != SshStateFinished );
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_PARSER_DONE)) {
- printf("Didn't detect the msg code of new keys (ciphered data starts): ");
- goto end;
- }
+ FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
- result = 1;
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
}
/** \test Send a banner and 2 records record in four chunks. */
static int SSHParserTest15(void)
{
- int result = 0;
- Flow f;
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
+ TcpSession ssn;
+ Flow *f = NULL;
+ Packet *p = NULL;
+
uint8_t sshbuf1[] = "SSH-2.0-MySSHClient-0.5.1\r\n";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
uint8_t sshbuf2[] = { 0x00, 0x00, 0x00, 0x10, 0x01, 17, 0x00};
- uint32_t sshlen2 = sizeof(sshbuf2);
-
uint8_t sshbuf3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
- uint32_t sshlen3 = sizeof(sshbuf3);
uint8_t sshbuf4[] = { 0x09, 0x10, 0x11, 0x12, 0x13, 0x00};
- uint32_t sshlen4 = sizeof(sshbuf4);
-
- /* first byte of this record in sshbuf4 */
uint8_t sshbuf5[] = { 0x00, 0x00, 0x02, 0x01, 20, 0x00, 0x00, 0x00, 0x02, 0x01, 21};
- uint32_t sshlen5 = sizeof(sshbuf5);
- TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
+ uint8_t* sshbufs[5] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4, sshbuf5};
+ uint32_t sshlens[5] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2), sizeof(sshbuf3), sizeof(sshbuf4), sizeof(sshbuf5)};
- StreamTcpInitConfig(TRUE);
+ memset(&tv, 0x00, sizeof(tv));
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOSERVER, sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf2, sshlen2);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf3, sshlen3);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf4, sshlen4);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf5, sshlen5);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
- if (ssh_state->cli_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
+ uint32_t seq = 2;
+ for (int i=0; i<5; i++) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seq, sshbufs[i], sshlens[i]) == -1);
+ seq += sshlens[i];
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
}
- if (ssh_state->cli_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (strncmp((char*)ssh_state->cli_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_flags(tx, STREAM_TOSERVER) != SshStateFinished );
- if (strncmp((char*)ssh_state->cli_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOSERVER));
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_PARSER_DONE)) {
- printf("Didn't detect the msg code of new keys (ciphered data starts): ");
- goto end;
- }
-
- result = 1;
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
}
/** \test Send toserver a banner and record in three chunks. */
static int SSHParserTest16(void)
{
- int result = 0;
- Flow f;
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
+ TcpSession ssn;
+ Flow *f = NULL;
+ Packet *p = NULL;
+
uint8_t sshbuf1[] = "SSH-";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
uint8_t sshbuf2[] = "2.0-MySSHClient-0.5.1\r\n";
- uint32_t sshlen2 = sizeof(sshbuf2) - 1;
uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x03,0x01, 21, 0x00};
- uint32_t sshlen3 = sizeof(sshbuf3);
- TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
-
- StreamTcpInitConfig(TRUE);
-
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOCLIENT, sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf2, sshlen2);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf3, sshlen3);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
+ uint8_t* sshbufs[3] = {sshbuf1, sshbuf2, sshbuf3};
+ uint32_t sshlens[3] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3)};
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
+ memset(&tv, 0x00, sizeof(tv));
- if (!(ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
- if (ssh_state->srv_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
- if (ssh_state->srv_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
- if (strncmp((char*)ssh_state->srv_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
+ uint32_t seq = 2;
+ for (int i=0; i<3; i++) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
+ seq += sshlens[i];
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
}
- if (strncmp((char*)ssh_state->srv_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_flags(tx, STREAM_TOCLIENT) != SshStateFinished );
- if ( !(ssh_state->srv_hdr.flags & SSH_FLAG_PARSER_DONE)) {
- printf("Didn't detect the msg code of new keys (ciphered data starts): ");
- goto end;
- }
+ FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT));
- result = 1;
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
}
/** \test Send toserver a banner and 2 records record in four chunks. */
static int SSHParserTest17(void)
{
- int result = 0;
- Flow f;
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
+ TcpSession ssn;
+ Flow *f = NULL;
+ Packet *p = NULL;
+
uint8_t sshbuf1[] = "SSH-";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
uint8_t sshbuf2[] = "2.0-MySSHClient-0.5.1\r\n";
- uint32_t sshlen2 = sizeof(sshbuf2) - 1;
uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 17, 0x00};
- uint32_t sshlen3 = sizeof(sshbuf3);
uint8_t sshbuf4[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00};
- uint32_t sshlen4 = sizeof(sshbuf4);
- TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
+ uint8_t* sshbufs[4] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4};
+ uint32_t sshlens[4] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3), sizeof(sshbuf4)};
- StreamTcpInitConfig(TRUE);
+ memset(&tv, 0x00, sizeof(tv));
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOCLIENT, sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf2, sshlen2);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf3, sshlen3);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf4, sshlen4);
- if (r != 0) {
- printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
- if (!(ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
- if (ssh_state->srv_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
+ uint32_t seq = 2;
+ for (int i=0; i<4; i++) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
+ seq += sshlens[i];
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
}
- if (ssh_state->srv_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (strncmp((char*)ssh_state->srv_hdr.software_version, "MySSHClient-0.5.1", strlen("MySSHClient-0.5.1")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_flags(tx, STREAM_TOCLIENT) != SshStateFinished );
- if (strncmp((char*)ssh_state->srv_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ FAIL_IF(SSHParserTestUtilCheck("2.0", "MySSHClient-0.5.1", tx, STREAM_TOCLIENT));
- if ( !(ssh_state->srv_hdr.flags & SSH_FLAG_PARSER_DONE)) {
- printf("Didn't detect the msg code of new keys (ciphered data starts): ");
- goto end;
- }
-
- result = 1;
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
}
/** \test 2 directional test */
static int SSHParserTest18(void)
{
- int result = 0;
- Flow f;
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
+ TcpSession ssn;
+ Flow *f = NULL;
+ Packet *p = NULL;
uint8_t server1[] = "SSH-2.0-OpenSSH_4.7p1 Debian-8ubuntu3\r\n";
- uint32_t serverlen1 = sizeof(server1) - 1;
-
uint8_t sshbuf1[] = "SSH-";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
uint8_t sshbuf2[] = "2.0-MySSHClient-0.5.1\r\n";
- uint32_t sshlen2 = sizeof(sshbuf2) - 1;
-
uint8_t server2[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00 };
- uint32_t serverlen2 = sizeof(server2) - 1;
-
- uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00 };
- uint32_t sshlen3 = sizeof(sshbuf3);
-
-
- TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
-
- StreamTcpInitConfig(TRUE);
-
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOCLIENT, server1, serverlen1);
- if (r != 0) {
- printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf2, sshlen2);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- server2, serverlen2);
- if (r != 0) {
- printf("toclient chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
-
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOSERVER,
- sshbuf3, sshlen3);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
-
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
-
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_PARSER_DONE)) {
- printf("Didn't detect the msg code of new keys (ciphered data starts): ");
- goto end;
- }
-
- if ( !(ssh_state->srv_hdr.flags & SSH_FLAG_PARSER_DONE)) {
- printf("Didn't detect the msg code of new keys (ciphered data starts): ");
- goto end;
- }
-
- if (!(AppLayerParserStateIssetFlag(f.alparser, APP_LAYER_PARSER_NO_INSPECTION))) {
- printf("detection not disabled: ");
- goto end;
- }
-
- result = 1;
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
-}
-
-/** \test Really long banner handling: bannel exactly 255 */
-static int SSHParserTest19(void)
-{
- int result = 0;
- Flow f;
- uint8_t sshbuf1[] = "SSH-";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
- uint8_t sshbuf2[] = "2.0-";
- uint32_t sshlen2 = sizeof(sshbuf2) - 1; // 8
- uint8_t sshbuf3[] = "abcdefghijklmnopqrstuvwxyz"
- "abcdefghijklmnopqrstuvwxyz"//60
- "abcdefghijklmnopqrstuvwxyz"
- "abcdefghijklmnopqrstuvwxyz"//112
- "abcdefghijklmnopqrstuvwxyz"
- "abcdefghijklmnopqrstuvwxyz"//164
- "abcdefghijklmnopqrstuvwxyz"
- "abcdefghijklmnopqrstuvwxyz"//216
- "abcdefghijklmnopqrstuvwxyz"//242
- "abcdefghijkl\r";//255
- uint32_t sshlen3 = sizeof(sshbuf3) - 1;
-
- uint8_t sshbuf4[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00};
- uint32_t sshlen4 = sizeof(sshbuf4);
- TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
-
- StreamTcpInitConfig(TRUE);
-
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOCLIENT, sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf2, sshlen2);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf3, sshlen3);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf4, sshlen4);
- if (r != 0) {
- printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
+ uint8_t sshbuf3[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00 };
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
- if (!(ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
+ memset(&tv, 0x00, sizeof(tv));
+
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
+
+ uint8_t* sshbufs[5] = {server1, sshbuf1, sshbuf2, server2, sshbuf3};
+ uint32_t sshlens[5] = {sizeof(server1) - 1, sizeof(sshbuf1) - 1, sizeof(sshbuf2) -1, sizeof(server2) - 1, sizeof(sshbuf3)};
+ bool sshdirs[5] = {true, false, false, true, false};
+
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
+
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
+
+ uint32_t seqcli = 2;
+ uint32_t seqsrv = 2;
+ for (int i=0; i<5; i++) {
+ if (sshdirs[i]) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seqsrv, sshbufs[i], sshlens[i]) == -1);
+ seqsrv += sshlens[i];
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
+ } else {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.client, seqcli, sshbufs[i], sshlens[i]) == -1);
+ seqcli += sshlens[i];
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.client, p, UPDATE_DIR_PACKET) < 0);
+ }
}
- if (ssh_state->srv_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_flags(tx, STREAM_TOCLIENT) != SshStateFinished );
- if (ssh_state->srv_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ FAIL_IF(!(AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_NO_INSPECTION)));
- char *name = SCCalloc(1, 256);
- if (name == NULL)
- goto end;
- strlcpy(name, (char *)sshbuf3, 256);
- name[strlen(name) - 1] = '\0'; // strip \r
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
+}
- if (strcmp((char*)ssh_state->srv_hdr.software_version, name) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+/** \test Really long banner handling: bannel exactly 255 */
+static int SSHParserTest19(void)
+{
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
+ TcpSession ssn;
+ Flow *f = NULL;
+ Packet *p = NULL;
- if (strncmp((char*)ssh_state->srv_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ uint8_t sshbuf1[] = "SSH-";
+ uint8_t sshbuf2[] = "2.0-";
+ uint8_t sshbuf3[] = "abcdefghijklmnopqrstuvwxyz"
+ "abcdefghijklmnopqrstuvwxyz"//60
+ "abcdefghijklmnopqrstuvwxyz"
+ "abcdefghijklmnopqrstuvwxyz"//112
+ "abcdefghijklmnopqrstuvwxyz"
+ "abcdefghijklmnopqrstuvwxyz"//164
+ "abcdefghijklmnopqrstuvwxyz"
+ "abcdefghijklmnopqrstuvwxyz"//216
+ "abcdefghijklmnopqrstuvwxyz"//242
+ "abcdefghijkl\r";//255
+ uint8_t sshbuf4[] = { 0x00, 0x00, 0x00, 0x03, 0x01, 21, 0x00};
- if ( !(ssh_state->srv_hdr.flags & SSH_FLAG_PARSER_DONE)) {
- printf("Didn't detect the msg code of new keys (ciphered data starts): ");
- goto end;
+ uint8_t* sshbufs[4] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4};
+ uint32_t sshlens[4] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3) - 1, sizeof(sshbuf4)};
+
+ memset(&tv, 0x00, sizeof(tv));
+
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
+
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
+
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
+
+ uint32_t seq = 2;
+ for (int i=0; i<4; i++) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
+ seq += sshlens[i];
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
}
- result = 1;
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_flags(tx, STREAM_TOCLIENT) != SshStateFinished );
+
+ sshbuf3[sizeof(sshbuf3) - 2] = 0;
+ FAIL_IF(SSHParserTestUtilCheck("2.0", (char *)sshbuf3, tx, STREAM_TOCLIENT));
+
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
}
/** \test Really long banner handling: banner exactly 255,
* followed by malformed record */
static int SSHParserTest20(void)
{
- int result = 0;
- Flow f;
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
+ TcpSession ssn;
+ Flow *f = NULL;
+ Packet *p = NULL;
+
uint8_t sshbuf1[] = "SSH-";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
uint8_t sshbuf2[] = "2.0-";
- uint32_t sshlen2 = sizeof(sshbuf2) - 1; // 8
uint8_t sshbuf3[] = "abcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyz"//60
"abcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyz"//216
"abcdefghijklmnopqrstuvwxyz"//242
"abcdefghijklm\r";//256
- uint32_t sshlen3 = sizeof(sshbuf3) - 1;
uint8_t sshbuf4[] = {'a','b','c','d','e','f', '\r',
0x00, 0x00, 0x00, 0x06, 0x01, 21, 0x00, 0x00, 0x00};
- uint32_t sshlen4 = sizeof(sshbuf4) - 1;
-
- TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
+ uint8_t* sshbufs[4] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4};
+ uint32_t sshlens[4] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3) - 1, sizeof(sshbuf4) - 1};
- StreamTcpInitConfig(TRUE);
+ memset(&tv, 0x00, sizeof(tv));
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOCLIENT, sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf2, sshlen2);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf3, sshlen3);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- SCLogDebug("chunk 4:");
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf4, sshlen4);
- if (r != 0) {
- printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
- if (!(ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
- if (ssh_state->srv_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
+ uint32_t seq = 2;
+ for (int i=0; i<4; i++) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
+ seq += sshlens[i];
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
}
- if (ssh_state->srv_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_flags(tx, STREAM_TOCLIENT) != SshStateFinished );
- if (strncmp((char*)ssh_state->srv_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ FAIL_IF(SSHParserTestUtilCheck("2.0", NULL, tx, STREAM_TOCLIENT));
- if ((ssh_state->srv_hdr.flags & SSH_FLAG_PARSER_DONE)) {
- printf("detected the msg code of new keys (ciphered data starts): ");
- goto end;
- }
- result = 1;
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
}
/** \test Fragmented banner handling: chunk has final part of bannel plus
* a record. */
static int SSHParserTest21(void)
{
- int result = 0;
- Flow f;
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
+ TcpSession ssn;
+ Flow *f = NULL;
+ Packet *p = NULL;
+
uint8_t sshbuf1[] = "SSH-";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
uint8_t sshbuf2[] = "2.0-";
- uint32_t sshlen2 = sizeof(sshbuf2) - 1; // 8
uint8_t sshbuf3[] = "abcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyz"//60
"abcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyz"//216
"abcdefghijklmnopqrstuvwxy";//241
- uint32_t sshlen3 = sizeof(sshbuf3) - 1;
uint8_t sshbuf4[] = {'l','i','b','s','s','h', '\r',
0x00, 0x00, 0x00, 0x06, 0x01, 21, 0x00, 0x00, 0x00};
- uint32_t sshlen4 = sizeof(sshbuf4) - 1;
- TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
- StreamTcpInitConfig(TRUE);
+ uint8_t* sshbufs[4] = {sshbuf1, sshbuf2, sshbuf3, sshbuf4};
+ uint32_t sshlens[4] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3) - 1, sizeof(sshbuf4)};
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOCLIENT, sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf2, sshlen2);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf3, sshlen3);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- SCLogDebug("chunk 4:");
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf4, sshlen4);
- if (r != 0) {
- printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
+ memset(&tv, 0x00, sizeof(tv));
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
- if (!(ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
- if (ssh_state->srv_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
- if (ssh_state->srv_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
+ uint32_t seq = 2;
+ for (int i=0; i<4; i++) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
+ seq += sshlens[i];
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
}
- if (strncmp((char*)ssh_state->srv_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_flags(tx, STREAM_TOCLIENT) != SshStateFinished );
- if ( !(ssh_state->srv_hdr.flags & SSH_FLAG_PARSER_DONE)) {
- printf("Didn't detect the msg code of new keys (ciphered data starts): ");
- goto end;
- }
+ FAIL_IF(SSHParserTestUtilCheck("2.0", NULL, tx, STREAM_TOCLIENT));
- result = 1;
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
}
/** \test Fragmented banner handling: chunk has final part of bannel plus
* a record. */
static int SSHParserTest22(void)
{
- int result = 0;
- Flow f;
+ TcpReassemblyThreadCtx *ra_ctx = NULL;
+ ThreadVars tv;
+ TcpSession ssn;
+ Flow *f = NULL;
+ Packet *p = NULL;
+
uint8_t sshbuf1[] = "SSH-";
- uint32_t sshlen1 = sizeof(sshbuf1) - 1;
uint8_t sshbuf2[] = "2.0-";
- uint32_t sshlen2 = sizeof(sshbuf2) - 1; // 8
uint8_t sshbuf3[] = {
'l', 'i', 'b', 's', 's', 'h', '\r', //7
0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, //150
0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, //200
-
- 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, //250
-
- 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x01, 21, 0x00, 0x00, 0x00, 0x00, //300
- };
- uint32_t sshlen3 = sizeof(sshbuf3) - 1;
- TcpSession ssn;
- AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-
- memset(&f, 0, sizeof(f));
- memset(&ssn, 0, sizeof(ssn));
- FLOW_INITIALIZE(&f);
- f.protoctx = (void *)&ssn;
- f.alproto = ALPROTO_SSH;
-
- StreamTcpInitConfig(TRUE);
-
- int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH,
- STREAM_TOCLIENT, sshbuf1, sshlen1);
- if (r != 0) {
- printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf2, sshlen2);
- if (r != 0) {
- printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
- r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT,
- sshbuf3, sshlen3);
- if (r != 0) {
- printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
-#if 0
- SCLogDebug("chunk 4:");
- r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SSH, STREAM_TOCLIENT, sshbuf4, sshlen4);
- if (r != 0) {
- printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
- goto end;
- }
-#endif
- SshState *ssh_state = f.alstate;
- if (ssh_state == NULL) {
- printf("no ssh state: ");
- goto end;
- }
-
- if (!(ssh_state->srv_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->srv_hdr.software_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
-
- if (ssh_state->srv_hdr.proto_version == NULL) {
- printf("Client version string not parsed: ");
- goto end;
- }
+ 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, //200
+
+ 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00, //250
+
+ 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x01, 17, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x01, 21, 0x00, 0x00, 0x00, 0x00, //300
+ };
+
+
+ uint8_t* sshbufs[3] = {sshbuf1, sshbuf2, sshbuf3};
+ uint32_t sshlens[3] = {sizeof(sshbuf1) - 1, sizeof(sshbuf2) - 1, sizeof(sshbuf3) - 1};
+
+ memset(&tv, 0x00, sizeof(tv));
+
+ StreamTcpUTInit(&ra_ctx);
+ StreamTcpUTInitInline();
+ StreamTcpUTSetupSession(&ssn);
+ StreamTcpUTSetupStream(&ssn.server, 1);
+ StreamTcpUTSetupStream(&ssn.client, 1);
+
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1234, 2222);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SSH;
+
+ p = PacketGetFromAlloc();
+ FAIL_IF(unlikely(p == NULL));
+ p->proto = IPPROTO_TCP;
+ p->flow = f;
+
+ uint32_t seq = 2;
+ for (int i=0; i<3; i++) {
+ FAIL_IF(StreamTcpUTAddSegmentWithPayload(&tv, ra_ctx, &ssn.server, seq, sshbufs[i], sshlens[i]) == -1);
+ seq += sshlens[i];
+ FAIL_IF(StreamTcpReassembleAppLayer(&tv, ra_ctx, &ssn, &ssn.server, p, UPDATE_DIR_PACKET) < 0);
+ }
- if (strncmp((char*)ssh_state->srv_hdr.proto_version, "2.0", strlen("2.0")) != 0) {
- printf("Client version string not parsed correctly: ");
- goto end;
- }
+ void *ssh_state = f->alstate;
+ FAIL_IF_NULL(ssh_state);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_flags(tx, STREAM_TOCLIENT) != SshStateFinished );
- if ( !(ssh_state->srv_hdr.flags & SSH_FLAG_PARSER_DONE)) {
- printf("Didn't detect the msg code of new keys (ciphered data starts): ");
- goto end;
- }
+ FAIL_IF(SSHParserTestUtilCheck("2.0", "libssh", tx, STREAM_TOCLIENT));
- result = 1;
-end:
- if (alp_tctx != NULL)
- AppLayerParserThreadCtxFree(alp_tctx);
- StreamTcpFreeConfig(TRUE);
- FLOW_DESTROY(&f);
- return result;
+ UTHFreePacket(p);
+ StreamTcpUTClearSession(&ssn);
+ StreamTcpUTDeinit(ra_ctx);
+ UTHFreeFlow(f);
+ PASS;
}
/** \test Send a version string in one chunk (client version str). */
goto end;
}
- SshState *ssh_state = f.alstate;
+ void *ssh_state = f.alstate;
if (ssh_state == NULL) {
printf("no ssh state: ");
goto end;
}
-
- if ( !(ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED)) {
- printf("Client version string not parsed: ");
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ if ( rs_ssh_tx_get_flags(tx, STREAM_TOSERVER) != SshStateBannerDone ) {
+ printf("Didn't detect the msg code of new keys (ciphered data starts): ");
goto end;
}
-
- if (ssh_state->cli_hdr.software_version) {
- printf("Client version string should not be parsed: ");
+ if (SSHParserTestUtilCheck("2.0", NULL, tx, STREAM_TOSERVER))
goto end;
- }
result = 1;
end:
STREAM_TOSERVER | STREAM_EOF, sshbuf, sshlen);
FAIL_IF(r != -1);
- SshState *ssh_state = f.alstate;
+ void *ssh_state = f.alstate;
FAIL_IF_NULL(ssh_state);
-
- FAIL_IF_NOT(!(ssh_state->cli_hdr.flags & SSH_FLAG_VERSION_PARSED));
- FAIL_IF(ssh_state->cli_hdr.software_version);
+ void * tx = rs_ssh_state_get_tx(ssh_state, 0);
+ FAIL_IF( rs_ssh_tx_get_flags(tx, STREAM_TOSERVER) == SshStateBannerDone );
+ const uint8_t *dummy = NULL;
+ uint32_t dummy_len = 0;
+ FAIL_IF (rs_ssh_tx_get_software(tx, &dummy, &dummy_len, STREAM_TOCLIENT) != 0);
AppLayerParserThreadCtxFree(alp_tctx);
StreamTcpFreeConfig(TRUE);