X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=ssl%2Ft1_lib.c;h=cc97258ae5368780e74785454b799e3a73d2dc55;hb=808f55351aa4834a7b358c43fb6cac371e79ff7c;hp=6c2085d6aa3871076c03e979fec641d5cc3698d7;hpb=c2b78c31d631f45cd43c2d04c5ae490b8e9f21ab;p=oweals%2Fopenssl.git diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 6c2085d6aa..cc97258ae5 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -133,8 +133,9 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha int extdatalen=0; unsigned char *ret = p; - /* don't add extensions for SSLv3 */ - if (s->client_version == SSL3_VERSION) + /* don't add extensions for SSLv3 unless doing secure renegotiation */ + if (s->client_version == SSL3_VERSION + && !s->s3->send_connection_binding) return p; ret+=2; @@ -173,9 +174,10 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha ret+=size_str; } - - /* Add the renegotiation option: TODOEKR switch */ - { + + /* Add RI if renegotiating */ + if (s->new_session) + { int el; if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0)) @@ -220,7 +222,8 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } } - if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) + if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp && + s->version != DTLS1_VERSION) { int i; long extlen, idlen, itmp; @@ -280,8 +283,8 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha int extdatalen=0; unsigned char *ret = p; - /* don't add extensions for SSLv3 */ - if (s->version == SSL3_VERSION) + /* don't add extensions for SSLv3, unless doing secure renegotiation */ + if (s->version == SSL3_VERSION && !s->s3->send_connection_binding) return p; ret+=2; @@ -295,13 +298,13 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha s2n(0,ret); } - if(s->s3->send_connection_binding) + if(s->s3->send_connection_binding) { int el; if(!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) { - SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } @@ -312,7 +315,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha if(!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el)) { - SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } @@ -351,23 +354,14 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in s->servername_done = 0; s->tlsext_status_type = -1; - s->s3->send_connection_binding = 0; if (data >= (d+n-2)) - { - if (s->new_session - && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) - { - /* We should always see one extension: the renegotiate extension */ - *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ - return 0; - } - return 1; - } + goto ri_check; + n2s(data,len); if (data > (d+n-len)) - return 1; + goto ri_check; while (data <= (d+n-4)) { @@ -375,7 +369,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in n2s(data,size); if (data+size > (d+n)) - return 1; + goto ri_check; if (s->tlsext_debug_cb) s->tlsext_debug_cb(s, 0, type, data, size, @@ -438,14 +432,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in switch (servname_type) { case TLSEXT_NAMETYPE_host_name: - if (s->session->tlsext_hostname == NULL) + if (!s->hit) { - if (len > TLSEXT_MAXLEN_host_name || - ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL)) + if(s->session->tlsext_hostname) + { + *al = SSL_AD_DECODE_ERROR; + return 0; + } + if (len > TLSEXT_MAXLEN_host_name) { *al = TLS1_AD_UNRECOGNIZED_NAME; return 0; } + if ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL) + { + *al = TLS1_AD_INTERNAL_ERROR; + return 0; + } memcpy(s->session->tlsext_hostname, sdata, len); s->session->tlsext_hostname[len]='\0'; if (strlen(s->session->tlsext_hostname) != len) { @@ -458,7 +461,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in } else - s->servername_done = strlen(s->session->tlsext_hostname) == len + s->servername_done = s->session->tlsext_hostname + && strlen(s->session->tlsext_hostname) == len && strncmp(s->session->tlsext_hostname, (char *)sdata, len) == 0; break; @@ -482,8 +486,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in return 0; renegotiate_seen = 1; } - else if (type == TLSEXT_TYPE_status_request - && s->ctx->tlsext_status_cb) + else if (type == TLSEXT_TYPE_status_request && + s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb) { if (size < 5) @@ -517,6 +521,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in } n2s(data, idsize); dsize -= 2 + idsize; + size -= 2 + idsize; if (dsize < 0) { *al = SSL_AD_DECODE_ERROR; @@ -555,9 +560,14 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in } /* Read in request_extensions */ + if (size < 2) + { + *al = SSL_AD_DECODE_ERROR; + return 0; + } n2s(data,dsize); size -= 2; - if (dsize > size) + if (dsize != size) { *al = SSL_AD_DECODE_ERROR; return 0; @@ -565,6 +575,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in sdata = data; if (dsize > 0) { + if (s->tlsext_ocsp_exts) + { + sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts, + X509_EXTENSION_free); + } + s->tlsext_ocsp_exts = d2i_X509_EXTENSIONS(NULL, &sdata, dsize); @@ -587,50 +603,50 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in data+=size; } + *p = data; - if (s->new_session && !renegotiate_seen - && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) + ri_check: + + /* Need RI if renegotiating */ + + if (!renegotiate_seen && s->new_session && + !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) { - *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ + *al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, + SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); return 0; } - *p = data; return 1; } int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al) { + unsigned short length; unsigned short type; unsigned short size; - unsigned short len; unsigned char *data = *p; int tlsext_servername = 0; int renegotiate_seen = 0; if (data >= (d+n-2)) + goto ri_check; + + n2s(data,length); + if (data+length != d+n) { - /* Because the client does not see any renegotiation during an - attack, we must enforce this on all server hellos, even the - first */ - if (!(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) - { - /* We should always see one extension: the renegotiate extension */ - *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ - return 0; - } - return 1; + *al = SSL_AD_DECODE_ERROR; + return 0; } - n2s(data,len); - while(data <= (d+n-4)) { n2s(data,type); n2s(data,size); if (data+size > (d+n)) - return 1; + goto ri_check; if (s->tlsext_debug_cb) s->tlsext_debug_cb(s, 1, type, data, size, @@ -655,7 +671,8 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in } s->tlsext_ticket_expected = 1; } - else if (type == TLSEXT_TYPE_status_request) + else if (type == TLSEXT_TYPE_status_request && + s->version != DTLS1_VERSION) { /* MUST be empty and only sent if we've requested * a status request message. @@ -683,13 +700,6 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in return 0; } - if (!renegotiate_seen - && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) - { - *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ - return 0; - } - if (!s->hit && tlsext_servername == 1) { if (s->tlsext_hostname) @@ -712,6 +722,26 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in } *p = data; + + ri_check: + + /* Determine if we need to see RI. Strictly speaking if we want to + * avoid an attack we should *always* see RI even on initial server + * hello because the client doesn't see any renegotiation during an + * attack. However this would mean we could not connect to any server + * which doesn't support RI so for the immediate future tolerate RI + * absence on initial connect only. + */ + if (!renegotiate_seen + && !(s->options & SSL_OP_LEGACY_SERVER_CONNECT) + && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) + { + *al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT, + SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + return 0; + } + return 1; }