X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_srvr.c;h=e2526cc5c4f2192e77b29684c44d78486dfdeb99;hp=233de6ca906af7f12cd2defe8598415589252c66;hb=3d14b9d04a73c3563efba12f16fd179b7aed4fbf;hpb=06ab81f9f7b055a4456798cb9ef3266160438a08 diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 233de6ca90..e2526cc5c4 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -59,24 +59,18 @@ #define REUSE_CIPHER_BUG #include -#include "buffer.h" -#include "rand.h" -#include "objects.h" -#include "evp.h" -#include "x509.h" +#include +#include +#include +#include +#include +#include +#include #include "ssl_locl.h" -#define BREAK break -/* SSLerr(SSL_F_SSL3_ACCEPT,ERR_R_MALLOC_FAILURE); - * SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,ERR_R_MALLOC_FAILURE); - * SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); - * SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_MALLOC_FAILURE); - * SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE); - */ - -#ifndef NOPROTO 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); @@ -86,23 +80,7 @@ static int ssl3_get_client_key_exchange(SSL *s); static int ssl3_get_client_certificate(SSL *s); static int ssl3_send_hello_request(SSL *s); -#else - -static SSL_METHOD *ssl3_get_server_method(); -static int ssl3_get_client_hello(); -static int ssl3_send_server_hello(); -static int ssl3_send_server_key_exchange(); -static int ssl3_send_certificate_request(); -static int ssl3_send_server_done(); -static int ssl3_get_cert_verify(); -static int ssl3_get_client_key_exchange(); -static int ssl3_get_client_certificate(); -static int ssl3_send_hello_request(); - -#endif - -static SSL_METHOD *ssl3_get_server_method(ver) -int ver; +static SSL_METHOD *ssl3_get_server_method(int ver) { if (ver == SSL3_VERSION) return(SSLv3_server_method()); @@ -110,31 +88,29 @@ int ver; return(NULL); } -SSL_METHOD *SSLv3_server_method() +SSL_METHOD *SSLv3_server_method(void) { static int init=1; static SSL_METHOD SSLv3_server_data; if (init) { - init=0; memcpy((char *)&SSLv3_server_data,(char *)sslv3_base_method(), sizeof(SSL_METHOD)); SSLv3_server_data.ssl_accept=ssl3_accept; SSLv3_server_data.get_ssl_method=ssl3_get_server_method; + init=0; } return(&SSLv3_server_data); } -int ssl3_accept(s) -SSL *s; +int ssl3_accept(SSL *s) { BUF_MEM *buf; unsigned long l,Time=time(NULL); void (*cb)()=NULL; long num1; int ret= -1; - CERT *ct; int new_state,state,skip=0; RAND_seed(&Time,sizeof(Time)); @@ -150,17 +126,11 @@ 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 (;;) { @@ -172,6 +142,7 @@ 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: @@ -215,8 +186,8 @@ SSL *s; if (s->state != SSL_ST_RENEGOTIATE) { + if(s->state != SSL3_ST_SR_MS_SGC) ssl3_init_finished_mac(s); s->state=SSL3_ST_SR_CLNT_HELLO_A; - ssl3_init_finished_mac(s); s->ctx->stats.sess_accept++; } else @@ -285,20 +256,6 @@ 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 */ @@ -312,9 +269,9 @@ 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 + && (s->cert->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) + && EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_EXPORT_PKEYLENGTH(l) ) ) ) @@ -332,9 +289,19 @@ 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))) { /* no cert request */ skip=1; @@ -376,12 +343,18 @@ 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 if MS SGC */ + ret = ssl3_check_client_hello(s); + if(ret <= 0) goto end; + if(ret == 2) s->state = SSL3_ST_SR_MS_SGC; + 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: @@ -523,8 +496,7 @@ end: return(ret); } -static int ssl3_send_hello_request(s) -SSL *s; +static int ssl3_send_hello_request(SSL *s) { unsigned char *p; @@ -546,8 +518,24 @@ SSL *s; return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } -static int ssl3_get_client_hello(s) -SSL *s; +static int ssl3_check_client_hello(SSL *s) + { + int ok; + long n; + + n=ssl3_get_message(s, + SSL3_ST_SR_CERT_A, + SSL3_ST_SR_CERT_B, + -1, + SSL3_RT_MAX_PLAIN_LENGTH, + &ok); + if (!ok) return((int)n); + s->s3->tmp.reuse_message = 1; + if(s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO) return 2; + return 1; +} + +static int ssl3_get_client_hello(SSL *s) { int i,j,ok,al,ret= -1; long n; @@ -555,7 +543,7 @@ SSL *s; unsigned char *p,*d,*q; SSL_CIPHER *c; SSL_COMP *comp=NULL; - STACK *ciphers=NULL; + STACK_OF(SSL_CIPHER) *ciphers=NULL; /* 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, @@ -578,10 +566,9 @@ SSL *s; if (!ok) return((int)n); d=p=(unsigned char *)s->init_buf->data; - /* 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 */ @@ -604,7 +591,9 @@ 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; @@ -643,9 +632,9 @@ SSL *s; #ifdef CIPHER_DEBUG printf("client sent %d ciphers\n",sk_num(ciphers)); #endif - for (i=0; ioptions & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_num(ciphers) == 1)) + if ((s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1)) { /* Very bad for multi-threading.... */ - s->session->cipher= - (SSL_CIPHER *)sk_value(ciphers,0); + s->session->cipher=sk_SSL_CIPHER_value(ciphers, + 0); } else { @@ -700,10 +689,10 @@ SSL *s; { /* See if we have a match */ int m,nn,o,v,done=0; - nn=sk_num(s->ctx->comp_methods); + nn=sk_SSL_COMP_num(s->ctx->comp_methods); for (m=0; mctx->comp_methods,m); + comp=sk_SSL_COMP_value(s->ctx->comp_methods,m); v=comp->id; for (o=0; osession->compress_meth=(comp == NULL)?0:comp->id; if (s->session->ciphers != NULL) - sk_free(s->session->ciphers); + sk_SSL_CIPHER_free(s->session->ciphers); s->session->ciphers=ciphers; if (ciphers == NULL) { @@ -751,7 +740,7 @@ SSL *s; } ciphers=NULL; c=ssl3_choose_cipher(s,s->session->ciphers, - ssl_get_ciphers_by_id(s)); + ssl_get_ciphers_by_id(s)); if (c == NULL) { @@ -765,16 +754,16 @@ SSL *s; { /* Session-id reuse */ #ifdef REUSE_CIPHER_BUG - STACK *sk; + STACK_OF(SSL_CIPHER) *sk; SSL_CIPHER *nc=NULL; SSL_CIPHER *ec=NULL; if (s->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG) { sk=s->session->ciphers; - for (i=0; ialgorithms & SSL_eNULL) nc=c; if (SSL_C_IS_EXPORT(c)) @@ -810,12 +799,11 @@ f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); } err: - if (ciphers != NULL) sk_free(ciphers); + if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers); return(ret); } -static int ssl3_send_server_hello(s) -SSL *s; +static int ssl3_send_server_hello(SSL *s) { unsigned char *buf; unsigned char *p,*d; @@ -881,8 +869,7 @@ SSL *s; return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } -static int ssl3_send_server_done(s) -SSL *s; +static int ssl3_send_server_done(SSL *s) { unsigned char *p; @@ -906,8 +893,7 @@ SSL *s; return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } -static int ssl3_send_server_key_exchange(s) -SSL *s; +static int ssl3_send_server_key_exchange(SSL *s) { #ifndef NO_RSA unsigned char *q; @@ -921,6 +907,7 @@ SSL *s; EVP_PKEY *pkey; unsigned char *p,*d; int al,i; + unsigned int u; unsigned long type; int n; CERT *cert; @@ -932,7 +919,7 @@ SSL *s; 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; @@ -942,10 +929,11 @@ SSL *s; 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, - !SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)); + 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); cert->rsa_tmp=rsa; } @@ -965,9 +953,10 @@ SSL *s; 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) { al=SSL_AD_HANDSHAKE_FAILURE; @@ -1073,15 +1062,14 @@ 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 @@ -1129,12 +1117,11 @@ err: return(-1); } -static int ssl3_send_certificate_request(s) -SSL *s; +static int ssl3_send_certificate_request(SSL *s) { unsigned char *p,*d; int i,j,nl,off,n; - STACK *sk=NULL; + STACK_OF(X509_NAME) *sk=NULL; X509_NAME *name; BUF_MEM *buf; @@ -1159,9 +1146,9 @@ SSL *s; nl=0; if (sk != NULL) { - for (i=0; is3->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) @@ -1289,7 +1273,7 @@ SSL *s; i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING); -#if 1 +#if 0 /* If a bad decrypt, use a random master key */ if ((i != SSL_MAX_MASTER_KEY_LENGTH) || ((p[0] != (s->client_version>>8)) || @@ -1321,7 +1305,7 @@ SSL *s; goto f_err; } - if ((p[0] != (s->version>>8)) || (p[1] != (s->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); @@ -1414,8 +1398,7 @@ err: return(-1); } -static int ssl3_get_cert_verify(s) -SSL *s; +static int ssl3_get_cert_verify(SSL *s) { EVP_PKEY *pkey=NULL; unsigned char *p; @@ -1501,16 +1484,16 @@ SSL *s; #ifndef 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.finish_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); @@ -1553,14 +1536,13 @@ end: return(ret); } -static int ssl3_get_client_certificate(s) -SSL *s; +static int ssl3_get_client_certificate(SSL *s) { int i,ok,al,ret= -1; X509 *x=NULL; unsigned long l,nc,llen,n; unsigned char *p,*d,*q; - STACK *sk=NULL; + STACK_OF(X509) *sk=NULL; n=ssl3_get_message(s, SSL3_ST_SR_CERT_A, @@ -1584,7 +1566,7 @@ 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); @@ -1603,7 +1585,7 @@ SSL *s; } d=p=(unsigned char *)s->init_buf->data; - if ((sk=sk_new_null()) == NULL) + if ((sk=sk_X509_new_null()) == NULL) { SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE); goto err; @@ -1639,7 +1621,7 @@ SSL *s; SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH); goto f_err; } - if (!sk_push(sk,(char *)x)) + if (!sk_X509_push(sk,x)) { SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE); goto err; @@ -1648,7 +1630,7 @@ SSL *s; nc+=l+3; } - if (sk_num(sk) <= 0) + if (sk_X509_num(sk) <= 0) { /* TLS does not mind 0 certs returned */ if (s->version == SSL3_VERSION) @@ -1677,10 +1659,27 @@ 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=(X509 *)sk_shift(sk); + s->session->peer=sk_X509_shift(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; + + sk=NULL; ret=1; if (0) @@ -1690,12 +1689,11 @@ f_err: } err: if (x != NULL) X509_free(x); - if (sk != NULL) sk_pop_free(sk,X509_free); + if (sk != NULL) sk_X509_pop_free(sk,X509_free); return(ret); } -int ssl3_send_server_certificate(s) -SSL *s; +int ssl3_send_server_certificate(SSL *s) { unsigned long l; X509 *x;