|
|
|
@ -28,9 +28,6 @@
|
|
|
|
|
#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"
|
|
|
|
@ -40,7 +37,6 @@
|
|
|
|
|
#include "app-layer-protos.h"
|
|
|
|
|
#include "app-layer-parser.h"
|
|
|
|
|
#include "app-layer-ssl.h"
|
|
|
|
|
|
|
|
|
|
#include "app-layer-tls-handshake.h"
|
|
|
|
|
|
|
|
|
|
#include "decode-events.h"
|
|
|
|
@ -49,11 +45,12 @@
|
|
|
|
|
#include "util-spm.h"
|
|
|
|
|
#include "util-unittest.h"
|
|
|
|
|
#include "util-debug.h"
|
|
|
|
|
#include "util-print.h"
|
|
|
|
|
#include "util-pool.h"
|
|
|
|
|
#include "util-byte.h"
|
|
|
|
|
#include "flow-util.h"
|
|
|
|
|
#include "flow-private.h"
|
|
|
|
|
|
|
|
|
|
#include "util-byte.h"
|
|
|
|
|
|
|
|
|
|
SCEnumCharMap tls_decoder_event_table[ ] = {
|
|
|
|
|
/* TLS protocol messages */
|
|
|
|
|
{ "INVALID_SSLV2_HEADER", TLS_DECODER_EVENT_INVALID_SSLV2_HEADER },
|
|
|
|
@ -68,7 +65,7 @@ SCEnumCharMap tls_decoder_event_table[ ] = {
|
|
|
|
|
{ "MULTIPLE_SNI_EXTENSIONS", TLS_DECODER_EVENT_MULTIPLE_SNI_EXTENSIONS },
|
|
|
|
|
{ "INVALID_SNI_TYPE", TLS_DECODER_EVENT_INVALID_SNI_TYPE },
|
|
|
|
|
{ "INVALID_SNI_LENGTH", TLS_DECODER_EVENT_INVALID_SNI_LENGTH },
|
|
|
|
|
/* Certificates decoding messages */
|
|
|
|
|
/* certificate decoding messages */
|
|
|
|
|
{ "INVALID_CERTIFICATE", TLS_DECODER_EVENT_INVALID_CERTIFICATE },
|
|
|
|
|
{ "CERTIFICATE_MISSING_ELEMENT", TLS_DECODER_EVENT_CERTIFICATE_MISSING_ELEMENT },
|
|
|
|
|
{ "CERTIFICATE_UNKNOWN_ELEMENT", TLS_DECODER_EVENT_CERTIFICATE_UNKNOWN_ELEMENT },
|
|
|
|
@ -87,47 +84,47 @@ typedef struct 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
|
|
|
|
|
#define SSLV3_HEARTBEAT_PROTOCOL 24
|
|
|
|
|
#define SSLV3_CHANGE_CIPHER_SPEC 20
|
|
|
|
|
#define SSLV3_ALERT_PROTOCOL 21
|
|
|
|
|
#define SSLV3_HANDSHAKE_PROTOCOL 22
|
|
|
|
|
#define SSLV3_APPLICATION_PROTOCOL 23
|
|
|
|
|
#define SSLV3_HEARTBEAT_PROTOCOL 24
|
|
|
|
|
|
|
|
|
|
/* 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_NEW_SESSION_TICKET 4
|
|
|
|
|
#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
|
|
|
|
|
#define SSLV3_HS_HELLO_REQUEST 0
|
|
|
|
|
#define SSLV3_HS_CLIENT_HELLO 1
|
|
|
|
|
#define SSLV3_HS_SERVER_HELLO 2
|
|
|
|
|
#define SSLV3_HS_NEW_SESSION_TICKET 4
|
|
|
|
|
#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_HDR_LEN 5
|
|
|
|
|
#define SSLV3_MESSAGE_HDR_LEN 4
|
|
|
|
|
|
|
|
|
|
#define SSLV3_CLIENT_HELLO_VERSION_LEN 2
|
|
|
|
|
#define SSLV3_CLIENT_HELLO_RANDOM_LEN 32
|
|
|
|
|
#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_HDR_LEN 5
|
|
|
|
|
#define SSLV3_MESSAGE_HDR_LEN 4
|
|
|
|
|
|
|
|
|
|
#define SSLV3_CLIENT_HELLO_VERSION_LEN 2
|
|
|
|
|
#define SSLV3_CLIENT_HELLO_RANDOM_LEN 32
|
|
|
|
|
|
|
|
|
|
/* TLS heartbeat protocol types */
|
|
|
|
|
#define TLS_HB_REQUEST 1
|
|
|
|
|
#define TLS_HB_RESPONSE 2
|
|
|
|
|
#define TLS_HB_REQUEST 1
|
|
|
|
|
#define TLS_HB_RESPONSE 2
|
|
|
|
|
|
|
|
|
|
#define HAS_SPACE(n) ((uint32_t)((input) + (n) - (initial_input)) > (uint32_t)(input_len)) ? 0 : 1
|
|
|
|
|
|
|
|
|
@ -291,16 +288,23 @@ end:
|
|
|
|
|
|
|
|
|
|
case SSLV3_HS_CERTIFICATE:
|
|
|
|
|
if (ssl_state->curr_connp->trec == NULL) {
|
|
|
|
|
ssl_state->curr_connp->trec_len = 2 * ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN + 1;
|
|
|
|
|
ssl_state->curr_connp->trec = SCMalloc( ssl_state->curr_connp->trec_len );
|
|
|
|
|
ssl_state->curr_connp->trec_len =
|
|
|
|
|
2 * ssl_state->curr_connp->record_length +
|
|
|
|
|
SSLV3_RECORD_HDR_LEN + 1;
|
|
|
|
|
ssl_state->curr_connp->trec =
|
|
|
|
|
SCMalloc(ssl_state->curr_connp->trec_len);
|
|
|
|
|
}
|
|
|
|
|
if (ssl_state->curr_connp->trec_pos + input_len >= ssl_state->curr_connp->trec_len) {
|
|
|
|
|
ssl_state->curr_connp->trec_len = ssl_state->curr_connp->trec_len + 2 * input_len + 1;
|
|
|
|
|
if (ssl_state->curr_connp->trec_pos + input_len >=
|
|
|
|
|
ssl_state->curr_connp->trec_len) {
|
|
|
|
|
ssl_state->curr_connp->trec_len =
|
|
|
|
|
ssl_state->curr_connp->trec_len + 2 * input_len + 1;
|
|
|
|
|
ptmp = SCRealloc(ssl_state->curr_connp->trec,
|
|
|
|
|
ssl_state->curr_connp->trec_len);
|
|
|
|
|
ssl_state->curr_connp->trec_len);
|
|
|
|
|
|
|
|
|
|
if (unlikely(ptmp == NULL)) {
|
|
|
|
|
SCFree(ssl_state->curr_connp->trec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssl_state->curr_connp->trec = ptmp;
|
|
|
|
|
}
|
|
|
|
|
if (unlikely(ssl_state->curr_connp->trec == NULL)) {
|
|
|
|
@ -312,30 +316,44 @@ end:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t write_len = 0;
|
|
|
|
|
if ((ssl_state->curr_connp->bytes_processed + input_len) > ssl_state->curr_connp->record_length + (SSLV3_RECORD_HDR_LEN)) {
|
|
|
|
|
if ((ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) < ssl_state->curr_connp->bytes_processed) {
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
if ((ssl_state->curr_connp->bytes_processed + input_len) >
|
|
|
|
|
ssl_state->curr_connp->record_length +
|
|
|
|
|
(SSLV3_RECORD_HDR_LEN)) {
|
|
|
|
|
if ((ssl_state->curr_connp->record_length +
|
|
|
|
|
SSLV3_RECORD_HDR_LEN) <
|
|
|
|
|
ssl_state->curr_connp->bytes_processed) {
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
write_len = (ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) - ssl_state->curr_connp->bytes_processed;
|
|
|
|
|
write_len = (ssl_state->curr_connp->record_length +
|
|
|
|
|
SSLV3_RECORD_HDR_LEN) -
|
|
|
|
|
ssl_state->curr_connp->bytes_processed;
|
|
|
|
|
} else {
|
|
|
|
|
write_len = input_len;
|
|
|
|
|
}
|
|
|
|
|
memcpy(ssl_state->curr_connp->trec + ssl_state->curr_connp->trec_pos, initial_input, write_len);
|
|
|
|
|
|
|
|
|
|
memcpy(ssl_state->curr_connp->trec +
|
|
|
|
|
ssl_state->curr_connp->trec_pos, initial_input, write_len);
|
|
|
|
|
ssl_state->curr_connp->trec_pos += write_len;
|
|
|
|
|
|
|
|
|
|
rc = DecodeTLSHandshakeServerCertificate(ssl_state, ssl_state->curr_connp->trec, ssl_state->curr_connp->trec_pos);
|
|
|
|
|
rc = DecodeTLSHandshakeServerCertificate(ssl_state,
|
|
|
|
|
ssl_state->curr_connp->trec,
|
|
|
|
|
ssl_state->curr_connp->trec_pos);
|
|
|
|
|
|
|
|
|
|
if (rc > 0) {
|
|
|
|
|
/* do not return normally if the packet was fragmented:
|
|
|
|
|
* we would return the size of the *entire* message,
|
|
|
|
|
* while we expect only the number of bytes parsed bytes
|
|
|
|
|
* from the *current* fragment
|
|
|
|
|
*/
|
|
|
|
|
we would return the size of the _entire_ message,
|
|
|
|
|
while we expect only the number of bytes parsed bytes
|
|
|
|
|
from the _current_ fragment */
|
|
|
|
|
if (write_len < (ssl_state->curr_connp->trec_pos - rc)) {
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
uint32_t diff = write_len - (ssl_state->curr_connp->trec_pos - rc);
|
|
|
|
|
|
|
|
|
|
uint32_t diff = write_len -
|
|
|
|
|
(ssl_state->curr_connp->trec_pos - rc);
|
|
|
|
|
ssl_state->curr_connp->bytes_processed += diff;
|
|
|
|
|
|
|
|
|
|
ssl_state->curr_connp->trec_pos = 0;
|
|
|
|
@ -362,28 +380,40 @@ end:
|
|
|
|
|
SCLogDebug("new session ticket");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t write_len = 0;
|
|
|
|
|
if ((ssl_state->curr_connp->bytes_processed + input_len) >= ssl_state->curr_connp->record_length + (SSLV3_RECORD_HDR_LEN)) {
|
|
|
|
|
if ((ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) < ssl_state->curr_connp->bytes_processed) {
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
if ((ssl_state->curr_connp->bytes_processed + input_len) >=
|
|
|
|
|
ssl_state->curr_connp->record_length + (SSLV3_RECORD_HDR_LEN)) {
|
|
|
|
|
if ((ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) <
|
|
|
|
|
ssl_state->curr_connp->bytes_processed) {
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
write_len = (ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) - ssl_state->curr_connp->bytes_processed;
|
|
|
|
|
write_len = (ssl_state->curr_connp->record_length +
|
|
|
|
|
SSLV3_RECORD_HDR_LEN) - ssl_state->curr_connp->bytes_processed;
|
|
|
|
|
} else {
|
|
|
|
|
write_len = input_len;
|
|
|
|
|
}
|
|
|
|
|
if ((ssl_state->curr_connp->trec_pos + write_len) >= ssl_state->curr_connp->message_length) {
|
|
|
|
|
if (ssl_state->curr_connp->message_length < ssl_state->curr_connp->trec_pos) {
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
|
|
|
|
|
if ((ssl_state->curr_connp->trec_pos + write_len) >=
|
|
|
|
|
ssl_state->curr_connp->message_length) {
|
|
|
|
|
if (ssl_state->curr_connp->message_length <
|
|
|
|
|
ssl_state->curr_connp->trec_pos) {
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
parsed += ssl_state->curr_connp->message_length - ssl_state->curr_connp->trec_pos;
|
|
|
|
|
parsed += ssl_state->curr_connp->message_length -
|
|
|
|
|
ssl_state->curr_connp->trec_pos;
|
|
|
|
|
|
|
|
|
|
ssl_state->curr_connp->bytes_processed += ssl_state->curr_connp->message_length - ssl_state->curr_connp->trec_pos;
|
|
|
|
|
ssl_state->curr_connp->bytes_processed +=
|
|
|
|
|
ssl_state->curr_connp->message_length -
|
|
|
|
|
ssl_state->curr_connp->trec_pos;
|
|
|
|
|
|
|
|
|
|
ssl_state->curr_connp->handshake_type = 0;
|
|
|
|
|
ssl_state->curr_connp->hs_bytes_processed = 0;
|
|
|
|
@ -405,10 +435,8 @@ static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, uint8_t *input,
|
|
|
|
|
uint8_t *initial_input = input;
|
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
|
|
if (input_len == 0 ||
|
|
|
|
|
ssl_state->curr_connp->bytes_processed ==
|
|
|
|
|
(ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN))
|
|
|
|
|
{
|
|
|
|
|
if (input_len == 0 || ssl_state->curr_connp->bytes_processed ==
|
|
|
|
|
(ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -417,40 +445,41 @@ static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, uint8_t *input,
|
|
|
|
|
ssl_state->curr_connp->handshake_type = *(input++);
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
ssl_state->curr_connp->hs_bytes_processed++;
|
|
|
|
|
if (--input_len == 0 ||
|
|
|
|
|
ssl_state->curr_connp->bytes_processed ==
|
|
|
|
|
(ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN))
|
|
|
|
|
{
|
|
|
|
|
if (--input_len == 0 || ssl_state->curr_connp->bytes_processed ==
|
|
|
|
|
(ssl_state->curr_connp->record_length +
|
|
|
|
|
SSLV3_RECORD_HDR_LEN)) {
|
|
|
|
|
return (input - initial_input);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 1:
|
|
|
|
|
ssl_state->curr_connp->message_length = *(input++) << 16;
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
ssl_state->curr_connp->hs_bytes_processed++;
|
|
|
|
|
if (--input_len == 0 ||
|
|
|
|
|
ssl_state->curr_connp->bytes_processed ==
|
|
|
|
|
(ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN))
|
|
|
|
|
{
|
|
|
|
|
if (--input_len == 0 || ssl_state->curr_connp->bytes_processed ==
|
|
|
|
|
(ssl_state->curr_connp->record_length +
|
|
|
|
|
SSLV3_RECORD_HDR_LEN)) {
|
|
|
|
|
return (input - initial_input);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 2:
|
|
|
|
|
ssl_state->curr_connp->message_length |= *(input++) << 8;
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
ssl_state->curr_connp->hs_bytes_processed++;
|
|
|
|
|
if (--input_len == 0 ||
|
|
|
|
|
ssl_state->curr_connp->bytes_processed ==
|
|
|
|
|
(ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN))
|
|
|
|
|
{
|
|
|
|
|
if (--input_len == 0 || ssl_state->curr_connp->bytes_processed ==
|
|
|
|
|
(ssl_state->curr_connp->record_length +
|
|
|
|
|
SSLV3_RECORD_HDR_LEN)) {
|
|
|
|
|
return (input - initial_input);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 3:
|
|
|
|
|
ssl_state->curr_connp->message_length |= *(input++);
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
ssl_state->curr_connp->hs_bytes_processed++;
|
|
|
|
|
--input_len;
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -458,6 +487,7 @@ static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, uint8_t *input,
|
|
|
|
|
if (retval < 0) {
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
input += retval;
|
|
|
|
|
|
|
|
|
|
return (input - initial_input);
|
|
|
|
@ -468,7 +498,7 @@ static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, uint8_t *input,
|
|
|
|
|
* \brief TLS Heartbeat parser (see RFC 6520)
|
|
|
|
|
*
|
|
|
|
|
* \param sslstate Pointer to the SSL state.
|
|
|
|
|
* \param input Pointer the received input data.
|
|
|
|
|
* \param input Pointer to the received input data.
|
|
|
|
|
* \param input_len Length in bytes of the received data.
|
|
|
|
|
* \param direction 1 toclient, 0 toserver
|
|
|
|
|
*
|
|
|
|
@ -481,10 +511,11 @@ static int SSLv3ParseHeartbeatProtocol(SSLState *ssl_state, uint8_t *input,
|
|
|
|
|
uint16_t payload_len;
|
|
|
|
|
uint16_t padding_len;
|
|
|
|
|
|
|
|
|
|
// expect at least 3 bytes, heartbeat type (1) + length (2)
|
|
|
|
|
/* expect at least 3 bytes: heartbeat type (1) + length (2) */
|
|
|
|
|
if (input_len < 3) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hb_type = *input++;
|
|
|
|
|
|
|
|
|
|
if (!(ssl_state->flags & SSL_AL_FLAG_CHANGE_CIPHER_SPEC)) {
|
|
|
|
@ -499,73 +530,80 @@ static int SSLv3ParseHeartbeatProtocol(SSLState *ssl_state, uint8_t *input,
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_HB_INFLIGHT;
|
|
|
|
|
|
|
|
|
|
if (direction) {
|
|
|
|
|
SCLogDebug("HeartBeat Record type sent in the toclient direction!");
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_HB_SERVER_INIT;
|
|
|
|
|
SCLogDebug("HeartBeat Record type sent in the toclient "
|
|
|
|
|
"direction!");
|
|
|
|
|
} else {
|
|
|
|
|
SCLogDebug("HeartBeat Record type sent in the toserver direction!");
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_HB_CLIENT_INIT;
|
|
|
|
|
SCLogDebug("HeartBeat Record type sent in the toserver "
|
|
|
|
|
"direction!");
|
|
|
|
|
}
|
|
|
|
|
/* if we reach this poin then can we assume that the HB request
|
|
|
|
|
* is encrypted if so lets set the heartbeat record len */
|
|
|
|
|
|
|
|
|
|
/* if we reach this point, then we can assume that the HB request
|
|
|
|
|
is encrypted. If so, let's set the HB record length */
|
|
|
|
|
if (ssl_state->flags & SSL_AL_FLAG_CHANGE_CIPHER_SPEC) {
|
|
|
|
|
ssl_state->hb_record_len = ssl_state->curr_connp->record_length;
|
|
|
|
|
SCLogDebug("Encrypted HeartBeat Request In-flight. Storing len %u", ssl_state->hb_record_len);
|
|
|
|
|
SCLogDebug("Encrypted HeartBeat Request In-flight. Storing len %u",
|
|
|
|
|
ssl_state->hb_record_len);
|
|
|
|
|
return (ssl_state->curr_connp->record_length - 3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
payload_len = (*input++) << 8;
|
|
|
|
|
payload_len |= (*input++);
|
|
|
|
|
|
|
|
|
|
// check that the requested payload length is really present in record (CVE-2014-0160)
|
|
|
|
|
/* check that the requested payload length is really present in
|
|
|
|
|
the record (CVE-2014-0160) */
|
|
|
|
|
if ((uint32_t)(payload_len+3) > ssl_state->curr_connp->record_length) {
|
|
|
|
|
SCLogDebug("We have a short record in HeartBeat Request");
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_OVERFLOW_HEARTBEAT);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_OVERFLOW_HEARTBEAT);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check the padding length
|
|
|
|
|
// it must be at least 16 bytes (RFC 6520, section 4)
|
|
|
|
|
/* check the padding length. It must be at least 16 bytes
|
|
|
|
|
(RFC 6520, section 4) */
|
|
|
|
|
padding_len = ssl_state->curr_connp->record_length - payload_len - 3;
|
|
|
|
|
if (padding_len < 16) {
|
|
|
|
|
SCLogDebug("We have a short record in HeartBeat Request");
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_HEARTBEAT);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_HEARTBEAT);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input_len < payload_len+padding_len) { // we don't have the payload
|
|
|
|
|
/* we don't have the payload */
|
|
|
|
|
if (input_len < payload_len + padding_len) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* OpenSSL still seems to discard multiple in-flight
|
|
|
|
|
* heartbeats although some tools send multiple at once */
|
|
|
|
|
heartbeats although some tools send multiple at once */
|
|
|
|
|
} else if (direction == 1 && (ssl_state->flags & SSL_AL_FLAG_HB_INFLIGHT) &&
|
|
|
|
|
(ssl_state->flags & SSL_AL_FLAG_HB_SERVER_INIT)) {
|
|
|
|
|
SCLogDebug("Multiple In-Flight Server Intiated HeartBeats");
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_HEARTBEAT);
|
|
|
|
|
SCLogDebug("Multiple in-flight server initiated HeartBeats");
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_HEARTBEAT);
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
} else if (direction == 0 && (ssl_state->flags & SSL_AL_FLAG_HB_INFLIGHT) &&
|
|
|
|
|
(ssl_state->flags & SSL_AL_FLAG_HB_CLIENT_INIT)) {
|
|
|
|
|
SCLogDebug("Multiple In-Flight Client Intiated HeartBeats");
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_HEARTBEAT);
|
|
|
|
|
SCLogDebug("Multiple in-flight client initiated HeartBeats");
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_HEARTBEAT);
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
/* we have a HB record in the opposite direction of the request
|
|
|
|
|
* lets reset our flags */
|
|
|
|
|
/* we have a HB record in the opposite direction of the request,
|
|
|
|
|
let's reset our flags */
|
|
|
|
|
ssl_state->flags &= ~SSL_AL_FLAG_HB_INFLIGHT;
|
|
|
|
|
ssl_state->flags &= ~SSL_AL_FLAG_HB_SERVER_INIT;
|
|
|
|
|
ssl_state->flags &= ~SSL_AL_FLAG_HB_CLIENT_INIT;
|
|
|
|
|
|
|
|
|
|
/* if we reach this poin then can we assume that the HB request is
|
|
|
|
|
*encrypted if so lets set the heartbeat record len */
|
|
|
|
|
/* if we reach this point, then we can assume that the HB request
|
|
|
|
|
is encrypted. If so, let's set the HB record length */
|
|
|
|
|
if (ssl_state->flags & SSL_AL_FLAG_CHANGE_CIPHER_SPEC) {
|
|
|
|
|
/* check to see if the encrypted response is longer than the
|
|
|
|
|
* encrypted request */
|
|
|
|
|
if (ssl_state->hb_record_len > 0 &&
|
|
|
|
|
ssl_state->hb_record_len < ssl_state->curr_connp->record_length)
|
|
|
|
|
{
|
|
|
|
|
SCLogDebug("My Heart It's Bleeding.. OpenSSL HeartBleed Response (%u)",
|
|
|
|
|
encrypted request */
|
|
|
|
|
if (ssl_state->hb_record_len > 0 && ssl_state->hb_record_len <
|
|
|
|
|
ssl_state->curr_connp->record_length) {
|
|
|
|
|
SCLogDebug("My heart is bleeding.. OpenSSL HeartBleed response (%u)",
|
|
|
|
|
ssl_state->hb_record_len);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_DATALEAK_HEARTBEAT_MISMATCH);
|
|
|
|
@ -573,11 +611,14 @@ static int SSLv3ParseHeartbeatProtocol(SSLState *ssl_state, uint8_t *input,
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* reset the hb record len in-case we have legit hb's followed by a bad one */
|
|
|
|
|
|
|
|
|
|
/* reset the HB record length in case we have a legit HB followed
|
|
|
|
|
by a bad one */
|
|
|
|
|
ssl_state->hb_record_len = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* skip the heartbeat, 3 bytes were already parsed, e.g |18 03 02| for TLS 1.2 */
|
|
|
|
|
/* skip the HeartBeat, 3 bytes were already parsed,
|
|
|
|
|
e.g |18 03 02| for TLS 1.2 */
|
|
|
|
|
return (ssl_state->curr_connp->record_length - 3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -605,28 +646,33 @@ static int SSLv3ParseRecord(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 1:
|
|
|
|
|
ssl_state->curr_connp->version = *(input++) << 8;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 2:
|
|
|
|
|
ssl_state->curr_connp->version |= *(input++);
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 3:
|
|
|
|
|
ssl_state->curr_connp->record_length = *(input++) << 8;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 4:
|
|
|
|
|
ssl_state->curr_connp->record_length |= *(input++);
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
} /* switch (ssl_state->curr_connp->bytes_processed) */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssl_state->curr_connp->bytes_processed += (input - initial_input);
|
|
|
|
|
|
|
|
|
@ -662,14 +708,16 @@ static int SSLv2ParseRecord(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
ssl_state->curr_connp->record_length |= *(input++);
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 2:
|
|
|
|
|
ssl_state->curr_connp->content_type = *(input++);
|
|
|
|
|
ssl_state->curr_connp->version = SSL_VERSION_2;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
} /* switch (ssl_state->curr_connp->bytes_processed) */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
switch (ssl_state->curr_connp->bytes_processed) {
|
|
|
|
@ -685,6 +733,7 @@ static int SSLv2ParseRecord(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 1:
|
|
|
|
|
ssl_state->curr_connp->record_length |= *(input++);
|
|
|
|
@ -704,8 +753,9 @@ static int SSLv2ParseRecord(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
ssl_state->curr_connp->version = SSL_VERSION_2;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
} /* switch (ssl_state->curr_connp->bytes_processed) */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssl_state->curr_connp->bytes_processed += (input - initial_input);
|
|
|
|
@ -728,12 +778,14 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* the + 1 because, we also 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)) {
|
|
|
|
|
/* 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);
|
|
|
|
|
if (retval == -1) {
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSLV2_HEADER);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSLV2_HEADER);
|
|
|
|
|
return -1;
|
|
|
|
|
} else {
|
|
|
|
|
input += retval;
|
|
|
|
@ -745,26 +797,28 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
return (input - initial_input);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* record_length should never be 0 */
|
|
|
|
|
/* record_length should never be zero */
|
|
|
|
|
if (ssl_state->curr_connp->record_length == 0) {
|
|
|
|
|
SCLogDebug("SSLv2 record length is 0");
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSLV2_HEADER);
|
|
|
|
|
SCLogDebug("SSLv2 record length is zero");
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSLV2_HEADER);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* record_lenghts_length should never be 0 */
|
|
|
|
|
/* record_lenghts_length should never be zero */
|
|
|
|
|
if (ssl_state->curr_connp->record_lengths_length == 0) {
|
|
|
|
|
SCLogDebug("SSLv2 record lengths length is 0");
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSLV2_HEADER);
|
|
|
|
|
SCLogDebug("SSLv2 record lengths length is zero");
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSLV2_HEADER);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (ssl_state->curr_connp->content_type) {
|
|
|
|
|
case SSLV2_MT_ERROR:
|
|
|
|
|
SCLogDebug("SSLV2_MT_ERROR msg_type received. "
|
|
|
|
|
"Error encountered in establishing the sslv2 "
|
|
|
|
|
"session, may be version");
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_ERROR_MSG_ENCOUNTERED);
|
|
|
|
|
SCLogDebug("SSLV2_MT_ERROR msg_type received. Error encountered "
|
|
|
|
|
"in establishing the sslv2 session, may be version");
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_ERROR_MSG_ENCOUNTERED);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -784,6 +838,7 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
if (ssl_state->curr_connp->session_id_length == 0) {
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_SSL_NO_SESSION_ID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
input++;
|
|
|
|
@ -791,40 +846,45 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 5:
|
|
|
|
|
input++;
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 6:
|
|
|
|
|
input++;
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 7:
|
|
|
|
|
input++;
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 8:
|
|
|
|
|
ssl_state->curr_connp->session_id_length = *(input++) << 8;
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case 9:
|
|
|
|
|
ssl_state->curr_connp->session_id_length |= *(input++);
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
} /* switch (ssl_state->curr_connp->bytes_processed) */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ssl_state->curr_connp->record_lengths_length is 3 */
|
|
|
|
|
} else {
|
|
|
|
|
switch (ssl_state->curr_connp->bytes_processed) {
|
|
|
|
|
case 3:
|
|
|
|
@ -837,6 +897,7 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
if (ssl_state->curr_connp->session_id_length == 0) {
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_SSL_NO_SESSION_ID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
input++;
|
|
|
|
@ -844,41 +905,47 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
|
input++;
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 5:
|
|
|
|
|
input++;
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
|
input++;
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 7:
|
|
|
|
|
ssl_state->curr_connp->session_id_length = *(input++) << 8;
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
|
ssl_state->curr_connp->session_id_length |= *(input++);
|
|
|
|
|
ssl_state->curr_connp->bytes_processed++;
|
|
|
|
|
if (--input_len == 0)
|
|
|
|
|
break;
|
|
|
|
|
} /* switch (ssl_state->curr_connp->bytes_processed) */
|
|
|
|
|
} /* else - if (ssl_state->curr_connp->record_lengths_length == 3) */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SSLV2_MT_CLIENT_MASTER_KEY:
|
|
|
|
|
if ( !(ssl_state->flags & SSL_AL_FLAG_SSL_CLIENT_HS)) {
|
|
|
|
|
if (!(ssl_state->flags & SSL_AL_FLAG_SSL_CLIENT_HS)) {
|
|
|
|
|
SCLogDebug("Client hello is not seen before master key "
|
|
|
|
|
"message!!");
|
|
|
|
|
"message!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_SSL_CLIENT_MASTER_KEY;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
@ -890,20 +957,23 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
} else {
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_STATE_CLIENT_KEYX;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case SSLV2_MT_SERVER_VERIFY:
|
|
|
|
|
case SSLV2_MT_SERVER_FINISHED:
|
|
|
|
|
if (direction == 0 &&
|
|
|
|
|
!(ssl_state->curr_connp->content_type & SSLV2_MT_CLIENT_CERTIFICATE)) {
|
|
|
|
|
!(ssl_state->curr_connp->content_type &
|
|
|
|
|
SSLV2_MT_CLIENT_CERTIFICATE)) {
|
|
|
|
|
SCLogDebug("Incorrect SSL Record type sent in the toserver "
|
|
|
|
|
"direction!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case SSLV2_MT_CLIENT_FINISHED:
|
|
|
|
|
case SSLV2_MT_REQUEST_CERTIFICATE:
|
|
|
|
|
/* both ways hello seen */
|
|
|
|
|
/* both client hello and server hello must be seen */
|
|
|
|
|
if ((ssl_state->flags & SSL_AL_FLAG_SSL_CLIENT_HS) &&
|
|
|
|
|
(ssl_state->flags & SSL_AL_FLAG_SSL_SERVER_HS)) {
|
|
|
|
|
(ssl_state->flags & SSL_AL_FLAG_SSL_SERVER_HS)) {
|
|
|
|
|
|
|
|
|
|
if (direction == 0) {
|
|
|
|
|
if (ssl_state->flags & SSL_AL_FLAG_SSL_NO_SESSION_ID) {
|
|
|
|
@ -919,11 +989,12 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((ssl_state->flags & SSL_AL_FLAG_SSL_CLIENT_SSN_ENCRYPTED) &&
|
|
|
|
|
(ssl_state->flags & SSL_AL_FLAG_SSL_SERVER_SSN_ENCRYPTED)) {
|
|
|
|
|
(ssl_state->flags & SSL_AL_FLAG_SSL_SERVER_SSN_ENCRYPTED)) {
|
|
|
|
|
AppLayerParserStateSetFlag(pstate,
|
|
|
|
|
APP_LAYER_PARSER_NO_INSPECTION);
|
|
|
|
|
APP_LAYER_PARSER_NO_INSPECTION);
|
|
|
|
|
if (ssl_config.no_reassemble == 1)
|
|
|
|
|
AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_NO_REASSEMBLY);
|
|
|
|
|
AppLayerParserStateSetFlag(pstate,
|
|
|
|
|
APP_LAYER_PARSER_NO_REASSEMBLY);
|
|
|
|
|
SCLogDebug("SSLv2 No reassembly & inspection has been set");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -938,16 +1009,19 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input_len + ssl_state->curr_connp->bytes_processed >=
|
|
|
|
|
(ssl_state->curr_connp->record_length + ssl_state->curr_connp->record_lengths_length)) {
|
|
|
|
|
/* looks like we have another record after this*/
|
|
|
|
|
(ssl_state->curr_connp->record_length +
|
|
|
|
|
ssl_state->curr_connp->record_lengths_length)) {
|
|
|
|
|
|
|
|
|
|
/* looks like we have another record after this */
|
|
|
|
|
uint32_t diff = ssl_state->curr_connp->record_length +
|
|
|
|
|
ssl_state->curr_connp->record_lengths_length + - ssl_state->curr_connp->bytes_processed;
|
|
|
|
|
ssl_state->curr_connp->record_lengths_length + -
|
|
|
|
|
ssl_state->curr_connp->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 */
|
|
|
|
|
/* we still don't have the entire record for the one we are
|
|
|
|
|
currently parsing */
|
|
|
|
|
} else {
|
|
|
|
|
input += input_len;
|
|
|
|
|
ssl_state->curr_connp->bytes_processed += input_len;
|
|
|
|
@ -965,7 +1039,8 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
if (ssl_state->curr_connp->bytes_processed < SSLV3_RECORD_HDR_LEN) {
|
|
|
|
|
retval = SSLv3ParseRecord(direction, ssl_state, input, input_len);
|
|
|
|
|
if (retval < 0) {
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_TLS_HEADER);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_TLS_HEADER);
|
|
|
|
|
return -1;
|
|
|
|
|
} else {
|
|
|
|
|
parsed += retval;
|
|
|
|
@ -979,17 +1054,18 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
|
|
|
|
|
/* check record version */
|
|
|
|
|
if (ssl_state->curr_connp->version < SSL_VERSION_3 ||
|
|
|
|
|
ssl_state->curr_connp->version > TLS_VERSION_12) {
|
|
|
|
|
ssl_state->curr_connp->version > TLS_VERSION_12) {
|
|
|
|
|
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_RECORD_VERSION);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* record_length should never be 0 */
|
|
|
|
|
/* record_length should never be zero */
|
|
|
|
|
if (ssl_state->curr_connp->record_length == 0) {
|
|
|
|
|
SCLogDebug("SSLv3 Record length is 0");
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_TLS_HEADER);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_TLS_HEADER);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1008,15 +1084,17 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
|
|
|
|
|
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)) {
|
|
|
|
|
(ssl_state->flags & SSL_AL_FLAG_SERVER_CHANGE_CIPHER_SPEC)) {
|
|
|
|
|
/*
|
|
|
|
|
AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_NO_INSPECTION);
|
|
|
|
|
if (ssl_config.no_reassemble == 1)
|
|
|
|
|
AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_NO_REASSEMBLY);
|
|
|
|
|
*/
|
|
|
|
|
AppLayerParserStateSetFlag(pstate,APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD);
|
|
|
|
|
AppLayerParserStateSetFlag(pstate,
|
|
|
|
|
APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
@ -1027,26 +1105,34 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
|
|
|
|
|
if (ssl_state->curr_connp->record_length < 4) {
|
|
|
|
|
SSLParserReset(ssl_state);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
retval = SSLv3ParseHandshakeProtocol(ssl_state, input + parsed, input_len);
|
|
|
|
|
if (retval < 0) {
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_HANDSHAKE_MESSAGE);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_HANDSHAKE_MESSAGE);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
return -1;
|
|
|
|
|
} else {
|
|
|
|
|
if ((uint32_t)retval > input_len) {
|
|
|
|
|
SCLogDebug("Error parsing SSLv3.x. Reseting parser "
|
|
|
|
|
"state. Let's get outta here");
|
|
|
|
|
SCLogDebug("Error parsing SSLv3.x. Reseting parser "
|
|
|
|
|
"state. Let's get outta here");
|
|
|
|
|
SSLParserReset(ssl_state);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parsed += retval;
|
|
|
|
|
input_len -= retval;
|
|
|
|
|
if (ssl_state->curr_connp->bytes_processed == ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) {
|
|
|
|
|
|
|
|
|
|
if (ssl_state->curr_connp->bytes_processed ==
|
|
|
|
|
ssl_state->curr_connp->record_length +
|
|
|
|
|
SSLV3_RECORD_HDR_LEN) {
|
|
|
|
|
SSLParserReset(ssl_state);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1056,23 +1142,31 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SSLV3_HEARTBEAT_PROTOCOL:
|
|
|
|
|
retval = SSLv3ParseHeartbeatProtocol(ssl_state, input + parsed, input_len, direction);
|
|
|
|
|
retval = SSLv3ParseHeartbeatProtocol(ssl_state, input + parsed,
|
|
|
|
|
input_len, direction);
|
|
|
|
|
if (retval < 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
/* \todo fix the event from invalid rule to unknown rule */
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_RECORD_TYPE);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_RECORD_TYPE);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input_len + ssl_state->curr_connp->bytes_processed >= ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) {
|
|
|
|
|
if ((ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) < ssl_state->curr_connp->bytes_processed) {
|
|
|
|
|
/* defensive checks. Something's wrong. */
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
if (input_len + ssl_state->curr_connp->bytes_processed >=
|
|
|
|
|
ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) {
|
|
|
|
|
if ((ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) <
|
|
|
|
|
ssl_state->curr_connp->bytes_processed) {
|
|
|
|
|
/* defensive checks. Something is wrong. */
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1080,13 +1174,14 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
|
|
|
|
|
AppLayerParserTriggerRawStreamReassembly(ssl_state->f);
|
|
|
|
|
|
|
|
|
|
/* looks like we have another record */
|
|
|
|
|
uint32_t diff = ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN - ssl_state->curr_connp->bytes_processed;
|
|
|
|
|
uint32_t diff = ssl_state->curr_connp->record_length +
|
|
|
|
|
SSLV3_RECORD_HDR_LEN - ssl_state->curr_connp->bytes_processed;
|
|
|
|
|
parsed += diff;
|
|
|
|
|
SSLParserReset(ssl_state);
|
|
|
|
|
return parsed;
|
|
|
|
|
|
|
|
|
|
/* we still don't have the entire record for the one we are
|
|
|
|
|
* currently parsing */
|
|
|
|
|
/* we still don't have the entire record for the one we are
|
|
|
|
|
currently parsing */
|
|
|
|
|
} else {
|
|
|
|
|
parsed += input_len;
|
|
|
|
|
ssl_state->curr_connp->bytes_processed += input_len;
|
|
|
|
@ -1126,7 +1221,8 @@ static int SSLDecode(Flow *f, uint8_t direction, void *alstate, AppLayerParserSt
|
|
|
|
|
|
|
|
|
|
ssl_state->f = f;
|
|
|
|
|
|
|
|
|
|
if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
|
|
|
|
|
if (input == NULL &&
|
|
|
|
|
AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
|
|
|
|
|
SCReturnInt(1);
|
|
|
|
|
} else if (input == NULL || input_len == 0) {
|
|
|
|
|
SCReturnInt(-1);
|
|
|
|
@ -1140,16 +1236,16 @@ static int SSLDecode(Flow *f, uint8_t direction, void *alstate, AppLayerParserSt
|
|
|
|
|
/* if we have more than one record */
|
|
|
|
|
while (input_len > 0) {
|
|
|
|
|
if (counter++ == 30) {
|
|
|
|
|
SCLogDebug("Looks like we have looped quite a bit. Reset state "
|
|
|
|
|
SCLogDebug("Looks like we have looped quite a bit. Reset state "
|
|
|
|
|
"and get out of here");
|
|
|
|
|
SSLParserReset(ssl_state);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ssl_state->bytes_processed is 0 for a
|
|
|
|
|
* fresh record or positive to indicate a record currently being
|
|
|
|
|
* parsed */
|
|
|
|
|
/* ssl_state->bytes_processed is zero for a fresh record or
|
|
|
|
|
positive to indicate a record currently being parsed */
|
|
|
|
|
switch (ssl_state->curr_connp->bytes_processed) {
|
|
|
|
|
/* fresh record */
|
|
|
|
|
case 0:
|
|
|
|
@ -1160,10 +1256,11 @@ static int SSLDecode(Flow *f, uint8_t direction, void *alstate, AppLayerParserSt
|
|
|
|
|
retval = SSLv2Decode(direction, ssl_state, pstate, input,
|
|
|
|
|
input_len);
|
|
|
|
|
if (retval < 0) {
|
|
|
|
|
SCLogDebug("Error parsing SSLv2.x. Reseting parser "
|
|
|
|
|
"state. Let's get outta here");
|
|
|
|
|
SCLogDebug("Error parsing SSLv2.x. Reseting parser "
|
|
|
|
|
"state. Let's get outta here");
|
|
|
|
|
SSLParserReset(ssl_state);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
return -1;
|
|
|
|
|
} else {
|
|
|
|
|
input_len -= retval;
|
|
|
|
@ -1172,15 +1269,16 @@ static int SSLDecode(Flow *f, uint8_t direction, void *alstate, AppLayerParserSt
|
|
|
|
|
} else {
|
|
|
|
|
SCLogDebug("SSLv3.x detected");
|
|
|
|
|
/* we will keep it this way till our record parser tells
|
|
|
|
|
* us what exact version it is */
|
|
|
|
|
us what exact version this is */
|
|
|
|
|
ssl_state->curr_connp->version = TLS_VERSION_UNKNOWN;
|
|
|
|
|
retval = SSLv3Decode(direction, ssl_state, pstate, input,
|
|
|
|
|
input_len);
|
|
|
|
|
if (retval < 0) {
|
|
|
|
|
SCLogDebug("Error parsing SSLv3.x. Reseting parser "
|
|
|
|
|
"state. Let's get outta here");
|
|
|
|
|
SCLogDebug("Error parsing SSLv3.x. Reseting parser "
|
|
|
|
|
"state. Let's get outta here");
|
|
|
|
|
SSLParserReset(ssl_state);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
AppLayerDecoderEventsSetEvent(ssl_state->f,
|
|
|
|
|
TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
return -1;
|
|
|
|
|
} else {
|
|
|
|
|
input_len -= retval;
|
|
|
|
|