X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=ssl%2Fs3_srvr.c;h=0a46e4ab74e4316e7afa6f513ae7f88220d63211;hb=d88a26c4892152c326d8b4ca80a0cc59fe8c8d51;hp=c18b9c9131d502c2a3b59910a81c47666c77038c;hpb=de469ef21e4117908cc770f9ca25a26a01f9be38;p=oweals%2Fopenssl.git diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index c18b9c9131..0a46e4ab74 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -70,6 +70,10 @@ #include #include "ssl_locl.h" +#ifndef OPENSSL_NO_KRB5 +#include "kssl.h" +#endif /* OPENSSL_NO_KRB5 */ + 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); @@ -77,9 +81,9 @@ 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) @@ -144,7 +148,6 @@ int ssl3_accept(SSL *s) s->new_session=1; /* s->state=SSL_ST_ACCEPT; */ - case SSL3_ST_SR_MS_SGC: case SSL_ST_BEFORE: case SSL_ST_ACCEPT: case SSL_ST_BEFORE|SSL_ST_ACCEPT: @@ -154,8 +157,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, SSL_R_INTERNAL_ERROR); + return -1; + } s->type=SSL_ST_ACCEPT; if (s->init_buf == NULL) @@ -188,7 +193,7 @@ int ssl3_accept(SSL *s) if (s->state != SSL_ST_RENEGOTIATE) { - if(s->state != SSL3_ST_SR_MS_SGC) ssl3_init_finished_mac(s); + ssl3_init_finished_mac(s); s->state=SSL3_ST_SR_CLNT_HELLO_A; s->ctx->stats.sess_accept++; } @@ -261,7 +266,11 @@ int ssl3_accept(SSL *s) /* 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 */ + ) s->s3->tmp.use_rsa_tmp=1; else s->s3->tmp.use_rsa_tmp=0; @@ -350,10 +359,12 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: - /* Check for second client hello if MS SGC */ + /* 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_MS_SGC; + 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 :-) */ @@ -538,7 +549,21 @@ static int ssl3_check_client_hello(SSL *s) &ok); if (!ok) return((int)n); s->s3->tmp.reuse_message = 1; - if(s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO) return 2; + 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; } @@ -730,7 +755,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) @@ -747,7 +772,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) { @@ -902,14 +927,14 @@ 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 +#ifndef OPENSSL_NO_DH DH *dh=NULL,*dhp; #endif EVP_PKEY *pkey; @@ -932,7 +957,7 @@ static int ssl3_send_server_key_exchange(SSL *s) 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; @@ -941,6 +966,12 @@ static int ssl3_send_server_key_exchange(SSL *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)); + 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; + } CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA); cert->rsa_tmp=rsa; } @@ -956,13 +987,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) && (s->cert->dh_tmp_cb != NULL)) dhp=s->cert->dh_tmp_cb(s, - !SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), + SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); if (dhp == NULL) { @@ -1060,7 +1091,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; @@ -1088,7 +1119,7 @@ static int ssl3_send_server_key_exchange(SSL *s) } else #endif -#if !defined(NO_DSA) +#if !defined(OPENSSL_NO_DSA) if (pkey->type == EVP_PKEY_DSA) { /* lets do DSS */ @@ -1226,20 +1257,23 @@ 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); @@ -1247,7 +1281,7 @@ static int ssl3_get_client_key_exchange(SSL *s) 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 */ @@ -1299,31 +1333,6 @@ static int ssl3_get_client_key_exchange(SSL *s) i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING); -#if 0 - /* 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_pseudo_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 if (i != SSL_MAX_MASTER_KEY_LENGTH) { al=SSL_AD_DECODE_ERROR; @@ -1331,13 +1340,23 @@ static int ssl3_get_client_key_exchange(SSL *s) goto f_err; } - if ((p[0] != (s->client_version>>8)) || (p[1] != (s->client_version & 0xff))) + if (!((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 s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, @@ -1347,7 +1366,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); @@ -1406,9 +1425,57 @@ 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; + KSSL_CTX *kssl_ctx = s->kssl_ctx; + + if (!kssl_ctx) kssl_ctx = kssl_ctx_new(); + if ((krb5rc = kssl_sget_tkt(kssl_ctx, + s->init_buf->data, s->init_buf->length, + &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; + } + +#ifdef KSSL_DEBUG + kssl_ctx_show(kssl_ctx); +#endif /* KSSL_DEBUG */ + + /* 19991013 VRS - 3DES is kind of bogus here, + ** at least until Kerberos supports 3DES. The only + ** real secret is the 8-byte Kerberos session key; + ** the other key material (client_random, server_random) + ** could be sniffed. Nonces may help against replays though. + ** + ** Alternate code for Kerberos Purists: + ** + ** memcpy(s->session->master_key, kssl_ctx->key, kssl_ctx->length); + ** s->session->master_key_length = kssl_ctx->length; + */ + s->session->master_key_length= + s->method->ssl3_enc->generate_master_secret(s, + s->session->master_key, kssl_ctx->key, kssl_ctx->length); + /* 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); @@ -1418,7 +1485,7 @@ static int ssl3_get_client_key_exchange(SSL *s) 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); @@ -1507,7 +1574,7 @@ 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_verify(NID_md5_sha1, s->s3->tmp.cert_verify_md, @@ -1528,7 +1595,7 @@ 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, @@ -1574,7 +1641,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) +#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32) 1024*30, /* 30k max cert list :-) */ #else 1024*100, /* 100k max cert list :-) */ @@ -1704,6 +1771,8 @@ static int ssl3_get_client_certificate(SSL *s) 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; @@ -1727,7 +1796,11 @@ 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); return(0);