X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_srvr.c;h=72fd3e40d6653abe7e9a35e73dae9930937bab58;hp=4630374a6c5ef6e90a2b2da4324104721f825ada;hb=92d81ba622396425764d676ba4fb3f0dac273f17;hpb=4082fea81c150e9f2643819148d275e500f309a3;ds=sidebyside diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 4630374a6c..72fd3e40d6 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -272,6 +272,14 @@ int ssl3_accept(SSL *s) SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR); return -1; } + + if (!ssl_security(s, SSL_SECOP_VERSION, 0, + s->version, NULL)) + { + SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_VERSION_TOO_LOW); + return -1; + } + s->type=SSL_ST_ACCEPT; if (s->init_buf == NULL) @@ -352,12 +360,11 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: - if (s->rwstate != SSL_X509_LOOKUP) - { - ret=ssl3_get_client_hello(s); - if (ret <= 0) goto end; - } + ret=ssl3_get_client_hello(s); + if (ret <= 0) goto end; #ifndef OPENSSL_NO_SRP + s->state = SSL3_ST_SR_CLNT_HELLO_D; + case SSL3_ST_SR_CLNT_HELLO_D: { int al; if ((ret = ssl_check_srp_ext_ClientHello(s,&al)) < 0) @@ -493,7 +500,7 @@ int ssl3_accept(SSL *s) /* SRP: send ServerKeyExchange */ || (alg_k & SSL_kSRP) #endif - || (alg_k & SSL_kEDH) + || (alg_k & SSL_kDHE) || (alg_k & SSL_kECDHE) || ((alg_k & SSL_kRSA) && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL @@ -950,6 +957,9 @@ int ssl3_get_client_hello(SSL *s) #endif STACK_OF(SSL_CIPHER) *ciphers=NULL; + if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet) + goto retry_cert; + /* We do this so that we will respond with our native type. * If we are TLSv1 and we get SSLv3, we will respond with TLSv1, * This down switching should be handled by a different method. @@ -1303,7 +1313,7 @@ int ssl3_get_client_hello(SSL *s) int m, comp_id = s->session->compress_meth; /* Perform sanity checks on resumed compression algorithm */ /* Can't disable compression */ - if (s->options & SSL_OP_NO_COMPRESSION) + if (!ssl_allow_compression(s)) { SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION); goto f_err; @@ -1338,7 +1348,7 @@ int ssl3_get_client_hello(SSL *s) } else if (s->hit) comp = NULL; - else if (!(s->options & SSL_OP_NO_COMPRESSION) && s->ctx->comp_methods) + else if (ssl_allow_compression(s) && s->ctx->comp_methods) { /* See if we have a match */ int m,nn,o,v,done=0; @@ -1394,12 +1404,22 @@ int ssl3_get_client_hello(SSL *s) } ciphers=NULL; /* Let cert callback update server certificates if required */ - if (s->cert->cert_cb - && s->cert->cert_cb(s, s->cert->cert_cb_arg) <= 0) + retry_cert: + if (s->cert->cert_cb) { - al=SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CERT_CB_ERROR); - goto f_err; + int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (rv == 0) + { + al=SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CERT_CB_ERROR); + goto f_err; + } + if (rv < 0) + { + s->rwstate=SSL_X509_LOOKUP; + return -1; + } + s->rwstate = SSL_NOTHING; } c=ssl3_choose_cipher(s,s->session->ciphers, SSL_get_ciphers(s)); @@ -1414,7 +1434,7 @@ int ssl3_get_client_hello(SSL *s) /* check whether we should disable session resumption */ if (s->not_resumable_session_cb != NULL) s->session->not_resumable=s->not_resumable_session_cb(s, - ((c->algorithm_mkey & (SSL_kEDH | SSL_kECDHE)) != 0)); + ((c->algorithm_mkey & (SSL_kDHE | SSL_kECDHE)) != 0)); if (s->session->not_resumable) /* do not send a session ticket */ s->tlsext_ticket_expected = 0; @@ -1493,6 +1513,7 @@ int ssl3_send_server_hello(SSL *s) unsigned char *buf; unsigned char *p,*d; int i,sl; + int al = 0; unsigned long l; if (s->state == SSL3_ST_SW_SRVR_HELLO_A) @@ -1562,8 +1583,9 @@ int ssl3_send_server_hello(SSL *s) SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT); return -1; } - if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) + if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH, &al)) == NULL) { + ssl3_send_alert(s, SSL3_AL_FATAL, al); SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR); return -1; } @@ -1663,9 +1685,20 @@ int ssl3_send_server_key_exchange(SSL *s) else #endif #ifndef OPENSSL_NO_DH - if (type & SSL_kEDH) + if (type & SSL_kDHE) { - dhp=cert->dh_tmp; + if (s->cert->dh_tmp_auto) + { + dhp = ssl_get_auto_dh(s); + if (dhp == NULL) + { + al=SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); + goto f_err; + } + } + else + dhp=cert->dh_tmp; if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL)) dhp=s->cert->dh_tmp_cb(s, SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), @@ -1676,14 +1709,22 @@ int ssl3_send_server_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY); goto f_err; } - + if (!ssl_security(s, SSL_SECOP_TMP_DH, + DH_security_bits(dhp), 0, dhp)) + { + al=SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_DH_KEY_TOO_SMALL); + goto f_err; + } if (s->s3->tmp.dh != NULL) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } - if ((dh=DHparams_dup(dhp)) == NULL) + if (s->cert->dh_tmp_auto) + dh = dhp; + else if ((dh=DHparams_dup(dhp)) == NULL) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB); goto err; @@ -1884,7 +1925,7 @@ int ssl3_send_server_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); goto f_err; } - for (i=0; r[i] != NULL && i<4; i++) + for (i=0; i < 4 && r[i] != NULL; i++) { nr[i]=BN_num_bytes(r[i]); #ifndef OPENSSL_NO_SRP @@ -1919,7 +1960,7 @@ int ssl3_send_server_key_exchange(SSL *s) } d = p = ssl_handshake_start(s); - for (i=0; r[i] != NULL && i<4; i++) + for (i=0; i < 4 && r[i] != NULL; i++) { #ifndef OPENSSL_NO_SRP if ((i == 2) && (type & SSL_kSRP)) @@ -2088,9 +2129,13 @@ int ssl3_send_certificate_request(SSL *s) if (SSL_USE_SIGALGS(s)) { const unsigned char *psigs; + unsigned char *etmp = p; nl = tls12_get_psigalgs(s, &psigs); - s2n(nl, p); - memcpy(p, psigs, nl); + /* Skip over length for now */ + p += 2; + nl = tls12_copy_sigalgs(s, p, psigs, nl); + /* Now fill in length */ + s2n(nl, etmp); p += nl; n += nl + 2; } @@ -2139,6 +2184,11 @@ int ssl3_send_certificate_request(SSL *s) #ifdef NETSCAPE_HANG_BUG if (!SSL_IS_DTLS(s)) { + if (!BUF_MEM_grow_clean(buf, s->init_num + 4)) + { + SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB); + goto err; + } p=(unsigned char *)s->init_buf->data + s->init_num; /* do the header */ *(p++)=SSL3_MT_SERVER_DONE; @@ -2346,7 +2396,7 @@ int ssl3_get_client_key_exchange(SSL *s) else #endif #ifndef OPENSSL_NO_DH - if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) + if (alg_k & (SSL_kDHE|SSL_kDHr|SSL_kDHd)) { int idx = -1; EVP_PKEY *skey = NULL; @@ -2934,6 +2984,8 @@ int ssl3_get_client_key_exchange(SSL *s) unsigned char premaster_secret[32], *start; size_t outlen=32, inlen; unsigned long alg_a; + int Ttag, Tclass; + long Tlen; /* Get our certificate private key*/ alg_a = s->s3->tmp.new_cipher->algorithm_auth; @@ -2955,26 +3007,15 @@ int ssl3_get_client_key_exchange(SSL *s) ERR_clear_error(); } /* Decrypt session key */ - if ((*p!=( V_ASN1_SEQUENCE| V_ASN1_CONSTRUCTED))) - { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED); - goto gerr; - } - if (p[1] == 0x81) - { - start = p+3; - inlen = p[2]; - } - else if (p[1] < 0x80) - { - start = p+2; - inlen = p[1]; - } - else + if (ASN1_get_object((const unsigned char **)&p, &Tlen, &Ttag, &Tclass, n) != V_ASN1_CONSTRUCTED || + Ttag != V_ASN1_SEQUENCE || + Tclass != V_ASN1_UNIVERSAL) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED); goto gerr; } + start = p; + inlen = Tlen; if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,start,inlen) <=0) { @@ -3386,6 +3427,7 @@ int ssl3_get_client_certificate(SSL *s) } else { + EVP_PKEY *pkey; i=ssl_verify_cert_chain(s,sk); if (i <= 0) { @@ -3393,6 +3435,21 @@ int ssl3_get_client_certificate(SSL *s) SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED); goto f_err; } + if (i > 1) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, i); + al = SSL_AD_HANDSHAKE_FAILURE; + goto f_err; + } + pkey = X509_get_pubkey(sk_X509_value(sk, 0)); + if (pkey == NULL) + { + al=SSL3_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, + SSL_R_UNKNOWN_CERTIFICATE_TYPE); + goto f_err; + } + EVP_PKEY_free(pkey); } if (s->session->peer != NULL) /* This should not be needed */ @@ -3449,7 +3506,11 @@ int ssl3_send_server_certificate(SSL *s) } } - ssl3_output_cert_chain(s,cpk); + if (!ssl3_output_cert_chain(s,cpk)) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR); + return(0); + } s->state=SSL3_ST_SW_CERT_B; } @@ -3691,6 +3752,7 @@ int ssl3_get_next_proto(SSL *s) int tls1_send_server_supplemental_data(SSL *s, int *skip) { + int al = 0; if (s->ctx->srv_supp_data_records_count) { unsigned char *p = NULL; @@ -3710,14 +3772,13 @@ int tls1_send_server_supplemental_data(SSL *s, int *skip) if (!record->fn1) continue; cb_retval = record->fn1(s, record->supp_data_type, - &out, &outlen, - record->arg); + &out, &outlen, &al, record->arg); if (cb_retval == -1) continue; /* skip this supp data entry */ if (cb_retval == 0) { SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB); - return 0; + goto f_err; } if (outlen == 0 || TLSEXT_MAXLEN_supplemental_data < outlen + 4 + length) { @@ -3779,6 +3840,9 @@ int tls1_send_server_supplemental_data(SSL *s, int *skip) s->init_num = 0; s->init_off = 0; return 1; +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); + return 0; } int tls1_get_client_supplemental_data(SSL *s) @@ -3789,17 +3853,17 @@ int tls1_get_client_supplemental_data(SSL *s) long n; const unsigned char *p, *d; unsigned short supp_data_entry_type = 0; - unsigned long supp_data_entry_len = 0; + unsigned short supp_data_entry_len = 0; unsigned long supp_data_len = 0; size_t i = 0; n=s->method->ssl_get_message(s, - SSL3_ST_SR_SUPPLEMENTAL_DATA_A, - SSL3_ST_SR_SUPPLEMENTAL_DATA_B, - SSL3_MT_SUPPLEMENTAL_DATA, - /* use default limit */ - TLSEXT_MAXLEN_supplemental_data, - &ok); + SSL3_ST_SR_SUPPLEMENTAL_DATA_A, + SSL3_ST_SR_SUPPLEMENTAL_DATA_B, + SSL3_MT_SUPPLEMENTAL_DATA, + /* use default limit */ + TLSEXT_MAXLEN_supplemental_data, + &ok); if (!ok) return((int)n);