diff options
Diffstat (limited to 'ssl/d1_both.c')
-rw-r--r-- | ssl/d1_both.c | 162 |
1 files changed, 94 insertions, 68 deletions
diff --git a/ssl/d1_both.c b/ssl/d1_both.c index 2e4250f..1b9d64b 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -156,9 +156,8 @@ static unsigned char bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe static unsigned char bitmask_end_values[] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f}; /* XDTLS: figure out the right values */ -static unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28}; +static const unsigned int g_probable_mtu[] = {1500, 512, 256}; -static unsigned int dtls1_guess_mtu(unsigned int curr_mtu); static void dtls1_fix_message_header(SSL *s, unsigned long frag_off, unsigned long frag_len); static unsigned char *dtls1_write_message_header(SSL *s, @@ -211,8 +210,7 @@ dtls1_hm_fragment_new(unsigned long frag_len, int reassembly) return frag; } -static void -dtls1_hm_fragment_free(hm_fragment *frag) +void dtls1_hm_fragment_free(hm_fragment *frag) { if (frag->msg_header.is_ccs) @@ -225,53 +223,50 @@ dtls1_hm_fragment_free(hm_fragment *frag) OPENSSL_free(frag); } -/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */ -int dtls1_do_write(SSL *s, int type) - { - int ret; - int curr_mtu; - unsigned int len, frag_off, mac_size, blocksize; +static int dtls1_query_mtu(SSL *s) +{ + if(s->d1->link_mtu) + { + s->d1->mtu = s->d1->link_mtu-BIO_dgram_get_mtu_overhead(SSL_get_wbio(s)); + s->d1->link_mtu = 0; + } /* AHA! Figure out the MTU, and stick to the right size */ - if (s->d1->mtu < dtls1_min_mtu() && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) + if (s->d1->mtu < dtls1_min_mtu(s)) { - s->d1->mtu = - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); - - /* I've seen the kernel return bogus numbers when it doesn't know - * (initial write), so just make sure we have a reasonable number */ - if (s->d1->mtu < dtls1_min_mtu()) + if(!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) { - s->d1->mtu = 0; - s->d1->mtu = dtls1_guess_mtu(s->d1->mtu); - BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU, - s->d1->mtu, NULL); + s->d1->mtu = + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); + + /* I've seen the kernel return bogus numbers when it doesn't know + * (initial write), so just make sure we have a reasonable number */ + if (s->d1->mtu < dtls1_min_mtu(s)) + { + /* Set to min mtu */ + s->d1->mtu = dtls1_min_mtu(s); + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU, + s->d1->mtu, NULL); + } } + else + return 0; } -#if 0 - mtu = s->d1->mtu; - - fprintf(stderr, "using MTU = %d\n", mtu); - - mtu -= (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH); - - curr_mtu = mtu - BIO_wpending(SSL_get_wbio(s)); + return 1; +} - if ( curr_mtu > 0) - mtu = curr_mtu; - else if ( ( ret = BIO_flush(SSL_get_wbio(s))) <= 0) - return ret; +/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */ +int dtls1_do_write(SSL *s, int type) + { + int ret; + unsigned int curr_mtu; + int retry = 1; + unsigned int len, frag_off, mac_size, blocksize, used_len; - if ( BIO_wpending(SSL_get_wbio(s)) + s->init_num >= mtu) - { - ret = BIO_flush(SSL_get_wbio(s)); - if ( ret <= 0) - return ret; - mtu = s->d1->mtu - (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH); - } -#endif + if(!dtls1_query_mtu(s)) + return -1; - OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu()); /* should have something reasonable now */ + OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu(s)); /* should have something reasonable now */ if ( s->init_off == 0 && type == SSL3_RT_HANDSHAKE) OPENSSL_assert(s->init_num == @@ -289,10 +284,15 @@ int dtls1_do_write(SSL *s, int type) blocksize = 0; frag_off = 0; - while( s->init_num) + /* s->init_num shouldn't ever be < 0...but just in case */ + while(s->init_num > 0) { - curr_mtu = s->d1->mtu - BIO_wpending(SSL_get_wbio(s)) - - DTLS1_RT_HEADER_LENGTH - mac_size - blocksize; + used_len = BIO_wpending(SSL_get_wbio(s)) + DTLS1_RT_HEADER_LENGTH + + mac_size + blocksize; + if(s->d1->mtu > used_len) + curr_mtu = s->d1->mtu - used_len; + else + curr_mtu = 0; if ( curr_mtu <= DTLS1_HM_HEADER_LENGTH) { @@ -300,15 +300,27 @@ int dtls1_do_write(SSL *s, int type) ret = BIO_flush(SSL_get_wbio(s)); if ( ret <= 0) return ret; - curr_mtu = s->d1->mtu - DTLS1_RT_HEADER_LENGTH - - mac_size - blocksize; + used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize; + if(s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH) + { + curr_mtu = s->d1->mtu - used_len; + } + else + { + /* Shouldn't happen */ + return -1; + } } - if ( s->init_num > curr_mtu) + /* We just checked that s->init_num > 0 so this cast should be safe */ + if (((unsigned int)s->init_num) > curr_mtu) len = curr_mtu; else len = s->init_num; + /* Shouldn't ever happen */ + if(len > INT_MAX) + len = INT_MAX; /* XDTLS: this function is too long. split out the CCS part */ if ( type == SSL3_RT_HANDSHAKE) @@ -319,18 +331,29 @@ int dtls1_do_write(SSL *s, int type) s->init_off -= DTLS1_HM_HEADER_LENGTH; s->init_num += DTLS1_HM_HEADER_LENGTH; - if ( s->init_num > curr_mtu) + /* We just checked that s->init_num > 0 so this cast should be safe */ + if (((unsigned int)s->init_num) > curr_mtu) len = curr_mtu; else len = s->init_num; } + /* Shouldn't ever happen */ + if(len > INT_MAX) + len = INT_MAX; + + if ( len < DTLS1_HM_HEADER_LENGTH ) + { + /* + * len is so small that we really can't do anything sensible + * so fail + */ + return -1; + } dtls1_fix_message_header(s, frag_off, len - DTLS1_HM_HEADER_LENGTH); dtls1_write_message_header(s, (unsigned char *)&s->init_buf->data[s->init_off]); - - OPENSSL_assert(len >= DTLS1_HM_HEADER_LENGTH); } ret=dtls1_write_bytes(s,type,&s->init_buf->data[s->init_off], @@ -343,12 +366,23 @@ int dtls1_do_write(SSL *s, int type) * is fine and wait for an alert to handle the * retransmit */ - if ( BIO_ctrl(SSL_get_wbio(s), + if ( retry && BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0 ) - s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), - BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); + { + if(!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) + { + if(!dtls1_query_mtu(s)) + return -1; + /* Have one more go */ + retry = 0; + } + else + return -1; + } else + { return(-1); + } } else { @@ -1412,28 +1446,20 @@ dtls1_write_message_header(SSL *s, unsigned char *p) return p; } -unsigned int -dtls1_min_mtu(void) +unsigned int +dtls1_link_min_mtu(void) { return (g_probable_mtu[(sizeof(g_probable_mtu) / sizeof(g_probable_mtu[0])) - 1]); } -static unsigned int -dtls1_guess_mtu(unsigned int curr_mtu) +unsigned int +dtls1_min_mtu(SSL *s) { - unsigned int i; - - if ( curr_mtu == 0 ) - return g_probable_mtu[0] ; - - for ( i = 0; i < sizeof(g_probable_mtu)/sizeof(g_probable_mtu[0]); i++) - if ( curr_mtu > g_probable_mtu[i]) - return g_probable_mtu[i]; - - return curr_mtu; + return dtls1_link_min_mtu()-BIO_dgram_get_mtu_overhead(SSL_get_wbio(s)); } + void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr) { |