/* Copyright (C) 2007-2011 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free * Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * version 2 along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ /** * \file * * \author Anoop Saldanha * */ #include "suricata-common.h" #include "debug.h" #include "decode.h" #include "threads.h" #include "util-print.h" #include "util-pool.h" #include "stream-tcp-private.h" #include "stream-tcp-reassemble.h" #include "stream-tcp.h" #include "stream.h" #include "app-layer-protos.h" #include "app-layer-parser.h" #include "app-layer-ssl.h" #include "conf.h" #include "util-spm.h" #include "util-unittest.h" #include "util-debug.h" #include "flow-util.h" #include "flow-private.h" #include "util-byte.h" typedef struct SslConfig_ { int no_reassemble; } SslConfig; SslConfig ssl_config; /* SSLv3 record types */ #define SSLV3_CHANGE_CIPHER_SPEC 20 #define SSLV3_ALERT_PROTOCOL 21 #define SSLV3_HANDSHAKE_PROTOCOL 22 #define SSLV3_APPLICATION_PROTOCOL 23 /* SSLv3 handshake protocol types */ #define SSLV3_HS_HELLO_REQUEST 0 #define SSLV3_HS_CLIENT_HELLO 1 #define SSLV3_HS_SERVER_HELLO 2 #define SSLV3_HS_CERTIFICATE 11 #define SSLV3_HS_SERVER_KEY_EXCHANGE 12 #define SSLV3_HS_CERTIFICATE_REQUEST 13 #define SSLV3_HS_SERVER_HELLO_DONE 14 #define SSLV3_HS_CERTIFICATE_VERIFY 15 #define SSLV3_HS_CLIENT_KEY_EXCHANGE 16 #define SSLV3_HS_FINISHED 20 #define SSLV3_HS_CERTIFICATE_URL 21 #define SSLV3_HS_CERTIFICATE_STATUS 22 /* SSLv2 protocol message types */ #define SSLV2_MT_ERROR 0 #define SSLV2_MT_CLIENT_HELLO 1 #define SSLV2_MT_CLIENT_MASTER_KEY 2 #define SSLV2_MT_CLIENT_FINISHED 3 #define SSLV2_MT_SERVER_HELLO 4 #define SSLV2_MT_SERVER_VERIFY 5 #define SSLV2_MT_SERVER_FINISHED 6 #define SSLV2_MT_REQUEST_CERTIFICATE 7 #define SSLV2_MT_CLIENT_CERTIFICATE 8 #define SSLV3_RECORD_LEN 5 static void SSLParserReset(SSLState *ssl_state) { ssl_state->bytes_processed = 0; } static int SSLv3ParseHandshakeType(SSLState *ssl_state, uint8_t *input, uint32_t input_len) { uint8_t *initial_input = input; uint32_t parsed = 0; if (input_len == 0) { return 0; } switch (ssl_state->handshake_type) { case SSLV3_HS_CLIENT_HELLO: ssl_state->flags |= SSL_AL_FLAG_STATE_CLIENT_HELLO; switch (ssl_state->bytes_processed) { case 9: ssl_state->bytes_processed++; ssl_state->handshake_client_hello_ssl_version = *(input++) << 8; if (--input_len == 0) break; case 10: ssl_state->bytes_processed++; ssl_state->handshake_client_hello_ssl_version |= *(input++); if (--input_len == 0) break; } break; case SSLV3_HS_SERVER_HELLO: ssl_state->flags |= SSL_AL_FLAG_STATE_SERVER_HELLO; switch (ssl_state->bytes_processed) { case 9: ssl_state->bytes_processed++; ssl_state->handshake_server_hello_ssl_version = *(input++) << 8; if (--input_len == 0) break; case 10: ssl_state->bytes_processed++; ssl_state->handshake_server_hello_ssl_version |= *(input++); if (--input_len == 0) break; } break; case SSLV3_HS_SERVER_KEY_EXCHANGE: ssl_state->flags |= SSL_AL_FLAG_STATE_SERVER_KEYX; break; case SSLV3_HS_CLIENT_KEY_EXCHANGE: ssl_state->flags |= SSL_AL_FLAG_STATE_CLIENT_KEYX; break; case SSLV3_HS_HELLO_REQUEST: case SSLV3_HS_CERTIFICATE: case SSLV3_HS_CERTIFICATE_REQUEST: case SSLV3_HS_CERTIFICATE_VERIFY: case SSLV3_HS_FINISHED: case SSLV3_HS_CERTIFICATE_URL: case SSLV3_HS_CERTIFICATE_STATUS: break; default: break; } /* looks like we have another record */ parsed += (input - initial_input); if ((input_len + ssl_state->bytes_processed) >= ssl_state->record_length + SSLV3_RECORD_LEN) { uint32_t diff = ssl_state->record_length + SSLV3_RECORD_LEN - ssl_state->bytes_processed; parsed += diff; ssl_state->bytes_processed += diff; return parsed; /* we still don't have the entire record for the one we are * currently parsing */ } else { parsed += input_len; ssl_state->bytes_processed += input_len; return parsed; } } static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, uint8_t *input, uint32_t input_len) { uint8_t *initial_input = input; if (input_len == 0) { return 0; } switch (ssl_state->bytes_processed) { case 5: if (input_len >= 4) { ssl_state->handshake_type = *(input++); input += 3; input_len -= 4; ssl_state->bytes_processed += 4; break; } else { ssl_state->handshake_type = *(input++); ssl_state->bytes_processed++; if (--input_len == 0) break; } case 6: ssl_state->bytes_processed++; input++; if (--input_len == 0) break; case 7: ssl_state->bytes_processed++; input++; if (--input_len == 0) break; case 8: ssl_state->bytes_processed++; input++; if (--input_len == 0) break; } if (input_len == 0) return (input - initial_input); int retval = SSLv3ParseHandshakeType(ssl_state, input, input_len); if (retval == -1) { SCReturnInt(-1); } else { input += retval; return (input - initial_input); } } static int SSLv3ParseRecord(uint8_t direction, SSLState *ssl_state, uint8_t *input, uint32_t input_len) { uint8_t *initial_input = input; if (input_len == 0) { return 0; } switch (ssl_state->bytes_processed) { case 0: if (input_len >= 5) { /* toserver - 0 */ ssl_state->cur_content_type = input[0]; if (direction == 0) { ssl_state->client_content_type = input[0]; ssl_state->client_version = input[1] << 8; ssl_state->client_version |= input[2]; /* toclient - 1 */ } else { ssl_state->server_content_type = input[0]; ssl_state->server_version = input[1] << 8; ssl_state->server_version |= input[2]; } ssl_state->record_length = input[3] << 8; ssl_state->record_length |= input[4]; ssl_state->bytes_processed += SSLV3_RECORD_LEN; return SSLV3_RECORD_LEN; } else { ssl_state->cur_content_type = *input; if (direction == 0) { ssl_state->client_content_type = *(input++); } else { ssl_state->server_content_type = *(input++); } if (--input_len == 0) break; } case 1: if (direction == 0) { ssl_state->client_version = *(input++) << 8; } else { ssl_state->server_version = *(input++) << 8; } if (--input_len == 0) break; case 2: if (direction == 0) { ssl_state->client_version |= *(input++); } else { ssl_state->server_version |= *(input++); } if (--input_len == 0) break; case 3: ssl_state->record_length = *(input++) << 8; if (--input_len == 0) break; case 4: ssl_state->record_length |= *(input++); if (ssl_state->record_length <= SSLV3_RECORD_LEN) return -1; if (--input_len == 0) break; } /* switch (ssl_state->bytes_processed) */ ssl_state->bytes_processed += (input - initial_input); return (input - initial_input); } static int SSLv2ParseRecord(uint8_t direction, SSLState *ssl_state, uint8_t *input, uint32_t input_len) { uint8_t *initial_input = input; if (input_len == 0) { return 0; } if (ssl_state->record_lengths_length == 2) { switch (ssl_state->bytes_processed) { case 0: if (input_len >= ssl_state->record_lengths_length + 1) { ssl_state->record_length = (0x7f & input[0]) << 8 | input[1]; ssl_state->cur_content_type = input[2]; if (direction == 0) { ssl_state->client_content_type = input[2]; ssl_state->client_version = SSL_VERSION_2; } else { ssl_state->server_content_type = input[2]; ssl_state->server_version = SSL_VERSION_2; } ssl_state->bytes_processed += 3; return 3; } else { ssl_state->record_length = (0x7f & *(input++)) << 8; if (--input_len == 0) break; } case 1: ssl_state->record_length |= *(input++); if (--input_len == 0) break; case 2: ssl_state->cur_content_type = *input; if (direction == 0) { ssl_state->client_content_type = *(input++); ssl_state->client_version = SSL_VERSION_2; } else { ssl_state->server_content_type = *(input++); ssl_state->server_version = SSL_VERSION_2; } if (--input_len == 0) break; } /* switch (ssl_state->bytes_processed) */ } else { switch (ssl_state->bytes_processed) { case 0: if (input_len >= ssl_state->record_lengths_length + 1) { ssl_state->record_length = (0x3f & input[0]) << 8 | input[1]; ssl_state->cur_content_type = input[3]; if (direction == 0) { ssl_state->client_content_type = input[3]; ssl_state->client_version = SSL_VERSION_2; } else { ssl_state->server_content_type = input[3]; ssl_state->server_version = SSL_VERSION_2; } ssl_state->bytes_processed += 4; return 4; } else { ssl_state->record_length = (0x3f & *(input++)) << 8; if (--input_len == 0) break; } case 1: ssl_state->record_length |= *(input++); if (--input_len == 0) break; case 2: /* padding */ input++; if (--input_len == 0) break; case 3: ssl_state->cur_content_type = *input; if (direction == 0) { ssl_state->client_content_type = *(input++); ssl_state->client_version = SSL_VERSION_2; } else { ssl_state->server_content_type = *(input++); ssl_state->server_version = SSL_VERSION_2; } if (--input_len == 0) break; } /* switch (ssl_state->bytes_processed) */ } ssl_state->bytes_processed += (input - initial_input); return (input - initial_input); } static int SSLv2Decode(uint8_t direction, SSLState *ssl_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len) { int retval = 0; uint8_t *initial_input = input; if (ssl_state->bytes_processed == 0) { if (input[0] & 0x80) { ssl_state->record_lengths_length = 2; } else { ssl_state->record_lengths_length = 3; } } /* the + 1 because, we also read one extra byte inside SSLv2ParseRecord * to read the msg_type */ if (ssl_state->bytes_processed < (ssl_state->record_lengths_length + 1)) { retval = SSLv2ParseRecord(direction, ssl_state, input, input_len); if (retval == -1) { SCLogDebug("Error parsing SSLv2Header"); return -1; } else { input += retval; input_len -= retval; } } if (input_len == 0) { return (input - initial_input); } switch (ssl_state->cur_content_type) { case SSLV2_MT_ERROR: SCLogWarning(SC_ERR_ALPARSER, "SSLV2_MT_ERROR msg_type recived. " "Error encountered in establishing the sslv2 " "session, may be version"); break; case SSLV2_MT_CLIENT_HELLO: ssl_state->flags |= SSL_AL_FLAG_STATE_CLIENT_HELLO; ssl_state->flags |= SSL_AL_FLAG_SSL_CLIENT_HS; if (ssl_state->record_lengths_length == 3) { switch (ssl_state->bytes_processed) { case 4: if (input_len >= 6) { ssl_state->session_id_length = input[4] << 8; ssl_state->session_id_length |= input[5]; input += 6; input_len -= 6; ssl_state->bytes_processed += 6; if (ssl_state->session_id_length == 0) { ssl_state->flags |= SSL_AL_FLAG_SSL_NO_SESSION_ID; } break; } else { input++; ssl_state->bytes_processed++; if (--input_len == 0) break; } case 5: input++; ssl_state->bytes_processed++; if (--input_len == 0) break; case 6: input++; ssl_state->bytes_processed++; if (--input_len == 0) break; case 7: input++; ssl_state->bytes_processed++; if (--input_len == 0) break; case 8: ssl_state->session_id_length = *(input++) << 8; ssl_state->bytes_processed++; if (--input_len == 0) break; case 9: ssl_state->session_id_length |= *(input++); ssl_state->bytes_processed++; if (--input_len == 0) break; } /* switch (ssl_state->bytes_processed) */ /* ssl_state->record_lengths_length is 3 */ } else { switch (ssl_state->bytes_processed) { case 3: if (input_len >= 6) { ssl_state->session_id_length = input[4] << 8; ssl_state->session_id_length |= input[5]; input += 6; input_len -= 6; ssl_state->bytes_processed += 6; if (ssl_state->session_id_length == 0) { ssl_state->flags |= SSL_AL_FLAG_SSL_NO_SESSION_ID; } break; } else { input++; ssl_state->bytes_processed++; if (--input_len == 0) break; } case 4: input++; ssl_state->bytes_processed++; if (--input_len == 0) break; case 5: input++; ssl_state->bytes_processed++; if (--input_len == 0) break; case 6: input++; ssl_state->bytes_processed++; if (--input_len == 0) break; case 7: ssl_state->session_id_length = *(input++) << 8; ssl_state->bytes_processed++; if (--input_len == 0) break; case 8: ssl_state->session_id_length |= *(input++); ssl_state->bytes_processed++; if (--input_len == 0) break; } /* switch (ssl_state->bytes_processed) */ } /* else - if (ssl_state->record_lengths_length == 3) */ break; case SSLV2_MT_CLIENT_MASTER_KEY: if ( !(ssl_state->flags & SSL_AL_FLAG_SSL_CLIENT_HS)) { SCLogDebug("Client hello is not seen before master key " "message!!"); } ssl_state->flags |= SSL_AL_FLAG_SSL_CLIENT_MASTER_KEY; break; case SSLV2_MT_CLIENT_CERTIFICATE: if (direction == 1) { SCLogDebug("Incorrect SSL Record type sent in the toclient " "direction!"); } else { ssl_state->flags |= SSL_AL_FLAG_STATE_CLIENT_KEYX; } case SSLV2_MT_SERVER_VERIFY: case SSLV2_MT_SERVER_FINISHED: if (direction == 0 && !(ssl_state->cur_content_type & SSLV2_MT_CLIENT_CERTIFICATE)) { SCLogDebug("Incorrect SSL Record type sent in the toserver " "direction!"); } case SSLV2_MT_CLIENT_FINISHED: case SSLV2_MT_REQUEST_CERTIFICATE: /* both ways hello seen */ if ((ssl_state->flags & SSL_AL_FLAG_SSL_CLIENT_HS) && (ssl_state->flags & SSL_AL_FLAG_SSL_SERVER_HS)) { if (direction == 0) { if (ssl_state->flags & SSL_AL_FLAG_SSL_NO_SESSION_ID) { ssl_state->flags |= SSL_AL_FLAG_SSL_CLIENT_SSN_ENCRYPTED; SCLogDebug("SSLv2 client side has started the encryption"); } else if (ssl_state->flags & SSL_AL_FLAG_SSL_CLIENT_MASTER_KEY) { ssl_state->flags |= SSL_AL_FLAG_SSL_CLIENT_SSN_ENCRYPTED; SCLogDebug("SSLv2 client side has started the encryption"); } } else { ssl_state->flags |= SSL_AL_FLAG_SSL_SERVER_SSN_ENCRYPTED; SCLogDebug("SSLv2 Server side has started the encryption"); } if ((ssl_state->flags & SSL_AL_FLAG_SSL_CLIENT_SSN_ENCRYPTED) && (ssl_state->flags & SSL_AL_FLAG_SSL_SERVER_SSN_ENCRYPTED)) { pstate->flags |= APP_LAYER_PARSER_DONE; pstate->flags |= APP_LAYER_PARSER_NO_INSPECTION; if (ssl_config.no_reassemble == 1) pstate->flags |= APP_LAYER_PARSER_NO_REASSEMBLY; SCLogDebug("SSLv2 No reassembly & inspection has been set"); } } break; case SSLV2_MT_SERVER_HELLO: ssl_state->flags |= SSL_AL_FLAG_STATE_SERVER_HELLO; ssl_state->flags |= SSL_AL_FLAG_SSL_SERVER_HS; break; } if (input_len + ssl_state->bytes_processed >= (ssl_state->record_length + ssl_state->record_lengths_length)) { /* looks like we have another record after this*/ uint32_t diff = ssl_state->record_length + ssl_state->record_lengths_length + - ssl_state->bytes_processed; input += diff; SSLParserReset(ssl_state); return (input - initial_input); /* we still don't have the entire record for the one we are * currently parsing */ } else { input += input_len; ssl_state->bytes_processed += input_len; return (input - initial_input); } } static int SSLv3Decode(uint8_t direction, SSLState *ssl_state, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len) { int retval = 0; uint32_t parsed = 0; if (ssl_state->bytes_processed < SSLV3_RECORD_LEN) { retval = SSLv3ParseRecord(direction, ssl_state, input, input_len); if (retval == -1) { SCLogDebug("Error parsing SSLv3Header"); return -1; } else { parsed += retval; input_len -= retval; } } if (input_len == 0) { return parsed; } switch (ssl_state->cur_content_type) { /* we don't need any data from these types */ case SSLV3_CHANGE_CIPHER_SPEC: ssl_state->flags |= SSL_AL_FLAG_CHANGE_CIPHER_SPEC; if (direction) ssl_state->flags |= SSL_AL_FLAG_SERVER_CHANGE_CIPHER_SPEC; else ssl_state->flags |= SSL_AL_FLAG_CLIENT_CHANGE_CIPHER_SPEC; break; case SSLV3_ALERT_PROTOCOL: break; case SSLV3_APPLICATION_PROTOCOL: if ((ssl_state->flags & SSL_AL_FLAG_CLIENT_CHANGE_CIPHER_SPEC) && (ssl_state->flags & SSL_AL_FLAG_SERVER_CHANGE_CIPHER_SPEC)) { /* set flags */ pstate->flags |= APP_LAYER_PARSER_DONE; pstate->flags |= APP_LAYER_PARSER_NO_INSPECTION; if (ssl_config.no_reassemble == 1) pstate->flags |= APP_LAYER_PARSER_NO_REASSEMBLY; } case SSLV3_HANDSHAKE_PROTOCOL: if (ssl_state->flags & SSL_AL_FLAG_CHANGE_CIPHER_SPEC) break; retval = SSLv3ParseHandshakeProtocol(ssl_state, input + parsed, input_len); if (retval == -1) { SCLogDebug("Error parsing SSLv3.x. Let's get outta here"); return -1; } else { parsed += retval; input_len -= retval; if (ssl_state->bytes_processed == ssl_state->record_length + SSLV3_RECORD_LEN) { SSLParserReset(ssl_state); } return parsed; } break; default: SCLogDebug("Bad ssl record type"); return -1; } if (input_len + ssl_state->bytes_processed >= ssl_state->record_length + SSLV3_RECORD_LEN) { /* looks like we have another record */ uint32_t diff = ssl_state->record_length + SSLV3_RECORD_LEN - ssl_state->bytes_processed; parsed += diff; SSLParserReset(ssl_state); return parsed; /* we still don't have the entire record for the one we are * currently parsing */ } else { parsed += input_len; ssl_state->bytes_processed += input_len; return parsed; } } /** * \internal * \brief SSLv2, SSLv23, SSLv3, TLSv1.1, TLSv1.2, TLSv1.3 parser. * * On parsing error, this should be the only function that should reset * the parser state, to avoid multiple functions in the chain reseting * the parser state. * * \param direction 0 for toserver, 1 for toclient. * \param alstate Pointer to the state. * \param pstate Application layer parser state for this session. * \param input Pointer the received input data. * \param input_len Length in bytes of the received data. * \param output Pointer to the list of parsed output elements. * * \todo On reaching an inconsistent state, check if the input has * another new record, instead of just returning after the reset * * \retval >=0 On success. */ static int SSLDecode(uint8_t direction, void *alstate, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len) { SSLState *ssl_state = (SSLState *)alstate; int retval = 0; uint8_t counter = 0; /* if we have more than one record */ while (input_len) { if (counter++ == 30) { SCLogDebug("Looks like we have looped quite a bit. Reset state " "and get out of here"); SSLParserReset(ssl_state); return 0; } /* ssl_state->bytes_processed is either ways it is either 0 for a * fresh record or positive to indicate a record currently being * parsed */ switch (ssl_state->bytes_processed) { /* fresh record */ case 0: /* only SSLv2, has one of the top 2 bits set */ if (input[0] & 0x80 || input[0] & 0x40) { SCLogDebug("SSLv2 detected"); ssl_state->cur_ssl_version = SSL_VERSION_2; retval = SSLv2Decode(direction, ssl_state, pstate, input, input_len); if (retval == -1) { SCLogDebug("Error parsing SSLv2.x. Reseting parser " "state. Let's get outta here"); SSLParserReset(ssl_state); return 0; } else { input_len -= retval; input += retval; } } else { SCLogDebug("SSLv3.x detected"); retval = SSLv3Decode(direction, ssl_state, pstate, input, input_len); if (retval == -1) { SCLogDebug("Error parsing SSLv3.x. Reseting parser " "state. Let's get outta here"); SSLParserReset(ssl_state); return 0; } else { input_len -= retval; input += retval; } } break; default: /* we would have established by now if we are dealing with * SSLv2 or above */ if (ssl_state->cur_ssl_version == SSL_VERSION_2) { SCLogDebug("Continuing parsing SSLv2 record from where we " "previously left off"); retval = SSLv2Decode(direction, ssl_state, pstate, input, input_len); if (retval == -1) { SCLogDebug("Error parsing SSLv2.x. Reseting parser " "state. Let's get outta here"); SSLParserReset(ssl_state); return 0; } else { input_len -= retval; input += retval; } } else { SCLogDebug("Continuing parsing SSLv3.x record from where we " "previously left off"); retval = SSLv3Decode(direction, ssl_state, pstate, input, input_len); if (retval == -1) { SCLogDebug("Error parsing SSLv3.x. Reseting parser " "state. Let's get outta here"); SSLParserReset(ssl_state); return 0; } else { input_len -= retval; input += retval; } } break; } /* switch (ssl_state->bytes_processed) */ } /* while (input_len) */ return 1; } int SSLParseClientRecord(Flow *f, void *alstate, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, void *local_data, AppLayerParserResult *output) { return SSLDecode(0 /* toserver */, alstate, pstate, input, input_len); } int SSLParseServerRecord(Flow *f, void *alstate, AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, void *local_data, AppLayerParserResult *output) { return SSLDecode(1 /* toclient */, alstate, pstate, input, input_len); } /** * \internal * \brief Function to allocate the SSL state memory. */ void *SSLStateAlloc(void) { void *ssl_state = SCMalloc(sizeof(SSLState)); if (ssl_state == NULL) return NULL; memset(ssl_state, 0, sizeof(SSLState)); return ssl_state; } /** * \internal * \brief Function to free the SSL state memory. */ void SSLStateFree(void *p) { SCFree(p); return; } /** * \brief Function to register the SSL protocol parser and other functions */ void RegisterSSLParsers(void) { /** SSLv2 and SSLv23*/ AlpProtoAdd(&alp_proto_ctx, IPPROTO_TCP, ALPROTO_TLS, "|01 00 02|", 5, 2, STREAM_TOSERVER); /* subsection - SSLv2 style record by client, but informing the server the max * version it supports */ /* Updated by Anoop Saldanha. Disabled it for now. We'll get back to it * after some tests */ //AlpProtoAdd(&alp_proto_ctx, IPPROTO_TCP, ALPROTO_TLS, "|01 03 00|", 5, 2, STREAM_TOSERVER); //AlpProtoAdd(&alp_proto_ctx, IPPROTO_TCP, ALPROTO_TLS, "|00 02|", 7, 5, STREAM_TOCLIENT); /** SSLv3 */ AlpProtoAdd(&alp_proto_ctx, IPPROTO_TCP, ALPROTO_TLS, "|01 03 00|", 3, 0, STREAM_TOSERVER); AlpProtoAdd(&alp_proto_ctx, IPPROTO_TCP, ALPROTO_TLS, "|16 03 00|", 3, 0, STREAM_TOSERVER); /* client hello */ /** TLSv1 */ AlpProtoAdd(&alp_proto_ctx, IPPROTO_TCP, ALPROTO_TLS, "|01 03 01|", 3, 0, STREAM_TOSERVER); AlpProtoAdd(&alp_proto_ctx, IPPROTO_TCP, ALPROTO_TLS, "|16 03 01|", 3, 0, STREAM_TOSERVER); /* client hello */ /** TLSv1.1 */ AlpProtoAdd(&alp_proto_ctx, IPPROTO_TCP, ALPROTO_TLS, "|01 03 02|", 3, 0, STREAM_TOSERVER); AlpProtoAdd(&alp_proto_ctx, IPPROTO_TCP, ALPROTO_TLS, "|16 03 02|", 3, 0, STREAM_TOSERVER); /* client hello */ /** TLSv1.2 */ AlpProtoAdd(&alp_proto_ctx, IPPROTO_TCP, ALPROTO_TLS, "|01 03 03|", 3, 0, STREAM_TOSERVER); AlpProtoAdd(&alp_proto_ctx, IPPROTO_TCP, ALPROTO_TLS, "|16 03 03|", 3, 0, STREAM_TOSERVER); /* client hello */ AppLayerRegisterProto("tls", ALPROTO_TLS, STREAM_TOSERVER, SSLParseClientRecord); AppLayerRegisterProto("tls", ALPROTO_TLS, STREAM_TOCLIENT, SSLParseServerRecord); AppLayerRegisterStateFuncs(ALPROTO_TLS, SSLStateAlloc, SSLStateFree); /* Get the value of no reassembly option from the config file */ if (ConfGetBool("tls.no_reassemble", &ssl_config.no_reassemble) != 1) ssl_config.no_reassemble = 1; return; } /***************************************Unittests******************************/ #ifdef UNITTESTS /** *\test Send a get request in one chunk. */ static int SSLParserTest01(void) { int result = 1; Flow f; uint8_t tlsbuf[] = { 0x16, 0x03, 0x01 }; uint32_t tlslen = sizeof(tlsbuf); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER | STREAM_EOF, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x16, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != TLS_VERSION_10) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, ssl_state->client_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** \test Send a get request in two chunks. */ static int SSLParserTest02(void) { int result = 1; Flow f; uint8_t tlsbuf1[] = { 0x16 }; uint32_t tlslen1 = sizeof(tlsbuf1); uint8_t tlsbuf2[] = { 0x03, 0x01 }; uint32_t tlslen2 = sizeof(tlsbuf2); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf1, tlslen1); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf2, tlslen2); if (r != 0) { printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x16, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != TLS_VERSION_10) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, ssl_state->client_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** \test Send a get request in three chunks. */ static int SSLParserTest03(void) { int result = 1; Flow f; uint8_t tlsbuf1[] = { 0x16 }; uint32_t tlslen1 = sizeof(tlsbuf1); uint8_t tlsbuf2[] = { 0x03 }; uint32_t tlslen2 = sizeof(tlsbuf2); uint8_t tlsbuf3[] = { 0x01 }; uint32_t tlslen3 = sizeof(tlsbuf3); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf1, tlslen1); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf2, tlslen2); if (r != 0) { printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf3, tlslen3); if (r != 0) { printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x16, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != TLS_VERSION_10) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, ssl_state->client_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** \test Send a get request in three chunks + more data. */ static int SSLParserTest04(void) { int result = 1; Flow f; uint8_t tlsbuf1[] = { 0x16 }; uint32_t tlslen1 = sizeof(tlsbuf1); uint8_t tlsbuf2[] = { 0x03 }; uint32_t tlslen2 = sizeof(tlsbuf2); uint8_t tlsbuf3[] = { 0x01 }; uint32_t tlslen3 = sizeof(tlsbuf3); uint8_t tlsbuf4[] = { 0x01, 0x00, 0x00, 0xad, 0x03, 0x01 }; uint32_t tlslen4 = sizeof(tlsbuf4); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf1, tlslen1); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf2, tlslen2); if (r != 0) { printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf3, tlslen3); if (r != 0) { printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf4, tlslen4); if (r != 0) { printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x16, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != TLS_VERSION_10) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, ssl_state->client_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } #if 0 /** \test Test the setting up of no reassembly and no payload inspection flag * after detection of the TLS handshake completion */ static int SSLParserTest05(void) { int result = 1; Flow f; uint8_t tlsbuf[] = { 0x16, 0x03, 0x01, 0x00, 0x01 }; uint32_t tlslen = sizeof(tlsbuf); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOCLIENT, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } tlsbuf[0] = 0x14; r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } tlsbuf[0] = 0x14; r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOCLIENT, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } tlsbuf[0] = 0x17; r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x17) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x17, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != TLS_VERSION_10) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, ssl_state->client_version); result = 0; goto end; } AppLayerParserStateStore *parser_state_store = (AppLayerParserStateStore *) ssn.alparser; AppLayerParserState *parser_state = &parser_state_store->to_server; if (!(parser_state->flags & APP_LAYER_PARSER_NO_INSPECTION) && !(ssn.client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) && !(ssn.server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) { printf("The flags should be set\n"); result = 0; goto end; } if (!(f.flags & FLOW_NOPAYLOAD_INSPECTION)) { printf("The flags should be set\n"); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } #endif #if 0 /** \test Test the setting up of no reassembly and no payload inspection flag * after detection of the valid TLS handshake completion, the rouge * 0x17 packet will not be considered in the detection process */ static int SSLParserTest06(void) { int result = 1; Flow f; uint8_t tlsbuf[] = { 0x16, 0x03, 0x01, 0x00, 0x01 }; uint32_t tlslen = sizeof(tlsbuf); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOCLIENT, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } tlsbuf[0] = 0x14; r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } tlsbuf[0] = 0x17; r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x17) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x17, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != TLS_VERSION_10) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, ssl_state->client_version); result = 0; goto end; } AppLayerParserStateStore *parser_state_store = (AppLayerParserStateStore *) ssn.alparser; AppLayerParserState *parser_state = &parser_state_store->to_server; if ((parser_state->flags & APP_LAYER_PARSER_NO_INSPECTION) || (ssn.client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) || (ssn.server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) { printf("The flags should not be set\n"); result = 0; goto end; } tlsbuf[0] = 0x14; r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOCLIENT, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } tlsbuf[0] = 0x17; r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } if (!(parser_state->flags & APP_LAYER_PARSER_NO_INSPECTION) && !(ssn.client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) && !(ssn.server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) { printf("The flags should be set\n"); result = 0; goto end; } if (!(f.flags & FLOW_NOPAYLOAD_INSPECTION)) { printf("The flags should be set\n"); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } #endif /** \test multimsg test */ static int SSLParserMultimsgTest01(void) { int result = 1; Flow f; /* 3 msgs */ uint8_t tlsbuf1[] = { 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0xd3, 0x6f, 0x1f, 0x63, 0x82, 0x8d, 0x75, 0x77, 0x8c, 0x91, 0xbc, 0xa1, 0x3d, 0xbb, 0xe1, 0xb5, 0xd3, 0x31, 0x92, 0x59, 0x2b, 0x2c, 0x43, 0x96, 0xa3, 0xaa, 0x23, 0x92, 0xd0, 0x91, 0x2a, 0x5e, 0x10, 0x5b, 0xc8, 0xc1, 0xe2, 0xd3, 0x5c, 0x8b, 0x8c, 0x91, 0x9e, 0xc2, 0xf2, 0x9c, 0x3c, 0x4f, 0x37, 0x1e, 0x20, 0x5e, 0x33, 0xd5, 0xf0, 0xd6, 0xaf, 0x89, 0xf5, 0xcc, 0xb2, 0xcf, 0xc1, 0x60, 0x3a, 0x46, 0xd5, 0x4e, 0x2a, 0xb6, 0x6a, 0xb9, 0xfc, 0x32, 0x8b, 0xe0, 0x6e, 0xa0, 0xed, 0x25, 0xa0, 0xa4, 0x82, 0x81, 0x73, 0x90, 0xbf, 0xb5, 0xde, 0xeb, 0x51, 0x8d, 0xde, 0x5b, 0x6f, 0x94, 0xee, 0xba, 0xe5, 0x69, 0xfa, 0x1a, 0x80, 0x30, 0x54, 0xeb, 0x12, 0x01, 0xb9, 0xfe, 0xbf, 0x82, 0x95, 0x01, 0x7b, 0xb0, 0x97, 0x14, 0xc2, 0x06, 0x3c, 0x69, 0xfb, 0x1c, 0x66, 0x47, 0x17, 0xd9, 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0xf6, 0xbc, 0x0d, 0x6f, 0xe8, 0xbb, 0xaa, 0xbf, 0x14, 0xeb, 0x7b, 0xcc, 0x6c, 0x28, 0xb0, 0xfc, 0xa6, 0x01, 0x2a, 0x97, 0x96, 0x17, 0x5e, 0xe8, 0xb4, 0x4e, 0x78, 0xc9, 0x04, 0x65, 0x53, 0xb6, 0x93, 0x3d, 0xeb, 0x44, 0xee, 0x86, 0xf9, 0x80, 0x49, 0x45, 0x21, 0x34, 0xd1, 0xee, 0xc8, 0x9c }; uint32_t tlslen1 = sizeof(tlsbuf1); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf1, tlslen1); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x16, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != TLS_VERSION_10) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, ssl_state->client_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** \test multimsg test server */ static int SSLParserMultimsgTest02(void) { int result = 1; Flow f; /* 3 msgs */ uint8_t tlsbuf1[] = { 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0xd3, 0x6f, 0x1f, 0x63, 0x82, 0x8d, 0x75, 0x77, 0x8c, 0x91, 0xbc, 0xa1, 0x3d, 0xbb, 0xe1, 0xb5, 0xd3, 0x31, 0x92, 0x59, 0x2b, 0x2c, 0x43, 0x96, 0xa3, 0xaa, 0x23, 0x92, 0xd0, 0x91, 0x2a, 0x5e, 0x10, 0x5b, 0xc8, 0xc1, 0xe2, 0xd3, 0x5c, 0x8b, 0x8c, 0x91, 0x9e, 0xc2, 0xf2, 0x9c, 0x3c, 0x4f, 0x37, 0x1e, 0x20, 0x5e, 0x33, 0xd5, 0xf0, 0xd6, 0xaf, 0x89, 0xf5, 0xcc, 0xb2, 0xcf, 0xc1, 0x60, 0x3a, 0x46, 0xd5, 0x4e, 0x2a, 0xb6, 0x6a, 0xb9, 0xfc, 0x32, 0x8b, 0xe0, 0x6e, 0xa0, 0xed, 0x25, 0xa0, 0xa4, 0x82, 0x81, 0x73, 0x90, 0xbf, 0xb5, 0xde, 0xeb, 0x51, 0x8d, 0xde, 0x5b, 0x6f, 0x94, 0xee, 0xba, 0xe5, 0x69, 0xfa, 0x1a, 0x80, 0x30, 0x54, 0xeb, 0x12, 0x01, 0xb9, 0xfe, 0xbf, 0x82, 0x95, 0x01, 0x7b, 0xb0, 0x97, 0x14, 0xc2, 0x06, 0x3c, 0x69, 0xfb, 0x1c, 0x66, 0x47, 0x17, 0xd9, 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0xf6, 0xbc, 0x0d, 0x6f, 0xe8, 0xbb, 0xaa, 0xbf, 0x14, 0xeb, 0x7b, 0xcc, 0x6c, 0x28, 0xb0, 0xfc, 0xa6, 0x01, 0x2a, 0x97, 0x96, 0x17, 0x5e, 0xe8, 0xb4, 0x4e, 0x78, 0xc9, 0x04, 0x65, 0x53, 0xb6, 0x93, 0x3d, 0xeb, 0x44, 0xee, 0x86, 0xf9, 0x80, 0x49, 0x45, 0x21, 0x34, 0xd1, 0xee, 0xc8, 0x9c }; uint32_t tlslen1 = sizeof(tlsbuf1); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOCLIENT, tlsbuf1, tlslen1); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->server_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x16, ssl_state->server_content_type); result = 0; goto end; } if (ssl_state->server_version != 0x0301) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", 0x0301, ssl_state->server_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** * \test Test the detection of SSLv3 protocol from the given packet */ static int SSLParserTest07(void) { int result = 1; Flow f; uint8_t tlsbuf[] = { 0x16, 0x03, 0x00, 0x00, 0x6f, 0x01, 0x00, 0x00, 0x6b, 0x03, 0x00, 0x4b, 0x2f, 0xdc, 0x4e, 0xe6, 0x95, 0xf1, 0xa0, 0xc7, 0xcf, 0x8e, 0xf6, 0xeb, 0x22, 0x6d, 0xce, 0x9c, 0x44, 0xfb, 0xc8, 0xa0, 0x44, 0x31, 0x15, 0x4c, 0xe9, 0x97, 0xa7, 0xa1, 0xfe, 0xea, 0xcc, 0x20, 0x4b, 0x5d, 0xfb, 0xa5, 0x63, 0x7a, 0x73, 0x95, 0xf7, 0xff, 0x42, 0xac, 0x8f, 0x46, 0xed, 0xe4, 0xb1, 0x35, 0x35, 0x78, 0x1a, 0x9d, 0xaf, 0x10, 0xc5, 0x52, 0xf3, 0x7b, 0xfb, 0xb5, 0xe9, 0xa8, 0x00, 0x24, 0x00, 0x88, 0x00, 0x87, 0x00, 0x39, 0x00, 0x38, 0x00, 0x84, 0x00, 0x35, 0x00, 0x45, 0x00, 0x44, 0x00, 0x33, 0x00, 0x32, 0x00, 0x96, 0x00, 0x41, 0x00, 0x2f, 0x00, 0x16, 0x00, 0x13, 0xfe, 0xff, 0x00, 0x0a, 0x00, 0x02, 0x01, 0x00 }; uint32_t tlslen = sizeof(tlsbuf); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x17, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->client_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } #if 0 /** \test Test the setting up of no reassembly and no payload inspection flag * after detection of the SSLv3 handshake completion */ static int SSLParserTest08(void) { int result = 1; Flow f; uint8_t tlsbuf[] = { 0x16, 0x03, 0x00, 0x00, 0x01 }; uint32_t tlslen = sizeof(tlsbuf); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOCLIENT, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } tlsbuf[0] = 0x14; r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } tlsbuf[0] = 0x14; r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOCLIENT, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } tlsbuf[0] = 0x17; r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf, tlslen); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x17) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x17, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->client_version); result = 0; goto end; } AppLayerParserStateStore *parser_state_store = (AppLayerParserStateStore *) ssn.alparser; AppLayerParserState *parser_state = &parser_state_store->to_server; if (!(parser_state->flags & APP_LAYER_PARSER_NO_INSPECTION) && !(ssn.client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) && !(ssn.server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) { printf("The flags should be set\n"); result = 0; goto end; } if (!(f.flags & FLOW_NOPAYLOAD_INSPECTION)) { printf("The flags should be set\n"); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } #endif /** * \test Tests the parser for handling fragmented records. */ static int SSLParserTest09(void) { int result = 1; Flow f; uint8_t buf1[] = { 0x16, }; uint32_t buf1_len = sizeof(buf1); uint8_t buf2[] = { 0x03, 0x00, 0x00, 0x6f, 0x01, 0x00, 0x00, 0x6b, 0x03, 0x00, 0x4b, 0x2f, 0xdc, 0x4e, 0xe6, 0x95, 0xf1, 0xa0, 0xc7, 0xcf, 0x8e, 0xf6, 0xeb, 0x22, 0x6d, 0xce, 0x9c, 0x44, 0xfb, 0xc8, 0xa0, 0x44, 0x31, 0x15, 0x4c, 0xe9, 0x97, 0xa7, 0xa1, 0xfe, 0xea, 0xcc, 0x20, 0x4b, 0x5d, 0xfb, 0xa5, 0x63, 0x7a, 0x73, 0x95, 0xf7, 0xff, 0x42, 0xac, 0x8f, 0x46, 0xed, 0xe4, 0xb1, 0x35, 0x35, 0x78, 0x1a, 0x9d, 0xaf, 0x10, 0xc5, 0x52, 0xf3, 0x7b, 0xfb, 0xb5, 0xe9, 0xa8, 0x00, 0x24, 0x00, 0x88, 0x00, 0x87, 0x00, 0x39, 0x00, 0x38, 0x00, 0x84, 0x00, 0x35, 0x00, 0x45, 0x00, 0x44, 0x00, 0x33, 0x00, 0x32, 0x00, 0x96, 0x00, 0x41, 0x00, 0x2f, 0x00, 0x16, 0x00, 0x13, 0xfe, 0xff, 0x00, 0x0a, 0x00, 0x02, 0x01, 0x00 }; uint32_t buf2_len = sizeof(buf2); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf2, buf2_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x17, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->client_version); result = 0; goto end; } if (ssl_state->handshake_client_hello_ssl_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->handshake_client_hello_ssl_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** * \test Tests the parser for handling fragmented records. */ static int SSLParserTest10(void) { int result = 1; Flow f; uint8_t buf1[] = { 0x16, 0x03, }; uint32_t buf1_len = sizeof(buf1); uint8_t buf2[] = { 0x00, 0x00, 0x6f, 0x01, 0x00, 0x00, 0x6b, 0x03, 0x00, 0x4b, 0x2f, 0xdc, 0x4e, 0xe6, 0x95, 0xf1, 0xa0, 0xc7, 0xcf, 0x8e, 0xf6, 0xeb, 0x22, 0x6d, 0xce, 0x9c, 0x44, 0xfb, 0xc8, 0xa0, 0x44, 0x31, 0x15, 0x4c, 0xe9, 0x97, 0xa7, 0xa1, 0xfe, 0xea, 0xcc, 0x20, 0x4b, 0x5d, 0xfb, 0xa5, 0x63, 0x7a, 0x73, 0x95, 0xf7, 0xff, 0x42, 0xac, 0x8f, 0x46, 0xed, 0xe4, 0xb1, 0x35, 0x35, 0x78, 0x1a, 0x9d, 0xaf, 0x10, 0xc5, 0x52, 0xf3, 0x7b, 0xfb, 0xb5, 0xe9, 0xa8, 0x00, 0x24, 0x00, 0x88, 0x00, 0x87, 0x00, 0x39, 0x00, 0x38, 0x00, 0x84, 0x00, 0x35, 0x00, 0x45, 0x00, 0x44, 0x00, 0x33, 0x00, 0x32, 0x00, 0x96, 0x00, 0x41, 0x00, 0x2f, 0x00, 0x16, 0x00, 0x13, 0xfe, 0xff, 0x00, 0x0a, 0x00, 0x02, 0x01, 0x00 }; uint32_t buf2_len = sizeof(buf2); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf2, buf2_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x17, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->client_version); result = 0; goto end; } if (ssl_state->handshake_client_hello_ssl_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->handshake_client_hello_ssl_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** * \test Tests the parser for handling fragmented records. */ static int SSLParserTest11(void) { int result = 1; Flow f; uint8_t buf1[] = { 0x16, 0x03, 0x00, 0x00, 0x6f, 0x01, }; uint32_t buf1_len = sizeof(buf1); uint8_t buf2[] = { 0x00, 0x00, 0x6b, 0x03, 0x00, 0x4b, 0x2f, 0xdc, 0x4e, 0xe6, 0x95, 0xf1, 0xa0, 0xc7, 0xcf, 0x8e, 0xf6, 0xeb, 0x22, 0x6d, 0xce, 0x9c, 0x44, 0xfb, 0xc8, 0xa0, 0x44, 0x31, 0x15, 0x4c, 0xe9, 0x97, 0xa7, 0xa1, 0xfe, 0xea, 0xcc, 0x20, 0x4b, 0x5d, 0xfb, 0xa5, 0x63, 0x7a, 0x73, 0x95, 0xf7, 0xff, 0x42, 0xac, 0x8f, 0x46, 0xed, 0xe4, 0xb1, 0x35, 0x35, 0x78, 0x1a, 0x9d, 0xaf, 0x10, 0xc5, 0x52, 0xf3, 0x7b, 0xfb, 0xb5, 0xe9, 0xa8, 0x00, 0x24, 0x00, 0x88, 0x00, 0x87, 0x00, 0x39, 0x00, 0x38, 0x00, 0x84, 0x00, 0x35, 0x00, 0x45, 0x00, 0x44, 0x00, 0x33, 0x00, 0x32, 0x00, 0x96, 0x00, 0x41, 0x00, 0x2f, 0x00, 0x16, 0x00, 0x13, 0xfe, 0xff, 0x00, 0x0a, 0x00, 0x02, 0x01, 0x00 }; uint32_t buf2_len = sizeof(buf2); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf2, buf2_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x17, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->client_version); result = 0; goto end; } if (ssl_state->handshake_client_hello_ssl_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->handshake_client_hello_ssl_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** * \test Tests the parser for handling fragmented records. */ static int SSLParserTest12(void) { int result = 1; Flow f; uint8_t buf1[] = { 0x16, 0x03, 0x00, 0x00, 0x6f, 0x01, }; uint32_t buf1_len = sizeof(buf1); uint8_t buf2[] = { 0x00, 0x00, 0x6b, }; uint32_t buf2_len = sizeof(buf2); uint8_t buf3[] = { 0x03, 0x00, 0x4b, 0x2f, 0xdc, 0x4e, 0xe6, 0x95, 0xf1, 0xa0, 0xc7, 0xcf, 0x8e, 0xf6, 0xeb, 0x22, 0x6d, 0xce, 0x9c, 0x44, 0xfb, 0xc8, 0xa0, 0x44, 0x31, 0x15, 0x4c, 0xe9, 0x97, 0xa7, 0xa1, 0xfe, 0xea, 0xcc, 0x20, 0x4b, 0x5d, 0xfb, 0xa5, 0x63, 0x7a, 0x73, 0x95, 0xf7, 0xff, 0x42, 0xac, 0x8f, 0x46, 0xed, 0xe4, 0xb1, 0x35, 0x35, 0x78, 0x1a, 0x9d, 0xaf, 0x10, 0xc5, 0x52, 0xf3, 0x7b, 0xfb, 0xb5, 0xe9, 0xa8, 0x00, 0x24, 0x00, 0x88, 0x00, 0x87, 0x00, 0x39, 0x00, 0x38, 0x00, 0x84, 0x00, 0x35, 0x00, 0x45, 0x00, 0x44, 0x00, 0x33, 0x00, 0x32, 0x00, 0x96, 0x00, 0x41, 0x00, 0x2f, 0x00, 0x16, 0x00, 0x13, 0xfe, 0xff, 0x00, 0x0a, 0x00, 0x02, 0x01, 0x00 }; uint32_t buf3_len = sizeof(buf2); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf2, buf2_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf3, buf3_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x17, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->client_version); result = 0; goto end; } if (ssl_state->handshake_client_hello_ssl_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->handshake_client_hello_ssl_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** * \test Tests the parser for handling fragmented records. */ static int SSLParserTest13(void) { int result = 1; Flow f; uint8_t buf1[] = { 0x16, 0x03, 0x00, 0x00, 0x6f, 0x01, }; uint32_t buf1_len = sizeof(buf1); uint8_t buf2[] = { 0x00, 0x00, 0x6b, }; uint32_t buf2_len = sizeof(buf2); uint8_t buf3[] = { 0x03, 0x00, 0x4b, 0x2f, 0xdc, 0x4e, 0xe6, 0x95, 0xf1, 0xa0, 0xc7, }; uint32_t buf3_len = sizeof(buf3); uint8_t buf4[] = { 0xcf, 0x8e, 0xf6, 0xeb, 0x22, 0x6d, 0xce, 0x9c, 0x44, 0xfb, 0xc8, 0xa0, 0x44, 0x31, 0x15, 0x4c, 0xe9, 0x97, 0xa7, 0xa1, 0xfe, 0xea, 0xcc, 0x20, 0x4b, 0x5d, 0xfb, 0xa5, 0x63, 0x7a, 0x73, 0x95, 0xf7, 0xff, 0x42, 0xac, 0x8f, 0x46, 0xed, 0xe4, 0xb1, 0x35, 0x35, 0x78, 0x1a, 0x9d, 0xaf, 0x10, 0xc5, 0x52, 0xf3, 0x7b, 0xfb, 0xb5, 0xe9, 0xa8, 0x00, 0x24, 0x00, 0x88, 0x00, 0x87, 0x00, 0x39, 0x00, 0x38, 0x00, 0x84, 0x00, 0x35, 0x00, 0x45, 0x00, 0x44, 0x00, 0x33, 0x00, 0x32, 0x00, 0x96, 0x00, 0x41, 0x00, 0x2f, 0x00, 0x16, 0x00, 0x13, 0xfe, 0xff, 0x00, 0x0a, 0x00, 0x02, 0x01, 0x00 }; uint32_t buf4_len = sizeof(buf4); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf2, buf2_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf3, buf3_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf4, buf4_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x17, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->client_version); result = 0; goto end; } if (ssl_state->handshake_client_hello_ssl_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->handshake_client_hello_ssl_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** * \test Tests the parser for handling fragmented records. */ static int SSLParserTest14(void) { int result = 1; Flow f; uint8_t buf1[] = { 0x16, 0x03, 0x00, 0x00, 0x00, }; uint32_t buf1_len = sizeof(buf1); uint8_t buf2[] = { 0x16, 0x03, 0x00, 0x00, 0x00, }; uint32_t buf2_len = sizeof(buf2); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf2, buf2_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** * \test Tests the parser for handling fragmented records. */ static int SSLParserTest15(void) { int result = 1; Flow f; uint8_t buf1[] = { 0x16, 0x03, 0x00, 0x00, 0x01, 0x01, }; uint32_t buf1_len = sizeof(buf1); uint8_t buf2[] = { 0x16, 0x03, 0x00, 0x00, 0x00, }; uint32_t buf2_len = sizeof(buf2); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf2, buf2_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** * \test Tests the parser for handling fragmented records. */ static int SSLParserTest16(void) { int result = 1; Flow f; uint8_t buf1[] = { 0x16, 0x03, 0x00, 0x00, 0x02, 0x01, 0x00 }; uint32_t buf1_len = sizeof(buf1); uint8_t buf2[] = { 0x16, 0x03, 0x00, 0x00, 0x00, }; uint32_t buf2_len = sizeof(buf2); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf2, buf2_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** * \test Tests the parser for handling fragmented records. */ static int SSLParserTest17(void) { int result = 1; Flow f; uint8_t buf1[] = { 0x16, 0x03, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00 }; uint32_t buf1_len = sizeof(buf1); uint8_t buf2[] = { 0x16, 0x03, 0x00, 0x00, 0x00, }; uint32_t buf2_len = sizeof(buf2); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf2, buf2_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** * \test Tests the parser for handling fragmented records. */ static int SSLParserTest18(void) { int result = 1; Flow f; uint8_t buf1[] = { 0x16, 0x03, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x6b, }; uint32_t buf1_len = sizeof(buf1); uint8_t buf2[] = { 0x16, 0x03, 0x00, 0x00, 0x00, }; uint32_t buf2_len = sizeof(buf2); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf2, buf2_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** * \test Tests the parser for handling fragmented records. */ static int SSLParserTest19(void) { int result = 1; Flow f; uint8_t buf1[] = { 0x16, 0x03, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x6b, 0x16, 0x03, 0x00, 0x00, 0x00, }; uint32_t buf1_len = sizeof(buf1); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** * \test Tests the parser for handling fragmented records. */ static int SSLParserTest20(void) { int result = 1; Flow f; uint8_t buf1[] = { 0x16, 0x03, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x16, 0x03, 0x00, 0x00, 0x00, }; uint32_t buf1_len = sizeof(buf1); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } /** * \test SSLv2 Record parsing. */ static int SSLParserTest21(void) { int result = 0; Flow f; uint8_t buf[] = { 0x80, 0x31, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, }; uint32_t buf_len = sizeof(buf); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); FLOW_INITIALIZE(&f); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER | STREAM_EOF, buf, buf_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); goto end; } SSLState *app_state = f.alstate; if (app_state == NULL) { printf("no ssl state: "); goto end; } if (app_state->client_content_type != SSLV2_MT_CLIENT_HELLO) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", SSLV2_MT_SERVER_HELLO, app_state->client_content_type); goto end; } if (app_state->client_version != SSL_VERSION_2) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_2, app_state->client_version); goto end; } result = 1; end: FLOW_DESTROY(&f); return result; } /** * \test SSLv2 Record parsing. */ static int SSLParserTest22(void) { int result = 1; Flow f; uint8_t buf[] = { 0x80, 0x31, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x07, 0x00, 0xc0, 0x05, 0x00, 0x80, 0x03, 0x00, 0x80, 0x01, 0x00, 0x80, 0x08, 0x00, 0x80, 0x06, 0x00, 0x40, 0x04, 0x00, 0x80, 0x02, 0x00, 0x80, 0x76, 0x64, 0x75, 0x2d, 0xa7, 0x98, 0xfe, 0xc9, 0x12, 0x92, 0xc1, 0x2f, 0x34, 0x84, 0x20, 0xc5}; uint32_t buf_len = sizeof(buf); TcpSession ssn; //AppLayerDetectProtoThreadInit(); memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); FLOW_INITIALIZE(&f); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOCLIENT | STREAM_EOF, buf, buf_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *app_state = f.alstate; if (app_state == NULL) { printf("no ssl state: "); result = 0; goto end; } if (app_state->server_content_type != SSLV2_MT_SERVER_HELLO) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", SSLV2_MT_SERVER_HELLO, app_state->server_content_type); result = 0; goto end; } if (app_state->server_version != SSL_VERSION_2) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_2, app_state->server_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); FLOW_DESTROY(&f); return result; } /** * \test SSLv2 Record parsing. */ static int SSLParserTest23(void) { int result = 1; Flow f; uint8_t chello_buf[] = { 0x80, 0x67, 0x01, 0x03, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x07, 0x00, 0xc0, 0x06, 0x00, 0x40, 0x02, 0x00, 0x80, 0x04, 0x00, 0x80, 0x00, 0x00, 0x39, 0x00, 0x00, 0x38, 0x00, 0x00, 0x35, 0x00, 0x00, 0x33, 0x00, 0x00, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x16, 0x00, 0x00, 0x13, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x15, 0x00, 0x00, 0x12, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x09, 0x00, 0x00, 0x64, 0x00, 0x00, 0x62, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0xa8, 0xb8, 0x93, 0xbb, 0x90, 0xe9, 0x2a, 0xa2, 0x4d, 0x6d, 0xcc, 0x1c, 0xe7, 0x2a, 0x80, 0x21 }; uint32_t chello_buf_len = sizeof(chello_buf); uint8_t shello_buf[] = { 0x16, 0x03, 0x00, 0x00, 0x4a, 0x02, 0x00, 0x00, 0x46, 0x03, 0x00, 0x44, 0x4c, 0x94, 0x8f, 0xfe, 0x81, 0xed, 0x93, 0x65, 0x02, 0x88, 0xa3, 0xf8, 0xeb, 0x63, 0x86, 0x0e, 0x2c, 0xf6, 0x8d, 0xd0, 0x0f, 0x2c, 0x2a, 0xd6, 0x4f, 0xcd, 0x2d, 0x3c, 0x16, 0xd7, 0xd6, 0x20, 0xa0, 0xfb, 0x60, 0x86, 0x3d, 0x1e, 0x76, 0xf3, 0x30, 0xfe, 0x0b, 0x01, 0xfd, 0x1a, 0x01, 0xed, 0x95, 0xf6, 0x7b, 0x8e, 0xc0, 0xd4, 0x27, 0xbf, 0xf0, 0x6e, 0xc7, 0x56, 0xb1, 0x47, 0xce, 0x98, 0x00, 0x35, 0x00, 0x16, 0x03, 0x00, 0x03, 0x44, 0x0b, 0x00, 0x03, 0x40, 0x00, 0x03, 0x3d, 0x00, 0x03, 0x3a, 0x30, 0x82, 0x03, 0x36, 0x30, 0x82, 0x02, 0x9f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x30, 0x81, 0xa9, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x58, 0x59, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0c, 0x53, 0x6e, 0x61, 0x6b, 0x65, 0x20, 0x44, 0x65, 0x73, 0x65, 0x72, 0x74, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x6e, 0x61, 0x6b, 0x65, 0x20, 0x54, 0x6f, 0x77, 0x6e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x53, 0x6e, 0x61, 0x6b, 0x65, 0x20, 0x4f, 0x69, 0x6c, 0x2c, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x15, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0c, 0x53, 0x6e, 0x61, 0x6b, 0x65, 0x20, 0x4f, 0x69, 0x6c, 0x20, 0x43, 0x41, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x0f, 0x63, 0x61, 0x40, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0x6f, 0x69, 0x6c, 0x2e, 0x64, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x33, 0x30, 0x33, 0x30, 0x35, 0x31, 0x36, 0x34, 0x37, 0x34, 0x35, 0x5a, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x33, 0x30, 0x33, 0x31, 0x36, 0x34, 0x37, 0x34, 0x35, 0x5a, 0x30, 0x81, 0xa7, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x58, 0x59, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0c, 0x53, 0x6e, 0x61, 0x6b, 0x65, 0x20, 0x44, 0x65, 0x73, 0x65, 0x72, 0x74, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x6e, 0x61, 0x6b, 0x65, 0x20, 0x54, 0x6f, 0x77, 0x6e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x53, 0x6e, 0x61, 0x6b, 0x65, 0x20, 0x4f, 0x69, 0x6c, 0x2c, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0e, 0x57, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x54, 0x65, 0x61, 0x6d, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0x6f, 0x69, 0x6c, 0x2e, 0x64, 0x6f, 0x6d, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x77, 0x77, 0x77, 0x40, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0x6f, 0x69, 0x6c, 0x2e, 0x64, 0x6f, 0x6d, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xa4, 0x6e, 0x53, 0x14, 0x0a, 0xde, 0x2c, 0xe3, 0x60, 0x55, 0x9a, 0xf2, 0x42, 0xa6, 0xaf, 0x47, 0x12, 0x2f, 0x17, 0xce, 0xfa, 0xba, 0xdc, 0x4e, 0x63, 0x56, 0x34, 0xb9, 0xba, 0x73, 0x4b, 0x78, 0x44, 0x3d, 0xc6, 0x6c, 0x69, 0xa4, 0x25, 0xb3, 0x61, 0x02, 0x9d, 0x09, 0x04, 0x3f, 0x72, 0x3d, 0xd8, 0x27, 0xd3, 0xb0, 0x5a, 0x45, 0x77, 0xb7, 0x36, 0xe4, 0x26, 0x23, 0xcc, 0x12, 0xb8, 0xae, 0xde, 0xa7, 0xb6, 0x3a, 0x82, 0x3c, 0x7c, 0x24, 0x59, 0x0a, 0xf8, 0x96, 0x43, 0x8b, 0xa3, 0x29, 0x36, 0x3f, 0x91, 0x7f, 0x5d, 0xc7, 0x23, 0x94, 0x29, 0x7f, 0x0a, 0xce, 0x0a, 0xbd, 0x8d, 0x9b, 0x2f, 0x19, 0x17, 0xaa, 0xd5, 0x8e, 0xec, 0x66, 0xa2, 0x37, 0xeb, 0x3f, 0x57, 0x53, 0x3c, 0xf2, 0xaa, 0xbb, 0x79, 0x19, 0x4b, 0x90, 0x7e, 0xa7, 0xa3, 0x99, 0xfe, 0x84, 0x4c, 0x89, 0xf0, 0x3d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x6e, 0x30, 0x6c, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x14, 0x30, 0x12, 0x81, 0x10, 0x77, 0x77, 0x77, 0x40, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0x6f, 0x69, 0x6c, 0x2e, 0x64, 0x6f, 0x6d, 0x30, 0x3a, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x0d, 0x04, 0x2d, 0x16, 0x2b, 0x6d, 0x6f, 0x64, 0x5f, 0x73, 0x73, 0x6c, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x06, 0x40, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0xae, 0x79, 0x79, 0x22, 0x90, 0x75, 0xfd, 0xa6, 0xd5, 0xc4, 0xb8, 0xc4, 0x99, 0x4e, 0x1c, 0x05, 0x7c, 0x91, 0x59, 0xbe, 0x89, 0x0d, 0x3d, 0xc6, 0x8c, 0xa3, 0xcf, 0xf6, 0xba, 0x23, 0xdf, 0xb8, 0xae, 0x44, 0x68, 0x8a, 0x8f, 0xb9, 0x8b, 0xcb, 0x12, 0xda, 0xe6, 0xa2, 0xca, 0xa5, 0xa6, 0x55, 0xd9, 0xd2, 0xa1, 0xad, 0xba, 0x9b, 0x2c, 0x44, 0x95, 0x1d, 0x4a, 0x90, 0x59, 0x7f, 0x83, 0xae, 0x81, 0x5e, 0x3f, 0x92, 0xe0, 0x14, 0x41, 0x82, 0x4e, 0x7f, 0x53, 0xfd, 0x10, 0x23, 0xeb, 0x8a, 0xeb, 0xe9, 0x92, 0xea, 0x61, 0xf2, 0x8e, 0x19, 0xa1, 0xd3, 0x49, 0xc0, 0x84, 0x34, 0x1e, 0x2e, 0x6e, 0xf6, 0x98, 0xe2, 0x87, 0x53, 0xd6, 0x55, 0xd9, 0x1a, 0x8a, 0x92, 0x5c, 0xad, 0xdc, 0x1e, 0x1c, 0x30, 0xa7, 0x65, 0x9d, 0xc2, 0x4f, 0x60, 0xd2, 0x6f, 0xdb, 0xe0, 0x9f, 0x9e, 0xbc, 0x41, 0x16, 0x03, 0x00, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00 }; uint32_t shello_buf_len = sizeof(shello_buf); uint8_t client_change_cipher_spec_buf[] = { 0x16, 0x03, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, 0x80, 0x65, 0x51, 0x2d, 0xa6, 0xd4, 0xa7, 0x38, 0xdf, 0xac, 0x79, 0x1f, 0x0b, 0xd9, 0xb2, 0x61, 0x7d, 0x73, 0x88, 0x32, 0xd9, 0xf2, 0x62, 0x3a, 0x8b, 0x11, 0x04, 0x75, 0xca, 0x42, 0xff, 0x4e, 0xd9, 0xcc, 0xb9, 0xfa, 0x86, 0xf3, 0x16, 0x2f, 0x09, 0x73, 0x51, 0x66, 0xaa, 0x29, 0xcd, 0x80, 0x61, 0x0f, 0xe8, 0x13, 0xce, 0x5b, 0x8e, 0x0a, 0x23, 0xf8, 0x91, 0x5e, 0x5f, 0x54, 0x70, 0x80, 0x8e, 0x7b, 0x28, 0xef, 0xb6, 0x69, 0xb2, 0x59, 0x85, 0x74, 0x98, 0xe2, 0x7e, 0xd8, 0xcc, 0x76, 0x80, 0xe1, 0xb6, 0x45, 0x4d, 0xc7, 0xcd, 0x84, 0xce, 0xb4, 0x52, 0x79, 0x74, 0xcd, 0xe6, 0xd7, 0xd1, 0x9c, 0xad, 0xef, 0x63, 0x6c, 0x0f, 0xf7, 0x05, 0xe4, 0x4d, 0x1a, 0xd3, 0xcb, 0x9c, 0xd2, 0x51, 0xb5, 0x61, 0xcb, 0xff, 0x7c, 0xee, 0xc7, 0xbc, 0x5e, 0x15, 0xa3, 0xf2, 0x52, 0x0f, 0xbb, 0x32, 0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16, 0x03, 0x00, 0x00, 0x40, 0xa9, 0xd8, 0xd7, 0x35, 0xbc, 0x39, 0x56, 0x98, 0xad, 0x87, 0x61, 0x2a, 0xc4, 0x8f, 0xcc, 0x03, 0xcb, 0x93, 0x80, 0x81, 0xb0, 0x4a, 0xc4, 0xd2, 0x09, 0x71, 0x3e, 0x90, 0x3c, 0x8d, 0xe0, 0x95, 0x44, 0xfe, 0x56, 0xd1, 0x7e, 0x88, 0xe2, 0x48, 0xfd, 0x76, 0x70, 0x76, 0xe2, 0xcd, 0x06, 0xd0, 0xf3, 0x9d, 0x13, 0x79, 0x67, 0x1e, 0x37, 0xf6, 0x98, 0xbe, 0x59, 0x18, 0x4c, 0xfc, 0x75, 0x56 }; uint32_t client_change_cipher_spec_buf_len = sizeof(client_change_cipher_spec_buf); uint8_t server_change_cipher_spec_buf[] = { 0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16, 0x03, 0x00, 0x00, 0x40, 0xce, 0x7c, 0x92, 0x43, 0x59, 0xcc, 0x3d, 0x90, 0x91, 0x9c, 0x58, 0xf0, 0x7a, 0xce, 0xae, 0x0d, 0x08, 0xe0, 0x76, 0xb4, 0x86, 0xb1, 0x15, 0x5b, 0x32, 0xb8, 0x77, 0x53, 0xe7, 0xa6, 0xf9, 0xd0, 0x95, 0x5f, 0xaa, 0x07, 0xc3, 0x96, 0x7c, 0xc9, 0x88, 0xc2, 0x7a, 0x20, 0x89, 0x4f, 0xeb, 0xeb, 0xb6, 0x19, 0xef, 0xaa, 0x27, 0x73, 0x9d, 0xa6, 0xb4, 0x9f, 0xeb, 0x34, 0xe2, 0x4d, 0x9f, 0x6b }; uint32_t server_change_cipher_spec_buf_len = sizeof(server_change_cipher_spec_buf); uint8_t toserver_app_data_buf[] = { 0x17, 0x03, 0x00, 0x01, 0xb0, 0x4a, 0xc3, 0x3e, 0x9d, 0x77, 0x78, 0x01, 0x2c, 0xb4, 0xbc, 0x4c, 0x9a, 0x84, 0xd7, 0xb9, 0x90, 0x0c, 0x21, 0x10, 0xf0, 0xfa, 0x00, 0x7c, 0x16, 0xbb, 0x77, 0xfb, 0x72, 0x42, 0x4f, 0xad, 0x50, 0x4a, 0xd0, 0xaa, 0x6f, 0xaa, 0x44, 0x6c, 0x62, 0x94, 0x1b, 0xc5, 0xfe, 0xe9, 0x1c, 0x5e, 0xde, 0x85, 0x0b, 0x0e, 0x05, 0xe4, 0x18, 0x6e, 0xd2, 0xd3, 0xb5, 0x20, 0xab, 0x81, 0xfd, 0x18, 0x9a, 0x73, 0xb8, 0xd7, 0xef, 0xc3, 0xdd, 0x74, 0xd7, 0x9c, 0x1e, 0x6f, 0x21, 0x6d, 0xf8, 0x24, 0xca, 0x3c, 0x70, 0x78, 0x36, 0x12, 0x7a, 0x8a, 0x9c, 0xac, 0x4e, 0x1c, 0xa8, 0xfb, 0x27, 0x30, 0xba, 0x9a, 0xf4, 0x2f, 0x0a, 0xab, 0x80, 0x6a, 0xa1, 0x60, 0x74, 0xf0, 0xe3, 0x91, 0x84, 0xe7, 0x90, 0x88, 0xcc, 0xf0, 0x95, 0x7b, 0x0a, 0x22, 0xf2, 0xf9, 0x27, 0xe0, 0xdd, 0x38, 0x0c, 0xfd, 0xe9, 0x03, 0x71, 0xdc, 0x70, 0xa4, 0x6e, 0xdf, 0xe3, 0x72, 0x9e, 0xa1, 0xf0, 0xc9, 0x00, 0xd6, 0x03, 0x55, 0x6a, 0x67, 0x5d, 0x9c, 0xb8, 0x75, 0x01, 0xb0, 0x01, 0x9f, 0xe6, 0xd2, 0x44, 0x18, 0xbc, 0xca, 0x7a, 0x10, 0x39, 0xa6, 0xcf, 0x15, 0xc7, 0xf5, 0x35, 0xd4, 0xb3, 0x6d, 0x91, 0x23, 0x84, 0x99, 0xba, 0xb0, 0x7e, 0xd0, 0xc9, 0x4c, 0xbf, 0x3f, 0x33, 0x68, 0x37, 0xb7, 0x7d, 0x44, 0xb0, 0x0b, 0x2c, 0x0f, 0xd0, 0x75, 0xa2, 0x6b, 0x5b, 0xe1, 0x9f, 0xd4, 0x69, 0x9a, 0x14, 0xc8, 0x29, 0xb7, 0xd9, 0x10, 0xbb, 0x99, 0x30, 0x9a, 0xfb, 0xcc, 0x13, 0x1f, 0x76, 0x4e, 0xe6, 0xdf, 0x14, 0xaa, 0xd5, 0x60, 0xbf, 0x91, 0x49, 0x0d, 0x64, 0x42, 0x29, 0xa8, 0x64, 0x27, 0xd4, 0x5e, 0x1b, 0x18, 0x03, 0xa8, 0x73, 0xd6, 0x05, 0x6e, 0xf7, 0x50, 0xb0, 0x09, 0x6b, 0x69, 0x7a, 0x12, 0x28, 0x58, 0xef, 0x5a, 0x86, 0x11, 0xde, 0x71, 0x71, 0x9f, 0xca, 0xbd, 0x79, 0x2a, 0xc2, 0xe5, 0x9b, 0x5e, 0x32, 0xe7, 0xcb, 0x97, 0x6e, 0xa0, 0xea, 0xa4, 0xa4, 0x6a, 0x32, 0xf9, 0x37, 0x39, 0xd8, 0x37, 0x6d, 0x63, 0xf3, 0x08, 0x1c, 0xdd, 0x06, 0xdd, 0x2c, 0x2b, 0x9f, 0x04, 0x88, 0x5f, 0x36, 0x42, 0xc1, 0xb1, 0xc7, 0xe8, 0x2d, 0x5d, 0xa4, 0x6c, 0xe5, 0x60, 0x94, 0xae, 0xd0, 0x90, 0x1e, 0x88, 0xa0, 0x87, 0x52, 0xfb, 0xed, 0x97, 0xa5, 0x25, 0x5a, 0xb7, 0x55, 0xc5, 0x13, 0x07, 0x85, 0x27, 0x40, 0xed, 0xb8, 0xa0, 0x26, 0x13, 0x44, 0x0c, 0xfc, 0xcc, 0x5a, 0x09, 0xe5, 0x44, 0xb5, 0x63, 0xa1, 0x43, 0x51, 0x23, 0x4f, 0x17, 0x21, 0x89, 0x2e, 0x58, 0xfd, 0xf9, 0x63, 0x74, 0x04, 0x70, 0x1e, 0x7d, 0xd0, 0x66, 0xba, 0x40, 0x5e, 0x45, 0xdc, 0x39, 0x7c, 0x53, 0x0f, 0xa8, 0x38, 0xb2, 0x13, 0x99, 0x27, 0xd9, 0x4a, 0x51, 0xe9, 0x9f, 0x2a, 0x92, 0xbb, 0x9c, 0x90, 0xab, 0xfd, 0xf1, 0xb7, 0x40, 0x05, 0xa9, 0x7a, 0x20, 0x63, 0x36, 0xc1, 0xef, 0xb9, 0xad, 0xa2, 0xe0, 0x1d, 0x20, 0x4f, 0xb2, 0x34, 0xbd, 0xea, 0x07, 0xac, 0x21, 0xce, 0xf6, 0x8a, 0xa2, 0x9e, 0xcd, 0xfa }; uint32_t toserver_app_data_buf_len = sizeof(toserver_app_data_buf); TcpSession ssn; //AppLayerDetectProtoThreadInit(); memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); FLOW_INITIALIZE(&f); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER | STREAM_START, chello_buf, chello_buf_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *app_state = f.alstate; if (app_state == NULL) { printf("no ssl state: "); result = 0; goto end; } if (app_state->client_content_type != SSLV2_MT_CLIENT_HELLO) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", SSLV2_MT_CLIENT_HELLO, app_state->client_content_type); result = 0; goto end; } if (app_state->client_version != SSL_VERSION_2) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_2, app_state->client_version); result = 0; goto end; } if (app_state->flags != (SSL_AL_FLAG_STATE_CLIENT_HELLO | SSL_AL_FLAG_SSL_CLIENT_HS | SSL_AL_FLAG_SSL_NO_SESSION_ID)) { printf("flags not set\n"); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOCLIENT, shello_buf, shello_buf_len); if (r != 0) { printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } if (app_state->server_content_type != SSLV3_HANDSHAKE_PROTOCOL) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", SSLV3_HANDSHAKE_PROTOCOL, app_state->server_content_type); result = 0; goto end; } if (app_state->server_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, app_state->server_version); result = 0; goto end; } if (app_state->flags != (SSL_AL_FLAG_STATE_CLIENT_HELLO | SSL_AL_FLAG_SSL_CLIENT_HS | SSL_AL_FLAG_SSL_NO_SESSION_ID | SSL_AL_FLAG_STATE_SERVER_HELLO)) { printf("flags not set\n"); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, client_change_cipher_spec_buf, client_change_cipher_spec_buf_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } /* with multiple records the client content type hold the type from the last * record */ if (app_state->client_content_type != SSLV3_HANDSHAKE_PROTOCOL) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", SSLV3_HANDSHAKE_PROTOCOL, app_state->client_content_type); result = 0; goto end; } if (app_state->client_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, app_state->client_version); result = 0; goto end; } if (app_state->flags != (SSL_AL_FLAG_STATE_CLIENT_HELLO | SSL_AL_FLAG_SSL_CLIENT_HS | SSL_AL_FLAG_SSL_NO_SESSION_ID | SSL_AL_FLAG_STATE_SERVER_HELLO | SSL_AL_FLAG_STATE_CLIENT_KEYX | SSL_AL_FLAG_CLIENT_CHANGE_CIPHER_SPEC | SSL_AL_FLAG_CHANGE_CIPHER_SPEC)) { printf("flags not set\n"); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOCLIENT, server_change_cipher_spec_buf, server_change_cipher_spec_buf_len); if (r != 0) { printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } /* with multiple records the serve content type hold the type from the last * record */ if (app_state->server_content_type != SSLV3_HANDSHAKE_PROTOCOL) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", SSLV3_HANDSHAKE_PROTOCOL, app_state->server_content_type); result = 0; goto end; } if (app_state->server_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, app_state->server_version); result = 0; goto end; } if (app_state->flags != (SSL_AL_FLAG_STATE_CLIENT_HELLO | SSL_AL_FLAG_SSL_CLIENT_HS | SSL_AL_FLAG_SSL_NO_SESSION_ID | SSL_AL_FLAG_STATE_SERVER_HELLO | SSL_AL_FLAG_STATE_CLIENT_KEYX | SSL_AL_FLAG_CLIENT_CHANGE_CIPHER_SPEC | SSL_AL_FLAG_CHANGE_CIPHER_SPEC | SSL_AL_FLAG_SERVER_CHANGE_CIPHER_SPEC | SSL_AL_FLAG_CHANGE_CIPHER_SPEC)) { printf("flags not set\n"); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, toserver_app_data_buf, toserver_app_data_buf_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } if (app_state->client_content_type != SSLV3_APPLICATION_PROTOCOL) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", SSLV3_APPLICATION_PROTOCOL, app_state->client_content_type); result = 0; goto end; } if (app_state->client_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, app_state->client_version); result = 0; goto end; } if (app_state->flags != (SSL_AL_FLAG_STATE_CLIENT_HELLO | SSL_AL_FLAG_SSL_CLIENT_HS | SSL_AL_FLAG_SSL_NO_SESSION_ID | SSL_AL_FLAG_STATE_SERVER_HELLO | SSL_AL_FLAG_STATE_CLIENT_KEYX | SSL_AL_FLAG_CLIENT_CHANGE_CIPHER_SPEC | SSL_AL_FLAG_CHANGE_CIPHER_SPEC | SSL_AL_FLAG_SERVER_CHANGE_CIPHER_SPEC | SSL_AL_FLAG_CHANGE_CIPHER_SPEC)) { printf("flags not set\n"); result = 0; goto end; } AppLayerParserStateStore *parser_state_store = (AppLayerParserStateStore *)f.alparser; AppLayerParserState *parser_state = &parser_state_store->to_server; if (!(parser_state->flags & APP_LAYER_PARSER_NO_INSPECTION) && !(ssn.client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) && !(ssn.server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) { printf("The flags should be set\n"); result = 0; goto end; } if (!(f.flags & FLOW_NOPAYLOAD_INSPECTION)) { printf("The flags should be set\n"); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); FLOW_DESTROY(&f); return result; } /** * \test Tests the parser for handling fragmented records. */ static int SSLParserTest24(void) { int result = 1; Flow f; uint8_t buf1[] = { 0x16, 0x03, 0x00, 0x00, 0x6f, 0x01, 0x00, 0x00, 0x6b, 0x03, }; uint32_t buf1_len = sizeof(buf1); uint8_t buf2[] = { 0x00, 0x4b, 0x2f, 0xdc, 0x4e, 0xe6, 0x95, 0xf1, 0xa0, 0xc7, 0xcf, 0x8e, 0xf6, 0xeb, 0x22, 0x6d, 0xce, 0x9c, 0x44, 0xfb, 0xc8, 0xa0, 0x44, 0x31, 0x15, 0x4c, 0xe9, 0x97, 0xa7, 0xa1, 0xfe, 0xea, 0xcc, 0x20, 0x4b, 0x5d, 0xfb, 0xa5, 0x63, 0x7a, 0x73, 0x95, 0xf7, 0xff, 0x42, 0xac, 0x8f, 0x46, 0xed, 0xe4, 0xb1, 0x35, 0x35, 0x78, 0x1a, 0x9d, 0xaf, 0x10, 0xc5, 0x52, 0xf3, 0x7b, 0xfb, 0xb5, 0xe9, 0xa8, 0x00, 0x24, 0x00, 0x88, 0x00, 0x87, 0x00, 0x39, 0x00, 0x38, 0x00, 0x84, 0x00, 0x35, 0x00, 0x45, 0x00, 0x44, 0x00, 0x33, 0x00, 0x32, 0x00, 0x96, 0x00, 0x41, 0x00, 0x2f, 0x00, 0x16, 0x00, 0x13, 0xfe, 0xff, 0x00, 0x0a, 0x00, 0x02, 0x01, 0x00 }; uint32_t buf2_len = sizeof(buf2); TcpSession ssn; memset(&f, 0, sizeof(f)); memset(&ssn, 0, sizeof(ssn)); f.protoctx = (void *)&ssn; StreamTcpInitConfig(TRUE); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf2, buf2_len); if (r != 0) { printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); result = 0; goto end; } SSLState *ssl_state = f.alstate; if (ssl_state == NULL) { printf("no tls state: "); result = 0; goto end; } if (ssl_state->client_content_type != 0x16) { printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x16, ssl_state->client_content_type); result = 0; goto end; } if (ssl_state->client_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->client_version); result = 0; goto end; } if (ssl_state->handshake_client_hello_ssl_version != SSL_VERSION_3) { printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", SSL_VERSION_3, ssl_state->handshake_client_hello_ssl_version); result = 0; goto end; } end: StreamTcpFreeConfig(TRUE); return result; } #endif /* UNITTESTS */ void SSLParserRegisterTests(void) { #ifdef UNITTESTS UtRegisterTest("SSLParserTest01", SSLParserTest01, 1); UtRegisterTest("SSLParserTest02", SSLParserTest02, 1); UtRegisterTest("SSLParserTest03", SSLParserTest03, 1); UtRegisterTest("SSLParserTest04", SSLParserTest04, 1); /* Updated by Anoop Saldanha. Faulty tests. Disable it for now */ //UtRegisterTest("SSLParserTest05", SSLParserTest05, 1); //UtRegisterTest("SSLParserTest06", SSLParserTest06, 1); UtRegisterTest("SSLParserTest07", SSLParserTest07, 1); //UtRegisterTest("SSLParserTest08", SSLParserTest08, 1); UtRegisterTest("SSLParserTest09", SSLParserTest09, 1); UtRegisterTest("SSLParserTest10", SSLParserTest10, 1); UtRegisterTest("SSLParserTest11", SSLParserTest11, 1); UtRegisterTest("SSLParserTest12", SSLParserTest12, 1); UtRegisterTest("SSLParserTest13", SSLParserTest13, 1); UtRegisterTest("SSLParserTest14", SSLParserTest14, 1); UtRegisterTest("SSLParserTest15", SSLParserTest15, 1); UtRegisterTest("SSLParserTest16", SSLParserTest16, 1); UtRegisterTest("SSLParserTest17", SSLParserTest17, 1); UtRegisterTest("SSLParserTest18", SSLParserTest18, 1); UtRegisterTest("SSLParserTest19", SSLParserTest19, 1); UtRegisterTest("SSLParserTest20", SSLParserTest20, 1); UtRegisterTest("SSLParserTest21", SSLParserTest21, 1); UtRegisterTest("SSLParserTest22", SSLParserTest22, 1); UtRegisterTest("SSLParserTest23", SSLParserTest23, 1); UtRegisterTest("SSLParserTest24", SSLParserTest24, 1); UtRegisterTest("SSLParserMultimsgTest01", SSLParserMultimsgTest01, 1); UtRegisterTest("SSLParserMultimsgTest02", SSLParserMultimsgTest02, 1); #endif /* UNITTESTS */ return; }