X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=ssl%2Fs3_srvr.c;h=ccf81b8881f385237ae05d6620be08b70035407d;hb=ef0a5354850becf858617d5ec62f440b51bda225;hp=743f8ea235cb4e84c081ea9500c38060e0ffd6ca;hpb=dfeab0689f69c0b4bd3480ffd37a9cacc2f17d9c;p=openssl.git diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 743f8ea235..ccf81b8881 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -59,22 +59,16 @@ #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_send_server_hello(SSL *s); static int ssl3_send_server_key_exchange(SSL *s); @@ -85,22 +79,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 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()); @@ -108,24 +87,23 @@ 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); @@ -133,10 +111,9 @@ SSL *s; long num1; int ret= -1; CERT *ct; - BIO *under; int new_state,state,skip=0; - RAND_seed((unsigned char *)&Time,sizeof(Time)); + RAND_seed(&Time,sizeof(Time)); ERR_clear_error(); clear_sys_error(); @@ -176,6 +153,7 @@ SSL *s; case SSL_ST_BEFORE|SSL_ST_ACCEPT: case SSL_ST_OK|SSL_ST_ACCEPT: + s->server=1; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); if ((s->version>>8) != 3) @@ -215,11 +193,11 @@ SSL *s; { s->state=SSL3_ST_SR_CLNT_HELLO_A; ssl3_init_finished_mac(s); - s->ctx->sess_accept++; + s->ctx->stats.sess_accept++; } else { - s->ctx->sess_accept_renegotiate++; + s->ctx->stats.sess_accept_renegotiate++; s->state=SSL3_ST_SW_HELLO_REQ_A; } break; @@ -238,15 +216,6 @@ SSL *s; break; case SSL3_ST_SW_HELLO_REQ_C: - /* remove buffering on output */ - under=BIO_pop(s->wbio); - if (under != NULL) - s->wbio=under; - else - abort(); /* ok */ - BIO_free(s->bbio); - s->bbio=NULL; - s->state=SSL_ST_OK; ret=1; goto end; @@ -316,16 +285,16 @@ SSL *s; /* only send if a DH key exchange, fortezza or * RSA but we have a sign only certificate */ - if ( s->s3->tmp.use_rsa_tmp || - (l & (SSL_DH|SSL_kFZA)) || - ((l & SSL_kRSA) && - ((ct->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL)|| - ((l & SSL_EXPORT) && - (EVP_PKEY_size(ct->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > 512) - ) - ) + 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) + ) + ) + ) ) - ) { ret=ssl3_send_server_key_exchange(s); if (ret <= 0) goto end; @@ -478,20 +447,14 @@ SSL *s; s->init_buf=NULL; /* remove buffering on output */ - under=BIO_pop(s->wbio); - if (under != NULL) - s->wbio=under; - else - abort(); /* ok */ - BIO_free(s->bbio); - s->bbio=NULL; + ssl_free_wbio_buffer(s); s->new_session=0; s->init_num=0; ssl_update_cache(s,SSL_SESS_CACHE_SERVER); - s->ctx->sess_accept_good++; + s->ctx->stats.sess_accept_good++; /* s->server=1; */ s->handshake_func=ssl3_accept; ret=1; @@ -536,8 +499,7 @@ end: return(ret); } -static int ssl3_send_hello_request(s) -SSL *s; +static int ssl3_send_hello_request(SSL *s) { unsigned char *p; @@ -559,15 +521,15 @@ SSL *s; return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } -static int ssl3_get_client_hello(s) -SSL *s; +static int ssl3_get_client_hello(SSL *s) { int i,j,ok,al,ret= -1; long n; unsigned long id; - unsigned char *p,*d; + unsigned char *p,*d,*q; SSL_CIPHER *c; - STACK *ciphers=NULL; + SSL_COMP *comp=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, @@ -593,6 +555,7 @@ SSL *s; /* 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]; */ p+=2; /* load the client random */ @@ -651,9 +614,16 @@ SSL *s; j=0; id=s->session->cipher->id; - for (i=0; iid == id) { j=1; @@ -662,11 +632,11 @@ SSL *s; } if (j == 0) { - if ((s->options & 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 { @@ -681,8 +651,11 @@ SSL *s; /* compression */ i= *(p++); + q=p; for (j=0; j= i) @@ -693,6 +666,35 @@ SSL *s; goto f_err; } + /* Worst case, we will use the NULL compression, but if we have other + * options, we will now look for them. We have i-1 compression + * algorithms from the client, starting at q. */ + s->s3->tmp.new_compression=NULL; + if (s->ctx->comp_methods != NULL) + { /* See if we have a match */ + int m,nn,o,v,done=0; + + nn=sk_SSL_COMP_num(s->ctx->comp_methods); + for (m=0; mctx->comp_methods,m); + v=comp->id; + for (o=0; os3->tmp.new_compression=comp; + else + comp=NULL; + } + /* TLS does not mind if there is extra stuff */ if (s->version == SSL3_VERSION) { @@ -706,15 +708,14 @@ SSL *s; } } - /* do nothing with compression */ - /* Given s->session->ciphers and ssl_get_ciphers_by_id(s), we must * pick a cipher */ if (!s->hit) { + s->session->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) { @@ -724,7 +725,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) { @@ -738,19 +739,19 @@ 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 (c->algorithms & SSL_EXP) + if (SSL_C_IS_EXPORT(c)) ec=c; } if (nc != NULL) @@ -783,12 +784,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; @@ -833,7 +833,10 @@ SSL *s; p+=i; /* put the compression method */ - *(p++)=0; + if (s->s3->tmp.new_compression == NULL) + *(p++)=0; + else + *(p++)=s->s3->tmp.new_compression->id; /* do the header */ l=(p-d); @@ -851,8 +854,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; @@ -876,8 +878,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; @@ -915,8 +916,8 @@ SSL *s; if ((rsa == NULL) && (s->ctx->default_cert->rsa_tmp_cb != NULL)) { rsa=s->ctx->default_cert->rsa_tmp_cb(s, - (s->s3->tmp.new_cipher->algorithms| - SSL_NOT_EXP)?0:1); + 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; } @@ -938,8 +939,8 @@ SSL *s; dhp=cert->dh_tmp; if ((dhp == NULL) && (cert->dh_tmp_cb != NULL)) dhp=cert->dh_tmp_cb(s, - (s->s3->tmp.new_cipher->algorithms| - SSL_NOT_EXP)?0:1); + !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; @@ -953,13 +954,16 @@ SSL *s; } s->s3->tmp.dh=dh; - if (((dhp->pub_key == NULL) || - (dhp->priv_key == NULL) || - (s->options & SSL_OP_SINGLE_DH_USE)) && - (!DH_generate_key(dh))) + if ((dhp->pub_key == NULL || + dhp->priv_key == NULL || + (s->options & SSL_OP_SINGLE_DH_USE))) { - SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB); - goto err; + if(!DH_generate_key(dh)) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, + ERR_R_DH_LIB); + goto err; + } } else { @@ -1098,12 +1102,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; @@ -1128,9 +1131,9 @@ SSL *s; nl=0; if (sk != NULL) { - for (i=0; iversion>>8)) || - (p[1] != (s->version & 0xff)))) + ((p[0] != (s->client_version>>8)) || + (p[1] != (s->client_version & 0xff)))) { - 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; + 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 if (i != SSL_MAX_MASTER_KEY_LENGTH) @@ -1370,8 +1387,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; @@ -1505,17 +1521,17 @@ f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); } end: + EVP_PKEY_free(pkey); 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, @@ -1558,7 +1574,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; @@ -1594,7 +1610,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; @@ -1603,7 +1619,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) @@ -1635,7 +1651,21 @@ SSL *s; /* This should not be needed */ if (s->session->peer != NULL) X509_free(s->session->peer); - s->session->peer=(X509 *)sk_shift(sk); + s->session->peer=sk_X509_shift(sk); + + /* FIXME: s->session->cert could be a SSL_CTX's struct cert_st! + * struct cert_st is used for too many purposes. It makes + * sense to use the same structure in both SSL_CTX and SSL, + * but then don't put any per-connection data in it. */ +#if 0 /* This could become a workaround, but it would still be utterly ugly */ + if (!ssl_cert_instantiate(&s->cert, s->ctx->default_cert)) + { + handle the error; + } +#endif + s->session->cert->cert_chain=sk; + + sk=NULL; ret=1; if (0) @@ -1645,12 +1675,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;