X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_srvr.c;h=ab2478d01cbeda974c7360e4f07e5e4a58f0f818;hp=154b6ada3473e4861ddb700d069bd71bef4a3888;hb=48948d53b6f61aa14bc5eab33f67f124c43175ff;hpb=d02f751ce1d13183a0c0e5528ec89f76587ed989 diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 154b6ada34..ab2478d01c 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -55,28 +55,85 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ #define REUSE_CIPHER_BUG +#define NETSCAPE_HANG_BUG + #include #include #include #include -#include -#include #include #include +#include #include "ssl_locl.h" +#include "kssl_lcl.h" +#include static SSL_METHOD *ssl3_get_server_method(int ver); static int ssl3_get_client_hello(SSL *s); +static int ssl3_check_client_hello(SSL *s); static int ssl3_send_server_hello(SSL *s); static int ssl3_send_server_key_exchange(SSL *s); static int ssl3_send_certificate_request(SSL *s); static int ssl3_send_server_done(SSL *s); -static int ssl3_get_cert_verify(SSL *s); static int ssl3_get_client_key_exchange(SSL *s); static int ssl3_get_client_certificate(SSL *s); +static int ssl3_get_cert_verify(SSL *s); static int ssl3_send_hello_request(SSL *s); static SSL_METHOD *ssl3_get_server_method(int ver) @@ -110,10 +167,10 @@ int ssl3_accept(SSL *s) void (*cb)()=NULL; long num1; int ret= -1; - CERT *ct; int new_state,state,skip=0; + int got_new_session=0; - RAND_seed(&Time,sizeof(Time)); + RAND_add(&Time,sizeof(Time),0); ERR_clear_error(); clear_sys_error(); @@ -126,17 +183,11 @@ int ssl3_accept(SSL *s) if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->in_handshake++; -#ifdef undef - /* FIX THIS EAY EAY EAY */ - /* we don't actually need a cert, we just need a cert or a DH_tmp */ - if (((s->session == NULL) || (s->session->cert == NULL)) && - (s->cert == NULL)) + if (s->cert == NULL) { SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_NO_CERTIFICATE_SET); - ret= -1; - goto end; + return(-1); } -#endif for (;;) { @@ -157,8 +208,10 @@ int ssl3_accept(SSL *s) if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); if ((s->version>>8) != 3) - abort(); - /* s->version=SSL3_VERSION; */ + { + SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR); + return -1; + } s->type=SSL_ST_ACCEPT; if (s->init_buf == NULL) @@ -182,21 +235,23 @@ int ssl3_accept(SSL *s) goto end; } - /* Ok, we now need to push on a buffering BIO so that - * the output is sent in a way that TCP likes :-) - */ - if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } - s->init_num=0; if (s->state != SSL_ST_RENEGOTIATE) { - s->state=SSL3_ST_SR_CLNT_HELLO_A; + /* Ok, we now need to push on a buffering BIO so that + * the output is sent in a way that TCP likes :-) + */ + if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } + ssl3_init_finished_mac(s); + s->state=SSL3_ST_SR_CLNT_HELLO_A; s->ctx->stats.sess_accept++; } else { + /* s->state == SSL_ST_RENEGOTIATE, + * we will just send a HelloRequest */ s->ctx->stats.sess_accept_renegotiate++; s->state=SSL3_ST_SW_HELLO_REQ_A; } @@ -217,9 +272,7 @@ int ssl3_accept(SSL *s) case SSL3_ST_SW_HELLO_REQ_C: s->state=SSL_ST_OK; - ret=1; - goto end; - /* break; */ + break; case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: @@ -228,6 +281,7 @@ int ssl3_accept(SSL *s) s->shutdown=0; ret=ssl3_get_client_hello(s); if (ret <= 0) goto end; + got_new_session=1; s->state=SSL3_ST_SW_SRVR_HELLO_A; s->init_num=0; break; @@ -261,24 +315,18 @@ int ssl3_accept(SSL *s) case SSL3_ST_SW_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: l=s->s3->tmp.new_cipher->algorithms; - if (s->session->cert == NULL) - { - if (s->cert != NULL) - { - CRYPTO_add(&s->cert->references,1,CRYPTO_LOCK_SSL_CERT); - s->session->cert=s->cert; - } - else - { - CRYPTO_add(&s->ctx->default_cert->references,1,CRYPTO_LOCK_SSL_CERT); - s->session->cert=s->ctx->default_cert; - } - } - ct=s->session->cert; /* clear this, it may get reset by * send_server_key_exchange */ - if (s->options & SSL_OP_EPHEMERAL_RSA) + if ((s->options & SSL_OP_EPHEMERAL_RSA) +#ifndef OPENSSL_NO_KRB5 + && !(l & SSL_KRB5) +#endif /* OPENSSL_NO_KRB5 */ + ) + /* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key + * even when forbidden by protocol specs + * (handshake may fail as clients are not required to + * be able to handle this) */ s->s3->tmp.use_rsa_tmp=1; else s->s3->tmp.use_rsa_tmp=0; @@ -288,9 +336,9 @@ int ssl3_accept(SSL *s) if (s->s3->tmp.use_rsa_tmp || (l & (SSL_DH|SSL_kFZA)) || ((l & SSL_kRSA) - && (ct->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL - || (SSL_IS_EXPORT(l) - && EVP_PKEY_size(ct->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_EXPORT_PKEYLENGTH(l) + && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL + || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) + && EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher) ) ) ) @@ -308,9 +356,21 @@ int ssl3_accept(SSL *s) case SSL3_ST_SW_CERT_REQ_A: case SSL3_ST_SW_CERT_REQ_B: - if (!(s->verify_mode & SSL_VERIFY_PEER) || + if (/* don't request cert unless asked for it: */ + !(s->verify_mode & SSL_VERIFY_PEER) || + /* if SSL_VERIFY_CLIENT_ONCE is set, + * don't request cert during re-negotiation: */ ((s->session->peer != NULL) && - (s->verify_mode & SSL_VERIFY_CLIENT_ONCE))) + (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || + /* never request cert in anonymous ciphersuites + * (see section "Certificate request" in SSL 3 drafts + * and in RFC 2246): */ + ((s->s3->tmp.new_cipher->algorithms & SSL_aNULL) && + /* ... except when the application insists on verification + * (against the specs, but s3_clnt.c accepts this for SSL 3) */ + !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || + /* never request cert in Kerberos ciphersuites */ + (s->s3->tmp.new_cipher->algorithms & SSL_aKRB5)) { /* no cert request */ skip=1; @@ -322,7 +382,12 @@ int ssl3_accept(SSL *s) s->s3->tmp.cert_request=1; ret=ssl3_send_certificate_request(s); if (ret <= 0) goto end; +#ifndef NETSCAPE_HANG_BUG s->state=SSL3_ST_SW_SRVR_DONE_A; +#else + s->state=SSL3_ST_SW_FLUSH; + s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; +#endif s->init_num=0; } break; @@ -352,12 +417,20 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: - /* could be sent for a DH cert, even if we - * have not asked for it :-) */ - ret=ssl3_get_client_certificate(s); - if (ret <= 0) goto end; - s->init_num=0; - s->state=SSL3_ST_SR_KEY_EXCH_A; + /* Check for second client hello (MS SGC) */ + ret = ssl3_check_client_hello(s); + if (ret <= 0) + goto end; + if (ret == 2) + s->state = SSL3_ST_SR_CLNT_HELLO_C; + else { + /* could be sent for a DH cert, even if we + * have not asked for it :-) */ + ret=ssl3_get_client_certificate(s); + if (ret <= 0) goto end; + s->init_num=0; + s->state=SSL3_ST_SR_KEY_EXCH_A; + } break; case SSL3_ST_SR_KEY_EXCH_A: @@ -371,10 +444,10 @@ int ssl3_accept(SSL *s) * a client cert, it can be verified */ s->method->ssl3_enc->cert_verify_mac(s, &(s->s3->finish_dgst1), - &(s->s3->tmp.finish_md[0])); + &(s->s3->tmp.cert_verify_md[0])); s->method->ssl3_enc->cert_verify_mac(s, &(s->s3->finish_dgst2), - &(s->s3->tmp.finish_md[MD5_DIGEST_LENGTH])); + &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH])); break; @@ -428,8 +501,8 @@ int ssl3_accept(SSL *s) case SSL3_ST_SW_FINISHED_B: ret=ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B, - s->method->ssl3_enc->server_finished, - s->method->ssl3_enc->server_finished_len); + s->method->ssl3_enc->server_finished_label, + s->method->ssl3_enc->server_finished_label_len); if (ret <= 0) goto end; s->state=SSL3_ST_SW_FLUSH; if (s->hit) @@ -449,18 +522,25 @@ int ssl3_accept(SSL *s) /* remove buffering on output */ ssl_free_wbio_buffer(s); - s->new_session=0; s->init_num=0; - ssl_update_cache(s,SSL_SESS_CACHE_SERVER); - - s->ctx->stats.sess_accept_good++; - /* s->server=1; */ - s->handshake_func=ssl3_accept; - ret=1; - - if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); - + if (got_new_session) /* skipped if we just sent a HelloRequest */ + { + /* actually not necessarily a 'new' session unless + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ + + s->new_session=0; + + ssl_update_cache(s,SSL_SESS_CACHE_SERVER); + + s->ctx->stats.sess_accept_good++; + /* s->server=1; */ + s->handshake_func=ssl3_accept; + + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); + } + + ret = 1; goto end; /* break; */ @@ -506,7 +586,7 @@ static int ssl3_send_hello_request(SSL *s) if (s->state == SSL3_ST_SW_HELLO_REQ_A) { p=(unsigned char *)s->init_buf->data; - *(p++)=SSL3_MT_CLIENT_REQUEST; + *(p++)=SSL3_MT_HELLO_REQUEST; *(p++)=0; *(p++)=0; *(p++)=0; @@ -521,6 +601,39 @@ static int ssl3_send_hello_request(SSL *s) return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } +static int ssl3_check_client_hello(SSL *s) + { + int ok; + long n; + + /* this function is called when we really expect a Certificate message, + * so permit appropriate message length */ + n=ssl3_get_message(s, + SSL3_ST_SR_CERT_A, + SSL3_ST_SR_CERT_B, + -1, + s->max_cert_list, + &ok); + if (!ok) return((int)n); + s->s3->tmp.reuse_message = 1; + if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO) + { + /* Throw away what we have done so far in the current handshake, + * which will now be aborted. (A full SSL_clear would be too much.) + * I hope that tmp.dh is the only thing that may need to be cleared + * when a handshake is not completed ... */ +#ifndef OPENSSL_NO_DH + if (s->s3->tmp.dh != NULL) + { + DH_free(s->s3->tmp.dh); + s->s3->tmp.dh = NULL; + } +#endif + return 2; + } + return 1; +} + static int ssl3_get_client_hello(SSL *s) { int i,j,ok,al,ret= -1; @@ -550,12 +663,11 @@ static int ssl3_get_client_hello(SSL *s) &ok); if (!ok) return((int)n); - d=p=(unsigned char *)s->init_buf->data; + d=p=(unsigned char *)s->init_msg; - /* The version number has already been checked in ssl3_get_message. - * I a native TLSv1/SSLv3 method, the match must be correct except - * perhaps for the first message */ -/* s->client_version=(((int)p[0])<<8)|(int)p[1]; */ + /* use version from inside client hello, not from record header + * (may differ: see RFC 2246, Appendix E, second paragraph) */ + s->client_version=(((int)p[0])<<8)|(int)p[1]; p+=2; /* load the client random */ @@ -566,7 +678,15 @@ static int ssl3_get_client_hello(SSL *s) j= *(p++); s->hit=0; - if (j == 0) + /* Versions before 0.9.7 always allow session reuse during renegotiation + * (i.e. when s->new_session is true), option + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is new with 0.9.7. + * Maybe this optional behaviour should always have been the default, + * but we cannot safely change the default behaviour (or new applications + * might be written that become totally unsecure when compiled with + * an earlier library version) + */ + if (j == 0 || (s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) { if (!ssl_get_new_session(s,1)) goto err; @@ -578,7 +698,9 @@ static int ssl3_get_client_hello(SSL *s) { /* previous session */ s->hit=1; } - else + else if (i == -1) + goto err; + else /* i == 0 */ { if (!ssl_get_new_session(s,1)) goto err; @@ -708,7 +830,7 @@ static int ssl3_get_client_hello(SSL *s) } } - /* Given s->session->ciphers and ssl_get_ciphers_by_id(s), we must + /* Given s->session->ciphers and SSL_get_ciphers, we must * pick a cipher */ if (!s->hit) @@ -725,7 +847,7 @@ static int ssl3_get_client_hello(SSL *s) } ciphers=NULL; c=ssl3_choose_cipher(s,s->session->ciphers, - ssl_get_ciphers_by_id(s)); + SSL_get_ciphers(s)); if (c == NULL) { @@ -773,7 +895,7 @@ static int ssl3_get_client_hello(SSL *s) * compression - basically ignored right now * ssl version is set - sslv3 * s->session - The ssl session has been setup. - * s->hit - sesson reuse flag + * s->hit - session reuse flag * s->tmp.new_cipher - the new cipher to use. */ @@ -801,7 +923,7 @@ static int ssl3_send_server_hello(SSL *s) p=s->s3->server_random; Time=time(NULL); /* Time */ l2n(Time,p); - RAND_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time)); + RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time)); /* Do the message type and length last */ d=p= &(buf[4]); @@ -880,14 +1002,15 @@ static int ssl3_send_server_done(SSL *s) static int ssl3_send_server_key_exchange(SSL *s) { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA unsigned char *q; int j,num; RSA *rsa; unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; + unsigned int u; #endif -#ifndef NO_DH - DH *dh,*dhp; +#ifndef OPENSSL_NO_DH + DH *dh=NULL,*dhp; #endif EVP_PKEY *pkey; unsigned char *p,*d; @@ -900,25 +1023,32 @@ static int ssl3_send_server_key_exchange(SSL *s) BUF_MEM *buf; EVP_MD_CTX md_ctx; + EVP_MD_CTX_init(&md_ctx); if (s->state == SSL3_ST_SW_KEY_EXCH_A) { type=s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK; - cert=s->session->cert; + cert=s->cert; buf=s->init_buf; r[0]=r[1]=r[2]=r[3]=NULL; n=0; -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (type & SSL_kRSA) { rsa=cert->rsa_tmp; - if ((rsa == NULL) && (s->ctx->default_cert->rsa_tmp_cb != NULL)) + if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL)) { - rsa=s->ctx->default_cert->rsa_tmp_cb(s, + rsa=s->cert->rsa_tmp_cb(s, SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); - CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA); + if(rsa == NULL) + { + al=SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY); + goto f_err; + } + RSA_up_ref(rsa); cert->rsa_tmp=rsa; } if (rsa == NULL) @@ -933,13 +1063,13 @@ static int ssl3_send_server_key_exchange(SSL *s) } else #endif -#ifndef NO_DH +#ifndef OPENSSL_NO_DH if (type & SSL_kEDH) { dhp=cert->dh_tmp; - if ((dhp == NULL) && (cert->dh_tmp_cb != NULL)) - dhp=cert->dh_tmp_cb(s, - !SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), + 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), SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); if (dhp == NULL) { @@ -947,6 +1077,14 @@ static 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 (s->s3->tmp.dh != NULL) + { + DH_free(dh); + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto err; + } + if ((dh=DHparams_dup(dhp)) == NULL) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB); @@ -1029,7 +1167,7 @@ static int ssl3_send_server_key_exchange(SSL *s) { /* n is the length of the params, they start at &(d[4]) * and p points to the space at the end. */ -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) { q=md_buf; @@ -1046,19 +1184,18 @@ static int ssl3_send_server_key_exchange(SSL *s) q+=i; j+=i; } - i=RSA_private_encrypt(j,md_buf,&(p[2]), - pkey->pkey.rsa,RSA_PKCS1_PADDING); - if (i <= 0) + if (RSA_sign(NID_md5_sha1, md_buf, j, + &(p[2]), &u, pkey->pkey.rsa) <= 0) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA); goto err; } - s2n(i,p); - n+=i+2; + s2n(u,p); + n+=u+2; } else #endif -#if !defined(NO_DSA) +#if !defined(OPENSSL_NO_DSA) if (pkey->type == EVP_PKEY_DSA) { /* lets do DSS */ @@ -1094,11 +1231,13 @@ static int ssl3_send_server_key_exchange(SSL *s) s->init_off=0; } - /* SSL3_ST_SW_KEY_EXCH_B */ + s->state = SSL3_ST_SW_KEY_EXCH_B; + EVP_MD_CTX_cleanup(&md_ctx); return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); err: + EVP_MD_CTX_cleanup(&md_ctx); return(-1); } @@ -1171,6 +1310,17 @@ static int ssl3_send_certificate_request(SSL *s) s->init_num=n+4; s->init_off=0; +#ifdef NETSCAPE_HANG_BUG + p=(unsigned char *)s->init_buf->data + s->init_num; + + /* do the header */ + *(p++)=SSL3_MT_SERVER_DONE; + *(p++)=0; + *(p++)=0; + *(p++)=0; + s->init_num += 4; +#endif + } /* SSL3_ST_SW_CERT_REQ_B */ @@ -1185,39 +1335,38 @@ static int ssl3_get_client_key_exchange(SSL *s) long n; unsigned long l; unsigned char *p; -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA RSA *rsa=NULL; EVP_PKEY *pkey=NULL; #endif -#ifndef NO_DH +#ifndef OPENSSL_NO_DH BIGNUM *pub=NULL; DH *dh_srvr; #endif +#ifndef OPENSSL_NO_KRB5 + KSSL_ERR kssl_err; +#endif /* OPENSSL_NO_KRB5 */ n=ssl3_get_message(s, SSL3_ST_SR_KEY_EXCH_A, SSL3_ST_SR_KEY_EXCH_B, SSL3_MT_CLIENT_KEY_EXCHANGE, - 400, /* ???? */ + 2048, /* ??? */ &ok); if (!ok) return((int)n); - p=(unsigned char *)s->init_buf->data; + p=(unsigned char *)s->init_msg; l=s->s3->tmp.new_cipher->algorithms; -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (l & SSL_kRSA) { /* FIX THIS UP EAY EAY EAY EAY */ if (s->s3->tmp.use_rsa_tmp) { - if ((s->session->cert != NULL) && - (s->session->cert->rsa_tmp != NULL)) - rsa=s->session->cert->rsa_tmp; - else if ((s->ctx->default_cert != NULL) && - (s->ctx->default_cert->rsa_tmp != NULL)) - rsa=s->ctx->default_cert->rsa_tmp; + if ((s->cert != NULL) && (s->cert->rsa_tmp != NULL)) + rsa=s->cert->rsa_tmp; /* Don't do a callback because rsa_tmp should * be sent already */ if (rsa == NULL) @@ -1262,46 +1411,53 @@ static int ssl3_get_client_key_exchange(SSL *s) i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING); -#if 1 - /* If a bad decrypt, use a random master key */ - if ((i != SSL_MAX_MASTER_KEY_LENGTH) || - ((p[0] != (s->client_version>>8)) || - (p[1] != (s->client_version & 0xff)))) - { - int bad=1; - - if ((i == SSL_MAX_MASTER_KEY_LENGTH) && - (p[0] == (s->version>>8)) && - (p[1] == 0)) - { - if (s->options & SSL_OP_TLS_ROLLBACK_BUG) - bad=0; - } - if (bad) - { - p[0]=(s->version>>8); - p[1]=(s->version & 0xff); - RAND_bytes(&(p[2]),SSL_MAX_MASTER_KEY_LENGTH-2); - i=SSL_MAX_MASTER_KEY_LENGTH; - } - /* else, an SSLeay bug, ssl only server, tls client */ - } -#else + al = -1; + if (i != SSL_MAX_MASTER_KEY_LENGTH) { al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); - goto f_err; } - if ((p[0] != (s->version>>8)) || (p[1] != (s->version & 0xff))) + if ((al == -1) && !((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff)))) { - al=SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); - goto f_err; + /* The premaster secret must contain the same version number as the + * ClientHello to detect version rollback attacks (strangely, the + * protocol does not offer such protection for DH ciphersuites). + * However, buggy clients exist that send the negotiated protocol + * version instead if the server does not support the requested + * protocol version. + * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */ + if (!((s->options & SSL_OP_TLS_ROLLBACK_BUG) && + (p[0] == (s->version>>8)) && (p[1] == (s->version & 0xff)))) + { + al=SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); + goto f_err; + } } -#endif + if (al != -1) + { +#if 0 + goto f_err; +#else + /* Some decryption failure -- use random value instead as countermeasure + * against Bleichenbacher's attack on PKCS #1 v1.5 RSA padding + * (see RFC 2246, section 7.4.7.1). + * But note that due to length and protocol version checking, the + * attack is impractical anyway (see section 5 in D. Bleichenbacher: + * "Chosen Ciphertext Attacks Against Protocols Based on the RSA + * Encryption Standard PKCS #1", CRYPTO '98, LNCS 1462, pp. 1-12). + */ + ERR_clear_error(); + i = SSL_MAX_MASTER_KEY_LENGTH; + p[0] = s->client_version >> 8; + p[1] = s->client_version & 0xff; + RAND_pseudo_bytes(p+2, i-2); /* should be RAND_bytes, but we cannot work around a failure */ +#endif + } + s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, @@ -1310,7 +1466,7 @@ static int ssl3_get_client_key_exchange(SSL *s) } else #endif -#ifndef NO_DH +#ifndef OPENSSL_NO_DH if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) { n2s(p,i); @@ -1369,19 +1525,167 @@ static int ssl3_get_client_key_exchange(SSL *s) s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, s->session->master_key,p,i); + memset(p,0,i); } else #endif +#ifndef OPENSSL_NO_KRB5 + if (l & SSL_kKRB5) + { + krb5_error_code krb5rc; + krb5_data enc_ticket; + krb5_data authenticator; + krb5_data enc_pms; + KSSL_CTX *kssl_ctx = s->kssl_ctx; + EVP_CIPHER_CTX ciph_ctx; + EVP_CIPHER *enc = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH + + EVP_MAX_IV_LENGTH + 1]; + int padl, outl = sizeof(pms); + krb5_timestamp authtime = 0; + krb5_ticket_times ttimes; + + if (!kssl_ctx) kssl_ctx = kssl_ctx_new(); + + n2s(p,i); + enc_ticket.length = i; + enc_ticket.data = p; + p+=enc_ticket.length; + + n2s(p,i); + authenticator.length = i; + authenticator.data = p; + p+=authenticator.length; + + n2s(p,i); + enc_pms.length = i; + enc_pms.data = p; + p+=enc_pms.length; + + if ((unsigned long)n != enc_ticket.length + authenticator.length + + enc_pms.length + 6) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + + if ((krb5rc = kssl_sget_tkt(kssl_ctx, &enc_ticket, &ttimes, + &kssl_err)) != 0) + { +#ifdef KSSL_DEBUG + printf("kssl_sget_tkt rtn %d [%d]\n", + krb5rc, kssl_err.reason); + if (kssl_err.text) + printf("kssl_err text= %s\n", kssl_err.text); +#endif /* KSSL_DEBUG */ + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + kssl_err.reason); + goto err; + } + + /* Note: no authenticator is not considered an error, + ** but will return authtime == 0. + */ + if ((krb5rc = kssl_check_authent(kssl_ctx, &authenticator, + &authtime, &kssl_err)) != 0) + { +#ifdef KSSL_DEBUG + printf("kssl_check_authent rtn %d [%d]\n", + krb5rc, kssl_err.reason); + if (kssl_err.text) + printf("kssl_err text= %s\n", kssl_err.text); +#endif /* KSSL_DEBUG */ + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + kssl_err.reason); + goto err; + } + + if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, krb5rc); + goto err; + } + +#ifdef KSSL_DEBUG + kssl_ctx_show(kssl_ctx); +#endif /* KSSL_DEBUG */ + + enc = kssl_map_enc(kssl_ctx->enctype); + if (enc == NULL) + goto err; + + memset(iv, 0, EVP_MAX_IV_LENGTH); /* per RFC 1510 */ + + if (!EVP_DecryptInit(&ciph_ctx,enc,kssl_ctx->key,iv)) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DECRYPTION_FAILED); + goto err; + } + if (!EVP_DecryptUpdate(&ciph_ctx, pms,&outl, + enc_pms.data, enc_pms.length)) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DECRYPTION_FAILED); + goto err; + } + if (outl > SSL_MAX_MASTER_KEY_LENGTH) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + if (!EVP_DecryptFinal(&ciph_ctx,&(pms[outl]),&padl)) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DECRYPTION_FAILED); + goto err; + } + outl += padl; + if (outl > SSL_MAX_MASTER_KEY_LENGTH) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + EVP_CIPHER_CTX_cleanup(&ciph_ctx); + + s->session->master_key_length= + s->method->ssl3_enc->generate_master_secret(s, + s->session->master_key, pms, outl); + + if (kssl_ctx->client_princ) + { + int len = strlen(kssl_ctx->client_princ); + if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH ) + { + s->session->krb5_client_princ_len = len; + memcpy(s->session->krb5_client_princ,kssl_ctx->client_princ,len); + } + } + + + /* Was doing kssl_ctx_free() here, + ** but it caused problems for apache. + ** kssl_ctx = kssl_ctx_free(kssl_ctx); + ** if (s->kssl_ctx) s->kssl_ctx = NULL; + */ + } + else +#endif /* OPENSSL_NO_KRB5 */ { al=SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNKNOWN_CIPHER_TYPE); + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_UNKNOWN_CIPHER_TYPE); goto f_err; } return(1); f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); -#if !defined(NO_DH) || !defined(NO_RSA) +#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) err: #endif return(-1); @@ -1452,7 +1756,7 @@ static int ssl3_get_cert_verify(SSL *s) } /* we now have a signature that we need to verify */ - p=(unsigned char *)s->init_buf->data; + p=(unsigned char *)s->init_msg; n2s(p,i); n-=2; if (i > n) @@ -1470,19 +1774,19 @@ static int ssl3_get_cert_verify(SSL *s) goto f_err; } -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) { - i=RSA_public_decrypt(i,p,p,pkey->pkey.rsa,RSA_PKCS1_PADDING); + i=RSA_verify(NID_md5_sha1, s->s3->tmp.cert_verify_md, + MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, p, i, + pkey->pkey.rsa); if (i < 0) { al=SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_DECRYPT); goto f_err; } - if ((i != (MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH)) || - memcmp(&(s->s3->tmp.finish_md[0]),p, - MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH)) + if (i == 0) { al=SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_SIGNATURE); @@ -1491,11 +1795,11 @@ static int ssl3_get_cert_verify(SSL *s) } else #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) { j=DSA_verify(pkey->save_type, - &(s->s3->tmp.finish_md[MD5_DIGEST_LENGTH]), + &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]), SHA_DIGEST_LENGTH,p,i,pkey->pkey.dsa); if (j <= 0) { @@ -1508,7 +1812,7 @@ static int ssl3_get_cert_verify(SSL *s) else #endif { - SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR); al=SSL_AD_UNSUPPORTED_CERTIFICATE; goto f_err; } @@ -1537,11 +1841,7 @@ static int ssl3_get_client_certificate(SSL *s) SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B, -1, -#if defined(MSDOS) && !defined(WIN32) - 1024*30, /* 30k max cert list :-) */ -#else - 1024*100, /* 100k max cert list :-) */ -#endif + s->max_cert_list, &ok); if (!ok) return((int)n); @@ -1555,7 +1855,7 @@ static int ssl3_get_client_certificate(SSL *s) al=SSL_AD_HANDSHAKE_FAILURE; goto f_err; } - /* If tls asked for a client cert we must return a 0 list */ + /* If tls asked for a client cert, the client must return a 0 list */ if ((s->version > SSL3_VERSION) && s->s3->tmp.cert_request) { SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST); @@ -1572,7 +1872,7 @@ static int ssl3_get_client_certificate(SSL *s) SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE); goto f_err; } - d=p=(unsigned char *)s->init_buf->data; + d=p=(unsigned char *)s->init_msg; if ((sk=sk_X509_new_null()) == NULL) { @@ -1648,11 +1948,28 @@ static int ssl3_get_client_certificate(SSL *s) } } - /* This should not be needed */ - if (s->session->peer != NULL) + if (s->session->peer != NULL) /* This should not be needed */ X509_free(s->session->peer); s->session->peer=sk_X509_shift(sk); - s->session->cert->cert_chain=sk; + s->session->verify_result = s->verify_result; + + /* With the current implementation, sess_cert will always be NULL + * when we arrive here. */ + if (s->session->sess_cert == NULL) + { + s->session->sess_cert = ssl_sess_cert_new(); + if (s->session->sess_cert == NULL) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE); + goto err; + } + } + if (s->session->sess_cert->cert_chain != NULL) + sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free); + s->session->sess_cert->cert_chain=sk; + /* Inconsistency alert: cert_chain does *not* include the + * peer's own certificate, while we do include it in s3_clnt.c */ + sk=NULL; ret=1; @@ -1675,9 +1992,13 @@ int ssl3_send_server_certificate(SSL *s) if (s->state == SSL3_ST_SW_CERT_A) { x=ssl_get_server_send_cert(s); - if (x == NULL) + if (x == NULL && + /* VRS: allow null cert if auth == KRB5 */ + (s->s3->tmp.new_cipher->algorithms + & (SSL_MKEY_MASK|SSL_AUTH_MASK)) + != (SSL_aKRB5|SSL_kKRB5)) { - SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR); return(0); }