diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index bf20c37ac..7474c14ab 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -779,8 +779,8 @@ struct _ssl_context size_t in_msglen; /*!< record header: message length */ size_t in_left; /*!< amount of data read so far */ #if defined(POLARSSL_SSL_PROTO_DTLS) - size_t next_record_offset; /*!< offset of the next record in datagram, - or 0 if none */ + size_t next_record_offset; /*!< offset of the next record in datagram + (equal to in_left if none) */ #endif size_t in_hslen; /*!< current handshake message length */ diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 95fcdfbef..39d93f9c3 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1832,7 +1832,7 @@ static int ssl_decompress_buf( ssl_context *ssl ) * with datagram transport (DTLS) on success ssl->in_left >= nb_want, * since we always read a whole datagram at once. * - * For DTLS, It is up to the caller to set ssl->next_record_offset when + * For DTLS, it is up to the caller to set ssl->next_record_offset when * they're done reading a record. */ int ssl_fetch_input( ssl_context *ssl, size_t nb_want ) @@ -2289,6 +2289,31 @@ static int ssl_reassemble_dtls_handshake( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "handshake message completed" ) ); + if( ssl->in_left > ssl->next_record_offset ) + { + /* + * We've got more data in the buffer after the current record, + * that we don't want to overwrite. Move it before writing the + * reassembled message, and adjust in_left and next_record_offset. + */ + unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset; + unsigned char *new_remain = ssl->in_msg + ssl->in_hslen; + size_t remain_len = ssl->in_left - ssl->next_record_offset; + + /* First compute and check new lengths */ + ssl->next_record_offset = new_remain - ssl->in_hdr; + ssl->in_left = ssl->next_record_offset + remain_len; + + if( ssl->in_left > SSL_BUFFER_LEN - + (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) ); + return( POLARSSL_ERR_SSL_BUFFER_TOO_SMALL ); + } + + memmove( new_remain, cur_remain, remain_len ); + } + memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen ); polarssl_free( ssl->handshake->hs_msg ); @@ -2409,6 +2434,8 @@ int ssl_read_record( ssl_context *ssl ) return( ret ); } + SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, ssl_hdr_len( ssl ) ); + ssl->in_msgtype = ssl->in_hdr[0]; ssl->in_msglen = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; ssl_read_version( &major_ver, &minor_ver, ssl->transport, ssl->in_hdr + 1 ); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index d5b1a296d..13847dd9b 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1988,27 +1988,26 @@ run_test "DTLS reassembly: no fragmentation (openssl server)" \ -C "found fragmented DTLS handshake message" \ -C "error" -# Not working yet -#run_test "DTLS reassembly: fragmentation (openssl server)" \ -# "$O_SRV -dtls1 -mtu 256" \ -# "$P_CLI dtls=1 debug_level=2" \ -# 0 \ -# -c "found fragmented DTLS handshake message" \ -# -C "error" -# -#run_test "DTLS reassembly: fragmentation (openssl server)" \ -# "$O_SRV -dtls1 -mtu 256" \ -# "$P_CLI dtls=1 debug_level=2" \ -# 0 \ -# -c "found fragmented DTLS handshake message" \ -# -C "error" -# -#run_test "DTLS reassembly: fragmentation, nbio (openssl server)" \ -# "$O_SRV -dtls1 -mtu 256" \ -# "$P_CLI dtls=1 nbio=2 debug_level=2" \ -# 0 \ -# -c "found fragmented DTLS handshake message" \ -# -C "error" +run_test "DTLS reassembly: fragmentation (openssl server)" \ + "$O_SRV -dtls1 -mtu 256" \ + "$P_CLI dtls=1 debug_level=2" \ + 0 \ + -c "found fragmented DTLS handshake message" \ + -C "error" + +run_test "DTLS reassembly: fragmentation (openssl server)" \ + "$O_SRV -dtls1 -mtu 256" \ + "$P_CLI dtls=1 debug_level=2" \ + 0 \ + -c "found fragmented DTLS handshake message" \ + -C "error" + +run_test "DTLS reassembly: fragmentation, nbio (openssl server)" \ + "$O_SRV -dtls1 -mtu 256" \ + "$P_CLI dtls=1 nbio=2 debug_level=2" \ + 0 \ + -c "found fragmented DTLS handshake message" \ + -C "error" # TODO: fragmentation with renegotiation, openssl + gnutls