uint32_t record_len; /* slice of input_len for the current record */
if (ssl_state->curr_connp->bytes_processed < SSLV3_RECORD_HDR_LEN) {
+ const uint16_t prev_version = ssl_state->curr_connp->version;
+
int retval = SSLv3ParseRecord(direction, ssl_state, input, input_len);
if (retval < 0 || retval > (int)input_len) {
DEBUG_VALIDATE_BUG_ON(retval > (int)input_len);
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_TLS_HEADER);
return SSL_DECODER_ERROR(-1);
}
+
+ bool unknown_record = false;
+ switch (ssl_state->curr_connp->content_type) {
+ case SSLV3_CHANGE_CIPHER_SPEC:
+ case SSLV3_ALERT_PROTOCOL:
+ case SSLV3_HANDSHAKE_PROTOCOL:
+ case SSLV3_APPLICATION_PROTOCOL:
+ case SSLV3_HEARTBEAT_PROTOCOL:
+ break;
+ default:
+ unknown_record = true;
+ break;
+ }
+
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,
SCLogDebug("record_len %u (input_len %u, parsed %u, ssl_state->curr_connp->record_length %u)",
record_len, input_len, parsed, ssl_state->curr_connp->record_length);
+ /* unknown record type. For TLS 1.0, 1.1 and 1.2 this is ok. For the rest it is fatal. Based
+ * on Wireshark logic. */
+ if (prev_version == TLS_VERSION_10 || prev_version == TLS_VERSION_11) {
+ if (unknown_record) {
+ SCLogDebug("unknown record, ignore it");
+ SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_RECORD_TYPE);
+
+ ssl_state->curr_connp->bytes_processed = 0; // TODO review this reset logic
+ ssl_state->curr_connp->content_type = 0;
+ ssl_state->curr_connp->record_length = 0;
+ // restore last good version
+ ssl_state->curr_connp->version = prev_version;
+ return SSL_DECODER_OK(input_len); // consume everything
+ }
+ } else {
+ if (unknown_record) {
+ SCLogDebug("unknown record, fatal");
+ SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_RECORD_TYPE);
+ return SSL_DECODER_ERROR(-1);
+ }
+ }
+
+ /* record_length should never be zero */
+ if (ssl_state->curr_connp->record_length == 0) {
+ SCLogDebug("SSLv3 Record length is 0");
+ SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_RECORD_LENGTH);
+ return SSL_DECODER_ERROR(-1);
+ }
+
if (!TLSVersionValid(ssl_state->curr_connp->version)) {
+ SCLogDebug("ssl_state->curr_connp->version %04x", ssl_state->curr_connp->version);
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_RECORD_VERSION);
return SSL_DECODER_ERROR(-1);
}
return SSL_DECODER_OK(parsed);
}
- /* record_length should never be zero */
- if (ssl_state->curr_connp->record_length == 0) {
- SCLogDebug("SSLv3 Record length is 0");
- SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_TLS_HEADER);
- return SSL_DECODER_ERROR(-1);
- }
AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input + parsed,
ssl_state->curr_connp->record_length, direction, TLS_FRAME_DATA);
break;
}
default:
- SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_RECORD_TYPE);
+ // should be unreachable now that we check after header parsing
+ DEBUG_VALIDATE_BUG_ON(1);
SCLogDebug("unsupported record type");
return SSL_DECODER_ERROR(-1);
}