Update trec_len, trec_pos to 32 bits from 16 bits.
Handle handshakes that are fragmented across records.
pull/306/merge
Anoop Saldanha 14 years ago committed by Victor Julien
parent c6d50764e5
commit ce7d78dd69

@ -112,7 +112,6 @@ SslConfig ssl_config;
static void SSLParserReset(SSLState *ssl_state) static void SSLParserReset(SSLState *ssl_state)
{ {
ssl_state->curr_connp->bytes_processed = 0; ssl_state->curr_connp->bytes_processed = 0;
ssl_state->curr_connp->message_start = 0;
} }
static int SSLv3ParseHandshakeType(SSLState *ssl_state, uint8_t *input, static int SSLv3ParseHandshakeType(SSLState *ssl_state, uint8_t *input,
@ -158,10 +157,16 @@ static int SSLv3ParseHandshakeType(SSLState *ssl_state, uint8_t *input,
/* error, skip packet */ /* error, skip packet */
parsed += input_len; parsed += input_len;
ssl_state->curr_connp->bytes_processed += input_len; ssl_state->curr_connp->bytes_processed += input_len;
break; 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)) {
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, input_len); memcpy(ssl_state->curr_connp->trec + ssl_state->curr_connp->trec_pos, initial_input, write_len);
ssl_state->curr_connp->trec_pos += input_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) { if (rc > 0) {
@ -170,10 +175,21 @@ static int SSLv3ParseHandshakeType(SSLState *ssl_state, uint8_t *input,
* while we expect only the number of bytes parsed bytes * while we expect only the number of bytes parsed bytes
* from the *current* fragment * from the *current* fragment
*/ */
uint32_t diff = input_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->bytes_processed += diff;
ssl_state->curr_connp->trec_pos = 0;
ssl_state->curr_connp->handshake_type = 0;
ssl_state->curr_connp->hs_bytes_processed = 0;
ssl_state->curr_connp->message_length = 0;
return diff; return diff;
} else {
ssl_state->curr_connp->bytes_processed += write_len;
parsed += write_len;
return parsed;
} }
break; break;
case SSLV3_HS_HELLO_REQUEST: case SSLV3_HS_HELLO_REQUEST:
case SSLV3_HS_CERTIFICATE_REQUEST: case SSLV3_HS_CERTIFICATE_REQUEST:
@ -186,18 +202,29 @@ static int SSLv3ParseHandshakeType(SSLState *ssl_state, uint8_t *input,
break; break;
} }
/* skip the rest of the current message */ uint32_t write_len = 0;
uint32_t next_msg_offset = ssl_state->curr_connp->message_start + SSLV3_MESSAGE_HDR_LEN + ssl_state->curr_connp->message_length; if ((ssl_state->curr_connp->bytes_processed + input_len) >= ssl_state->curr_connp->record_length + (SSLV3_RECORD_HDR_LEN)) {
if (ssl_state->curr_connp->bytes_processed + input_len < next_msg_offset) { write_len = (ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) - ssl_state->curr_connp->bytes_processed;
/* we don't have enough data */ } else {
parsed += input_len; write_len = input_len;
ssl_state->curr_connp->bytes_processed += input_len; }
if ((ssl_state->curr_connp->trec_pos + write_len) >= ssl_state->curr_connp->message_length) {
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->handshake_type = 0;
ssl_state->curr_connp->hs_bytes_processed = 0;
ssl_state->curr_connp->message_length = 0;
ssl_state->curr_connp->trec_pos = 0;
return parsed;
} else {
ssl_state->curr_connp->trec_pos += write_len;
ssl_state->curr_connp->bytes_processed += write_len;
parsed += write_len;
return parsed; return parsed;
} }
uint32_t diff = next_msg_offset - ssl_state->curr_connp->bytes_processed;
parsed += diff;
ssl_state->curr_connp->bytes_processed += diff;
return parsed;
} }
static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, uint8_t *input, static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, uint8_t *input,
@ -210,29 +237,29 @@ static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, uint8_t *input,
return 0; return 0;
} }
if (ssl_state->curr_connp->message_start == 0) { switch (ssl_state->curr_connp->hs_bytes_processed) {
ssl_state->curr_connp->message_start = SSLV3_RECORD_HDR_LEN;
}
switch (ssl_state->curr_connp->bytes_processed - ssl_state->curr_connp->message_start) {
case 0: case 0:
ssl_state->curr_connp->handshake_type = *(input++); ssl_state->curr_connp->handshake_type = *(input++);
ssl_state->curr_connp->bytes_processed++; ssl_state->curr_connp->bytes_processed++;
ssl_state->curr_connp->hs_bytes_processed++;
if (--input_len == 0) if (--input_len == 0)
break; break;
case 1: case 1:
ssl_state->curr_connp->message_length = *(input++) << 16; ssl_state->curr_connp->message_length = *(input++) << 16;
ssl_state->curr_connp->bytes_processed++; ssl_state->curr_connp->bytes_processed++;
ssl_state->curr_connp->hs_bytes_processed++;
if (--input_len == 0) if (--input_len == 0)
break; break;
case 2: case 2:
ssl_state->curr_connp->message_length |= *(input++) << 8; ssl_state->curr_connp->message_length |= *(input++) << 8;
ssl_state->curr_connp->bytes_processed++; ssl_state->curr_connp->bytes_processed++;
ssl_state->curr_connp->hs_bytes_processed++;
if (--input_len == 0) if (--input_len == 0)
break; break;
case 3: case 3:
ssl_state->curr_connp->message_length |= *(input++); ssl_state->curr_connp->message_length |= *(input++);
ssl_state->curr_connp->bytes_processed++; ssl_state->curr_connp->bytes_processed++;
ssl_state->curr_connp->hs_bytes_processed++;
if (--input_len == 0) if (--input_len == 0)
break; break;
} }
@ -243,15 +270,6 @@ static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, uint8_t *input,
} }
input += retval; input += retval;
uint32_t next_msg_offset = ssl_state->curr_connp->message_start + SSLV3_MESSAGE_HDR_LEN + ssl_state->curr_connp->message_length;
if (ssl_state->curr_connp->bytes_processed == next_msg_offset) {
ssl_state->curr_connp->handshake_type = 0;
ssl_state->curr_connp->message_length = 0;
ssl_state->curr_connp->message_start = next_msg_offset;
} else if (ssl_state->curr_connp->bytes_processed > next_msg_offset) {
return -1;
}
return (input - initial_input); return (input - initial_input);
} }
@ -648,6 +666,11 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
if (ssl_state->flags & SSL_AL_FLAG_CHANGE_CIPHER_SPEC) if (ssl_state->flags & SSL_AL_FLAG_CHANGE_CIPHER_SPEC)
break; break;
if (ssl_state->curr_connp->record_length < 4) {
SSLParserReset(ssl_state);
return -1;
}
retval = SSLv3ParseHandshakeProtocol(ssl_state, input + parsed, input_len); retval = SSLv3ParseHandshakeProtocol(ssl_state, input + parsed, input_len);
if (retval < 0) { if (retval < 0) {
AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_HANDSHAKE_MESSAGE); AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_HANDSHAKE_MESSAGE);
@ -2251,11 +2274,6 @@ static int SSLParserTest15(void)
}; };
uint32_t buf1_len = sizeof(buf1); uint32_t buf1_len = sizeof(buf1);
uint8_t buf2[] = {
0x16, 0x03, 0x00, 0x00, 0x00,
};
uint32_t buf2_len = sizeof(buf2);
TcpSession ssn; TcpSession ssn;
memset(&f, 0, sizeof(f)); memset(&f, 0, sizeof(f));
@ -2265,26 +2283,12 @@ static int SSLParserTest15(void)
StreamTcpInitConfig(TRUE); StreamTcpInitConfig(TRUE);
int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len);
if (r != 0) { 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); printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0; result = 0;
goto end; goto end;
} }
SSLState *ssl_state = f.alstate;
if (ssl_state == NULL) {
printf("no tls state: ");
result = 0;
goto end;
}
end: end:
StreamTcpFreeConfig(TRUE); StreamTcpFreeConfig(TRUE);
return result; return result;
@ -2303,11 +2307,6 @@ static int SSLParserTest16(void)
}; };
uint32_t buf1_len = sizeof(buf1); uint32_t buf1_len = sizeof(buf1);
uint8_t buf2[] = {
0x16, 0x03, 0x00, 0x00, 0x00,
};
uint32_t buf2_len = sizeof(buf2);
TcpSession ssn; TcpSession ssn;
memset(&f, 0, sizeof(f)); memset(&f, 0, sizeof(f));
@ -2317,26 +2316,12 @@ static int SSLParserTest16(void)
StreamTcpInitConfig(TRUE); StreamTcpInitConfig(TRUE);
int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len);
if (r != 0) { 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); printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0; result = 0;
goto end; goto end;
} }
SSLState *ssl_state = f.alstate;
if (ssl_state == NULL) {
printf("no tls state: ");
result = 0;
goto end;
}
end: end:
StreamTcpFreeConfig(TRUE); StreamTcpFreeConfig(TRUE);
return result; return result;
@ -2355,11 +2340,6 @@ static int SSLParserTest17(void)
}; };
uint32_t buf1_len = sizeof(buf1); uint32_t buf1_len = sizeof(buf1);
uint8_t buf2[] = {
0x16, 0x03, 0x00, 0x00, 0x00,
};
uint32_t buf2_len = sizeof(buf2);
TcpSession ssn; TcpSession ssn;
memset(&f, 0, sizeof(f)); memset(&f, 0, sizeof(f));
@ -2369,26 +2349,12 @@ static int SSLParserTest17(void)
StreamTcpInitConfig(TRUE); StreamTcpInitConfig(TRUE);
int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len);
if (r != 0) { 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); printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0; result = 0;
goto end; goto end;
} }
SSLState *ssl_state = f.alstate;
if (ssl_state == NULL) {
printf("no tls state: ");
result = 0;
goto end;
}
end: end:
StreamTcpFreeConfig(TRUE); StreamTcpFreeConfig(TRUE);
return result; return result;
@ -2511,19 +2477,12 @@ static int SSLParserTest20(void)
StreamTcpInitConfig(TRUE); StreamTcpInitConfig(TRUE);
int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len); int r = AppLayerParse(NULL, &f, ALPROTO_TLS, STREAM_TOSERVER, buf1, buf1_len);
if (r != 0) { if (r == 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0; result = 0;
goto end; goto end;
} }
SSLState *ssl_state = f.alstate;
if (ssl_state == NULL) {
printf("no tls state: ");
result = 0;
goto end;
}
end: end:
StreamTcpFreeConfig(TRUE); StreamTcpFreeConfig(TRUE);
return result; return result;

@ -105,6 +105,8 @@ typedef struct SSLStateConnp_ {
/* the no of bytes processed in the currently parsed record */ /* the no of bytes processed in the currently parsed record */
uint16_t bytes_processed; uint16_t bytes_processed;
/* the no of bytes processed in the currently parsed handshake */
uint16_t hs_bytes_processed;
/* sslv2 client hello session id length */ /* sslv2 client hello session id length */
uint16_t session_id_length; uint16_t session_id_length;
@ -123,8 +125,8 @@ typedef struct SSLStateConnp_ {
/* buffer for the tls record. /* buffer for the tls record.
* We use a malloced buffer, if the record is fragmented */ * We use a malloced buffer, if the record is fragmented */
uint8_t *trec; uint8_t *trec;
uint16_t trec_len; uint32_t trec_len;
uint16_t trec_pos; uint32_t trec_pos;
} SSLStateConnp; } SSLStateConnp;
/** /**

Loading…
Cancel
Save