|
|
|
@ -37,6 +37,7 @@
|
|
|
|
|
#include "app-layer.h"
|
|
|
|
|
#include "app-layer-protos.h"
|
|
|
|
|
#include "app-layer-parser.h"
|
|
|
|
|
#include "app-layer-frames.h"
|
|
|
|
|
#include "app-layer-ssl.h"
|
|
|
|
|
|
|
|
|
|
#include "decode-events.h"
|
|
|
|
@ -53,6 +54,38 @@
|
|
|
|
|
#include "flow-private.h"
|
|
|
|
|
#include "util-validate.h"
|
|
|
|
|
|
|
|
|
|
SCEnumCharMap tls_frame_table[] = {
|
|
|
|
|
{
|
|
|
|
|
"pdu",
|
|
|
|
|
TLS_FRAME_PDU,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"hdr",
|
|
|
|
|
TLS_FRAME_HDR,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data",
|
|
|
|
|
TLS_FRAME_DATA,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"alert",
|
|
|
|
|
TLS_FRAME_ALERT_DATA,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"heartbeat",
|
|
|
|
|
TLS_FRAME_HB_DATA,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"ssl2.hdr",
|
|
|
|
|
TLS_FRAME_SSLV2_HDR,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"ssl2.pdu",
|
|
|
|
|
TLS_FRAME_SSLV2_PDU,
|
|
|
|
|
},
|
|
|
|
|
{ NULL, -1 },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
SCEnumCharMap tls_decoder_event_table[ ] = {
|
|
|
|
|
/* TLS protocol messages */
|
|
|
|
|
{ "INVALID_SSLV2_HEADER", TLS_DECODER_EVENT_INVALID_SSLV2_HEADER },
|
|
|
|
@ -1980,9 +2013,8 @@ static int SSLv2ParseRecord(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
return (input - initial_input);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
AppLayerParserState *pstate, const uint8_t *input,
|
|
|
|
|
uint32_t input_len)
|
|
|
|
|
static int SSLv2Decode(uint8_t direction, SSLState *ssl_state, AppLayerParserState *pstate,
|
|
|
|
|
const uint8_t *input, uint32_t input_len, const StreamSlice stream_slice)
|
|
|
|
|
{
|
|
|
|
|
int retval = 0;
|
|
|
|
|
const uint8_t *initial_input = input;
|
|
|
|
@ -1993,18 +2025,37 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
} else {
|
|
|
|
|
ssl_state->curr_connp->record_lengths_length = 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCLogDebug("record start: ssl2.hdr frame");
|
|
|
|
|
AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input,
|
|
|
|
|
ssl_state->curr_connp->record_lengths_length + 1, direction, TLS_FRAME_SSLV2_HDR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCLogDebug("direction %u ssl_state->curr_connp->record_lengths_length + 1 %u, "
|
|
|
|
|
"ssl_state->curr_connp->bytes_processed %u",
|
|
|
|
|
direction, ssl_state->curr_connp->record_lengths_length + 1,
|
|
|
|
|
ssl_state->curr_connp->bytes_processed);
|
|
|
|
|
/* the +1 is because we read one extra byte inside SSLv2ParseRecord
|
|
|
|
|
to read the msg_type */
|
|
|
|
|
if (ssl_state->curr_connp->bytes_processed <
|
|
|
|
|
(ssl_state->curr_connp->record_lengths_length + 1)) {
|
|
|
|
|
retval = SSLv2ParseRecord(direction, ssl_state, input, input_len);
|
|
|
|
|
SCLogDebug("retval %d ssl_state->curr_connp->record_length %u", retval,
|
|
|
|
|
ssl_state->curr_connp->record_length);
|
|
|
|
|
if (retval < 0 || retval > (int)input_len) {
|
|
|
|
|
DEBUG_VALIDATE_BUG_ON(retval > (int)input_len);
|
|
|
|
|
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSLV2_HEADER);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
// TODO review
|
|
|
|
|
// BUG_ON(ssl_state->curr_connp->record_lengths_length + 1 !=
|
|
|
|
|
// ssl_state->curr_connp->bytes_processed);
|
|
|
|
|
|
|
|
|
|
AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input,
|
|
|
|
|
ssl_state->curr_connp->record_lengths_length + ssl_state->curr_connp->record_length,
|
|
|
|
|
direction, TLS_FRAME_SSLV2_PDU);
|
|
|
|
|
SCLogDebug("record start: ssl2.pdu frame");
|
|
|
|
|
|
|
|
|
|
input += retval;
|
|
|
|
|
input_len -= retval;
|
|
|
|
|
}
|
|
|
|
@ -2249,9 +2300,8 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
AppLayerParserState *pstate, const uint8_t *input,
|
|
|
|
|
const uint32_t input_len)
|
|
|
|
|
static int SSLv3Decode(uint8_t direction, SSLState *ssl_state, AppLayerParserState *pstate,
|
|
|
|
|
const uint8_t *input, const uint32_t input_len, const StreamSlice stream_slice)
|
|
|
|
|
{
|
|
|
|
|
uint32_t parsed = 0;
|
|
|
|
|
uint32_t record_len; /* slice of input_len for the current record */
|
|
|
|
@ -2264,6 +2314,12 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_TLS_HEADER);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
SCLogDebug("%s input %p record_length %u", (direction == 0) ? "toserver" : "toclient",
|
|
|
|
|
input, ssl_state->curr_connp->record_length);
|
|
|
|
|
AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input,
|
|
|
|
|
ssl_state->curr_connp->record_length + retval, direction, TLS_FRAME_PDU);
|
|
|
|
|
AppLayerFrameNewByPointer(
|
|
|
|
|
ssl_state->f, &stream_slice, input, SSLV3_RECORD_HDR_LEN, direction, TLS_FRAME_HDR);
|
|
|
|
|
parsed += retval;
|
|
|
|
|
record_len = MIN(input_len - parsed, ssl_state->curr_connp->record_length);
|
|
|
|
|
SCLogDebug("record_len %u (input_len %u, parsed %u, ssl_state->curr_connp->record_length %u)",
|
|
|
|
@ -2287,6 +2343,8 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_TLS_HEADER);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input + parsed,
|
|
|
|
|
ssl_state->curr_connp->record_length, direction, TLS_FRAME_DATA);
|
|
|
|
|
|
|
|
|
|
switch (ssl_state->curr_connp->content_type) {
|
|
|
|
|
|
|
|
|
@ -2303,6 +2361,8 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SSLV3_ALERT_PROTOCOL:
|
|
|
|
|
AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input + parsed,
|
|
|
|
|
ssl_state->curr_connp->record_length, direction, TLS_FRAME_ALERT_DATA);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SSLV3_APPLICATION_PROTOCOL:
|
|
|
|
@ -2395,6 +2455,8 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
return parsed;
|
|
|
|
|
}
|
|
|
|
|
case SSLV3_HEARTBEAT_PROTOCOL: {
|
|
|
|
|
AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input + parsed,
|
|
|
|
|
ssl_state->curr_connp->record_length, direction, TLS_FRAME_HB_DATA);
|
|
|
|
|
int retval = SSLv3ParseHeartbeatProtocol(ssl_state, input + parsed,
|
|
|
|
|
record_len, direction);
|
|
|
|
|
if (retval < 0) {
|
|
|
|
@ -2474,7 +2536,8 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate,
|
|
|
|
|
|
|
|
|
|
if (input == NULL &&
|
|
|
|
|
((direction == 0 && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS)) ||
|
|
|
|
|
(direction == 1 && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC)))) {
|
|
|
|
|
(direction == 1 &&
|
|
|
|
|
AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC)))) {
|
|
|
|
|
/* flag session as finished if APP_LAYER_PARSER_EOF is set */
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_STATE_FINISHED;
|
|
|
|
|
SCReturnStruct(APP_LAYER_OK);
|
|
|
|
@ -2526,8 +2589,7 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate,
|
|
|
|
|
} else {
|
|
|
|
|
SCLogDebug("Continuing parsing SSLv2 record");
|
|
|
|
|
}
|
|
|
|
|
int retval = SSLv2Decode(direction, ssl_state, pstate, input,
|
|
|
|
|
input_len);
|
|
|
|
|
int retval = SSLv2Decode(direction, ssl_state, pstate, input, input_len, stream_slice);
|
|
|
|
|
if (retval < 0 || retval > input_len) {
|
|
|
|
|
DEBUG_VALIDATE_BUG_ON(retval > input_len);
|
|
|
|
|
SCLogDebug("Error parsing SSLv2. Reseting parser "
|
|
|
|
@ -2548,8 +2610,7 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate,
|
|
|
|
|
SCLogDebug("Continuing parsing TLS record: record_length %u, bytes_processed %u",
|
|
|
|
|
ssl_state->curr_connp->record_length, ssl_state->curr_connp->bytes_processed);
|
|
|
|
|
}
|
|
|
|
|
int retval = SSLv3Decode(direction, ssl_state, pstate, input,
|
|
|
|
|
input_len);
|
|
|
|
|
int retval = SSLv3Decode(direction, ssl_state, pstate, input, input_len, stream_slice);
|
|
|
|
|
if (retval < 0 || retval > input_len) {
|
|
|
|
|
DEBUG_VALIDATE_BUG_ON(retval > input_len);
|
|
|
|
|
SCLogDebug("Error parsing TLS. Reseting parser "
|
|
|
|
@ -2704,6 +2765,22 @@ static AppProto SSLProbingParser(Flow *f, uint8_t direction,
|
|
|
|
|
return ALPROTO_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int SSLStateGetFrameIdByName(const char *frame_name)
|
|
|
|
|
{
|
|
|
|
|
int id = SCMapEnumNameToValue(frame_name, tls_frame_table);
|
|
|
|
|
if (id < 0) {
|
|
|
|
|
SCLogError(SC_ERR_INVALID_ENUM_MAP, "unknown frame type \"%s\"", frame_name);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *SSLStateGetFrameNameById(const uint8_t frame_id)
|
|
|
|
|
{
|
|
|
|
|
const char *name = SCMapEnumValueToName(frame_id, tls_frame_table);
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int SSLStateGetEventInfo(const char *event_name,
|
|
|
|
|
int *event_id, AppLayerEventType *event_type)
|
|
|
|
|
{
|
|
|
|
@ -2931,6 +3008,8 @@ void RegisterSSLParsers(void)
|
|
|
|
|
AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_TLS, STREAM_TOCLIENT,
|
|
|
|
|
SSLParseServerRecord);
|
|
|
|
|
|
|
|
|
|
AppLayerParserRegisterGetFrameFuncs(
|
|
|
|
|
IPPROTO_TCP, ALPROTO_TLS, SSLStateGetFrameIdByName, SSLStateGetFrameNameById);
|
|
|
|
|
AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_TLS, SSLStateGetEventInfo);
|
|
|
|
|
AppLayerParserRegisterGetEventInfoById(IPPROTO_TCP, ALPROTO_TLS, SSLStateGetEventInfoById);
|
|
|
|
|
|
|
|
|
|