X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=ssl%2Fd1_both.c;h=d11d6d5888281165e4b5b12ed1223a9dab891347;hb=4b06d778ad71fc3f7bde0e607e865e7c5e07fafc;hp=913098361143506950154849ce0f8e58c49c8806;hpb=e5fa864f62c096536d700d977a5eb924ad293304;p=oweals%2Fopenssl.git diff --git a/ssl/d1_both.c b/ssl/d1_both.c index 9130983611..d11d6d5888 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -300,7 +300,7 @@ int dtls1_do_write(SSL *s, int type) const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; int xlen; - if (frag_off == 0) + if (frag_off == 0 && s->version != DTLS1_BAD_VER) { /* reconstruct message header is if it * is being sent in single fragment */ @@ -407,8 +407,10 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) s2n (msg_hdr->seq,p); l2n3(0,p); l2n3(msg_len,p); - p -= DTLS1_HM_HEADER_LENGTH; - msg_len += DTLS1_HM_HEADER_LENGTH; + if (s->version != DTLS1_BAD_VER) { + p -= DTLS1_HM_HEADER_LENGTH; + msg_len += DTLS1_HM_HEADER_LENGTH; + } ssl3_finish_mac(s, p, msg_len); if (s->msg_callback) @@ -517,6 +519,7 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) if ( s->d1->handshake_read_seq == frag->msg_header.seq) { + unsigned long frag_len = frag->msg_header.frag_len; pqueue_pop(s->d1->buffered_messages); al=dtls1_preprocess_fragment(s,&frag->msg_header,max); @@ -534,7 +537,7 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) if (al==0) { *ok = 1; - return frag->msg_header.frag_len; + return frag_len; } ssl3_send_alert(s,SSL3_AL_FATAL,al); @@ -559,7 +562,20 @@ dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok) if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len) goto err; - if (msg_hdr->seq <= s->d1->handshake_read_seq) + /* Try to find item in queue, to prevent duplicate entries */ + memset(seq64be,0,sizeof(seq64be)); + seq64be[6] = (unsigned char) (msg_hdr->seq>>8); + seq64be[7] = (unsigned char) msg_hdr->seq; + item = pqueue_find(s->d1->buffered_messages, seq64be); + + /* Discard the message if sequence number was already there, is + * too far in the future, already in the queue or if we received + * a FINISHED before the SERVER_HELLO, which then must be a stale + * retransmit. + */ + if (msg_hdr->seq <= s->d1->handshake_read_seq || + msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL || + (s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED)) { unsigned char devnull [256]; @@ -775,6 +791,13 @@ int dtls1_send_change_cipher_spec(SSL *s, int a, int b) *p++=SSL3_MT_CCS; s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; s->init_num=DTLS1_CCS_HEADER_LENGTH; + + if (s->version == DTLS1_BAD_VER) { + s->d1->next_handshake_write_seq++; + s2n(s->d1->handshake_write_seq,p); + s->init_num+=2; + } + s->init_off=0; dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, @@ -790,14 +813,30 @@ int dtls1_send_change_cipher_spec(SSL *s, int a, int b) return(dtls1_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC)); } +static int dtls1_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) + { + int n; + unsigned char *p; + + n=i2d_X509(x,NULL); + if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3))) + { + SSLerr(SSL_F_DTLS1_ADD_CERT_TO_BUF,ERR_R_BUF_LIB); + return 0; + } + p=(unsigned char *)&(buf->data[*l]); + l2n3(n,p); + i2d_X509(x,&p); + *l+=n+3; + + return 1; + } unsigned long dtls1_output_cert_chain(SSL *s, X509 *x) { unsigned char *p; - int n,i; + int i; unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH; BUF_MEM *buf; - X509_STORE_CTX xs_ctx; - X509_OBJECT obj; /* TLSv1 sends a chain with nothing in it, instead of an alert */ buf=s->init_buf; @@ -808,54 +847,33 @@ unsigned long dtls1_output_cert_chain(SSL *s, X509 *x) } if (x != NULL) { - if(!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL)) - { - SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); - return(0); - } - - for (;;) - { - n=i2d_X509(x,NULL); - if (!BUF_MEM_grow_clean(buf,(n+l+3))) - { - SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); - return(0); - } - p=(unsigned char *)&(buf->data[l]); - l2n3(n,p); - i2d_X509(x,&p); - l+=n+3; - if (X509_NAME_cmp(X509_get_subject_name(x), - X509_get_issuer_name(x)) == 0) break; - - i=X509_STORE_get_by_subject(&xs_ctx,X509_LU_X509, - X509_get_issuer_name(x),&obj); - if (i <= 0) break; - x=obj.data.x509; - /* Count is one too high since the X509_STORE_get uped the - * ref count */ - X509_free(x); - } - - X509_STORE_CTX_cleanup(&xs_ctx); - } - - /* Thawte special :-) */ - if (s->ctx->extra_certs != NULL) + X509_STORE_CTX xs_ctx; + + if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL)) + { + SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); + return(0); + } + + X509_verify_cert(&xs_ctx); + for (i=0; i < sk_X509_num(xs_ctx.chain); i++) + { + x = sk_X509_value(xs_ctx.chain, i); + + if (!dtls1_add_cert_to_buf(buf, &l, x)) + { + X509_STORE_CTX_cleanup(&xs_ctx); + return 0; + } + } + X509_STORE_CTX_cleanup(&xs_ctx); + } + /* Thawte special :-) */ for (i=0; ictx->extra_certs); i++) { x=sk_X509_value(s->ctx->extra_certs,i); - n=i2d_X509(x,NULL); - if (!BUF_MEM_grow_clean(buf,(n+l+3))) - { - SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); - return(0); - } - p=(unsigned char *)&(buf->data[l]); - l2n3(n,p); - i2d_X509(x,&p); - l+=n+3; + if (!dtls1_add_cert_to_buf(buf, &l, x)) + return 0; } l-= (3 + DTLS1_HM_HEADER_LENGTH); @@ -873,7 +891,6 @@ unsigned long dtls1_output_cert_chain(SSL *s, X509 *x) int dtls1_read_failed(SSL *s, int code) { DTLS1_STATE *state; - BIO *bio; int send_alert = 0; if ( code > 0) @@ -882,8 +899,7 @@ int dtls1_read_failed(SSL *s, int code) return 1; } - bio = SSL_get_rbio(s); - if ( ! BIO_dgram_recv_timedout(bio)) + if (!dtls1_is_timer_expired(s)) { /* not a timeout, none of our business, let higher layers handle this. in fact it's probably an error */ @@ -896,6 +912,7 @@ int dtls1_read_failed(SSL *s, int code) return code; } + dtls1_double_timeout(s); state = s->d1; state->timeout.num_alerts++; if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) @@ -960,7 +977,7 @@ dtls1_retransmit_buffered_messages(SSL *s) { frag = (hm_fragment *)item->data; if ( dtls1_retransmit_message(s, - dtls1_get_queue_priority(frag->msg_header.seq, frag->msg_header.is_ccs), + (unsigned short)dtls1_get_queue_priority(frag->msg_header.seq, frag->msg_header.is_ccs), 0, &found) <= 0 && found) { fprintf(stderr, "dtls1_retransmit_message() failed\n"); @@ -989,7 +1006,7 @@ dtls1_buffer_message(SSL *s, int is_ccs) if ( is_ccs) { OPENSSL_assert(s->d1->w_msg_hdr.msg_len + - DTLS1_CCS_HEADER_LENGTH == (unsigned int)s->init_num); + ((s->version==DTLS1_VERSION)?DTLS1_CCS_HEADER_LENGTH:3) == (unsigned int)s->init_num); } else {