X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs2_clnt.c;h=b549628dbdbd9d5c2d8b2d4790195058e58812f0;hp=33112eeb3fa0c3e4eb23aabdee9d2c348e36c68f;hb=bbd1c84e6eabdbfbc2e2d1a4f4e9ab1d21b6453b;hpb=06ab81f9f7b055a4456798cb9ef3266160438a08 diff --git a/ssl/s2_clnt.c b/ssl/s2_clnt.c index 33112eeb3f..b549628dbd 100644 --- a/ssl/s2_clnt.c +++ b/ssl/s2_clnt.c @@ -56,14 +56,14 @@ * [including the GNU Public Licence.] */ -#include -#include "rand.h" -#include "buffer.h" -#include "objects.h" #include "ssl_locl.h" -#include "evp.h" +#ifndef OPENSSL_NO_SSL2 +#include +#include +#include +#include +#include -#ifndef NOPROTO static SSL_METHOD *ssl2_get_client_method(int ver); static int get_server_finished(SSL *s); static int get_server_verify(SSL *s); @@ -72,24 +72,11 @@ static int client_hello(SSL *s); static int client_master_key(SSL *s); static int client_finished(SSL *s); static int client_certificate(SSL *s); -static int ssl_rsa_public_encrypt(CERT *c, int len, unsigned char *from, +static int ssl_rsa_public_encrypt(SESS_CERT *sc, int len, unsigned char *from, unsigned char *to,int padding); -#else -static SSL_METHOD *ssl2_get_client_method(); -static int get_server_finished(); -static int get_server_verify(); -static int get_server_hello(); -static int client_hello(); -static int client_master_key(); -static int client_finished(); -static int client_certificate(); -static int ssl_rsa_public_encrypt(); -#endif - #define BREAK break -static SSL_METHOD *ssl2_get_client_method(ver) -int ver; +static SSL_METHOD *ssl2_get_client_method(int ver) { if (ver == SSL2_VERSION) return(SSLv2_client_method()); @@ -97,24 +84,23 @@ int ver; return(NULL); } -SSL_METHOD *SSLv2_client_method() +SSL_METHOD *SSLv2_client_method(void) { static int init=1; static SSL_METHOD SSLv2_client_data; if (init) { - init=0; memcpy((char *)&SSLv2_client_data,(char *)sslv2_base_method(), sizeof(SSL_METHOD)); SSLv2_client_data.ssl_connect=ssl2_connect; SSLv2_client_data.get_ssl_method=ssl2_get_client_method; + init=0; } return(&SSLv2_client_data); } -int ssl2_connect(s) -SSL *s; +int ssl2_connect(SSL *s) { unsigned long l=time(NULL); BUF_MEM *buf=NULL; @@ -122,7 +108,7 @@ SSL *s; void (*cb)()=NULL; int new_state,state; - RAND_seed(&l,sizeof(l)); + RAND_add(&l,sizeof(l),0); ERR_clear_error(); clear_sys_error(); @@ -259,7 +245,7 @@ SSL *s; /* ERR_clear_error();*/ /* If we want to cache session-ids in the client - * and we sucessfully add the session-id to the + * and we successfully add the session-id to the * cache, and there is a callback, then pass it out. * 26/11/96 - eay - only add if not a re-used session. */ @@ -296,13 +282,12 @@ end: return(ret); } -static int get_server_hello(s) -SSL *s; +static int get_server_hello(SSL *s) { unsigned char *buf; unsigned char *p; int i,j; - STACK *sk=NULL,*cl; + STACK_OF(SSL_CIPHER) *sk=NULL,*cl, *prio, *allow; buf=(unsigned char *)s->init_buf->data; p=buf; @@ -325,7 +310,13 @@ SSL *s; SSL_R_PEER_ERROR); return(-1); } +#ifdef __APPLE_CC__ + /* The Rhapsody 5.5 (a.k.a. MacOS X) compiler bug + * workaround. */ + s->hit=(i=*(p++))?1:0; +#else s->hit=(*(p++))?1:0; +#endif s->s2->tmp.cert_type= *(p++); n2s(p,i); if (i < s->version) s->version=i; @@ -377,7 +368,7 @@ SSL *s; */ #endif - /* we need to do this incase we were trying to reuse a + /* we need to do this in case we were trying to reuse a * client session but others are already reusing it. * If this was a new 'blank' session ID, the session-id * length will still be 0 */ @@ -411,7 +402,7 @@ SSL *s; /* load the ciphers */ sk=ssl_bytes_to_cipher_list(s,p,s->s2->tmp.csl, - &s->session->ciphers); + &s->session->ciphers); p+=s->s2->tmp.csl; if (sk == NULL) { @@ -420,48 +411,74 @@ SSL *s; return(-1); } - sk_set_cmp_func(sk,ssl_cipher_ptr_id_cmp); + sk_SSL_CIPHER_set_cmp_func(sk,ssl_cipher_ptr_id_cmp); /* get the array of ciphers we will accept */ - cl=ssl_get_ciphers_by_id(s); - + cl=SSL_get_ciphers(s); + sk_SSL_CIPHER_set_cmp_func(cl,ssl_cipher_ptr_id_cmp); + + /* + * If server preference flag set, choose the first + * (highest priority) cipher the server sends, otherwise + * client preference has priority. + */ + if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) + { + prio = sk; + allow = cl; + } + else + { + prio = cl; + allow = sk; + } /* In theory we could have ciphers sent back that we * don't want to use but that does not matter since we - * will check against the list we origionally sent and + * will check against the list we originally sent and * for performance reasons we should not bother to match * the two lists up just to check. */ - for (i=0; i= 0) + if (sk_SSL_CIPHER_find(allow, + sk_SSL_CIPHER_value(prio,i)) >= 0) break; } - if (i >= sk_num(cl)) + if (i >= sk_SSL_CIPHER_num(prio)) { ssl2_return_error(s,SSL2_PE_NO_CIPHER); SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_MATCH); return(-1); } - s->session->cipher=(SSL_CIPHER *)sk_value(cl,i); - } + s->session->cipher=sk_SSL_CIPHER_value(prio,i); - if ((s->session != NULL) && (s->session->peer != NULL)) - X509_free(s->session->peer); - /* hmmm, can we have the problem of the other session with this - * cert, Free's it before we increment the reference count. */ - CRYPTO_w_lock(CRYPTO_LOCK_X509); - s->session->peer=s->session->cert->key->x509; - CRYPTO_add(&s->session->peer->references,1,CRYPTO_LOCK_X509); - CRYPTO_w_unlock(CRYPTO_LOCK_X509); + if (s->session->peer != NULL) /* can't happen*/ + { + ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_SERVER_HELLO, SSL_R_INTERNAL_ERROR); + return(-1); + } + s->session->peer = s->session->sess_cert->peer_key->x509; + /* peer_key->x509 has been set by ssl2_set_certificate. */ + CRYPTO_add(&s->session->peer->references, 1, CRYPTO_LOCK_X509); + } + + if (s->session->peer != s->session->sess_cert->peer_key->x509) + /* can't happen */ + { + ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_SERVER_HELLO, SSL_R_INTERNAL_ERROR); + return(-1); + } + s->s2->conn_id_length=s->s2->tmp.conn_id_length; memcpy(s->s2->conn_id,p,s->s2->tmp.conn_id_length); return(1); } -static int client_hello(s) -SSL *s; +static int client_hello(SSL *s) { unsigned char *buf; unsigned char *p,*d; @@ -485,7 +502,7 @@ SSL *s; p=buf; /* header */ d=p+9; /* data section */ *(p++)=SSL2_MT_CLIENT_HELLO; /* type */ - s2n(SSL2_CLIENT_VERSION,p); /* version */ + s2n(SSL2_VERSION,p); /* version */ n=j=0; n=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),d); @@ -516,7 +533,7 @@ SSL *s; s->s2->challenge_length=SSL2_CHALLENGE_LENGTH; s2n(SSL2_CHALLENGE_LENGTH,p); /* challenge length */ /*challenge id data*/ - RAND_bytes(s->s2->challenge,SSL2_CHALLENGE_LENGTH); + RAND_pseudo_bytes(s->s2->challenge,SSL2_CHALLENGE_LENGTH); memcpy(d,s->s2->challenge,SSL2_CHALLENGE_LENGTH); d+=SSL2_CHALLENGE_LENGTH; @@ -528,15 +545,14 @@ SSL *s; return(ssl2_do_write(s)); } -static int client_master_key(s) -SSL *s; +static int client_master_key(SSL *s) { unsigned char *buf; unsigned char *p,*d; int clear,enc,karg,i; SSL_SESSION *sess; - EVP_CIPHER *c; - EVP_MD *md; + const EVP_CIPHER *c; + const EVP_MD *md; buf=(unsigned char *)s->init_buf->data; if (s->state == SSL2_ST_SEND_CLIENT_MASTER_KEY_A) @@ -559,12 +575,19 @@ SSL *s; /* make key_arg data */ i=EVP_CIPHER_iv_length(c); sess->key_arg_length=i; - if (i > 0) RAND_bytes(sess->key_arg,i); + if (i > 0) RAND_pseudo_bytes(sess->key_arg,i); /* make a master key */ i=EVP_CIPHER_key_length(c); sess->master_key_length=i; - if (i > 0) RAND_bytes(sess->master_key,i); + if (i > 0) + { + if (RAND_bytes(sess->master_key,i) <= 0) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + return(-1); + } + } if (sess->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC) enc=8; @@ -584,7 +607,7 @@ SSL *s; memcpy(d,sess->master_key,(unsigned int)clear); d+=clear; - enc=ssl_rsa_public_encrypt(sess->cert,enc, + enc=ssl_rsa_public_encrypt(sess->sess_cert,enc, &(sess->master_key[clear]),d, (s->s2->ssl2_rollback)?RSA_SSLV23_PADDING:RSA_PKCS1_PADDING); if (enc <= 0) @@ -614,8 +637,7 @@ SSL *s; return(ssl2_do_write(s)); } -static int client_finished(s) -SSL *s; +static int client_finished(SSL *s) { unsigned char *p; @@ -633,8 +655,7 @@ SSL *s; } /* read the data and then respond */ -static int client_certificate(s) -SSL *s; +static int client_certificate(SSL *s) { unsigned char *buf; unsigned char *p,*d; @@ -749,7 +770,7 @@ SSL *s; EVP_SignUpdate(&ctx,s->s2->key_material, (unsigned int)s->s2->key_material_length); EVP_SignUpdate(&ctx,cert_ch,(unsigned int)cert_ch_len); - n=i2d_X509(s->session->cert->key->x509,&p); + n=i2d_X509(s->session->sess_cert->peer_key->x509,&p); EVP_SignUpdate(&ctx,buf,(unsigned int)n); p=buf; @@ -763,7 +784,7 @@ SSL *s; { /* this is not good. If things have failed it * means there so something wrong with the key. - * We will contiune with a 0 length signature + * We will continue with a 0 length signature */ } memset(&ctx,0,sizeof(ctx)); @@ -778,8 +799,7 @@ SSL *s; return(ssl2_do_write(s)); } -static int get_server_verify(s) -SSL *s; +static int get_server_verify(SSL *s) { unsigned char *p; int i; @@ -822,8 +842,7 @@ SSL *s; return(1); } -static int get_server_finished(s) -SSL *s; +static int get_server_finished(SSL *s) { unsigned char *buf; unsigned char *p; @@ -888,15 +907,11 @@ SSL *s; } /* loads in the certificate from the server */ -int ssl2_set_certificate(s, type, len, data) -SSL *s; -int type; -int len; -unsigned char *data; +int ssl2_set_certificate(SSL *s, int type, int len, unsigned char *data) { - STACK *sk=NULL; + STACK_OF(X509) *sk=NULL; EVP_PKEY *pkey=NULL; - CERT *c=NULL; + SESS_CERT *sc=NULL; int i; X509 *x509=NULL; int ret=0; @@ -908,8 +923,7 @@ unsigned char *data; goto err; } - if (((sk=sk_new_null()) == NULL) || - (!sk_push(sk,(char *)x509))) + if ((sk=sk_X509_new_null()) == NULL || !sk_X509_push(sk,x509)) { SSLerr(SSL_F_SSL2_SET_CERTIFICATE,ERR_R_MALLOC_FAILURE); goto err; @@ -922,23 +936,21 @@ unsigned char *data; SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED); goto err; } + ERR_clear_error(); /* but we keep s->verify_result */ + s->session->verify_result = s->verify_result; - /* cert for ssl */ - c=ssl_cert_new(); - if (c == NULL) + /* server's cert for this session */ + sc=ssl_sess_cert_new(); + if (sc == NULL) { ret= -1; goto err; } + if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert); + s->session->sess_cert=sc; - /* cert for session */ - if (s->session->cert) ssl_cert_free(s->session->cert); - s->session->cert=c; - -/* c->cert_type=type; */ - - c->pkeys[SSL_PKEY_RSA_ENC].x509=x509; - c->key= &(c->pkeys[SSL_PKEY_RSA_ENC]); + sc->peer_pkeys[SSL_PKEY_RSA_ENC].x509=x509; + sc->peer_key= &(sc->peer_pkeys[SSL_PKEY_RSA_ENC]); pkey=X509_get_pubkey(x509); x509=NULL; @@ -953,28 +965,24 @@ unsigned char *data; goto err; } - if (!ssl_set_cert_type(c,SSL2_CT_X509_CERTIFICATE)) + if (!ssl_set_peer_cert_type(sc,SSL2_CT_X509_CERTIFICATE)) goto err; ret=1; err: - sk_free(sk); + sk_X509_free(sk); X509_free(x509); EVP_PKEY_free(pkey); return(ret); } -static int ssl_rsa_public_encrypt(c, len, from, to, padding) -CERT *c; -int len; -unsigned char *from; -unsigned char *to; -int padding; +static int ssl_rsa_public_encrypt(SESS_CERT *sc, int len, unsigned char *from, + unsigned char *to, int padding) { EVP_PKEY *pkey=NULL; int i= -1; - if ((c == NULL) || (c->key->x509 == NULL) || - ((pkey=X509_get_pubkey(c->key->x509)) == NULL)) + if ((sc == NULL) || (sc->peer_key->x509 == NULL) || + ((pkey=X509_get_pubkey(sc->peer_key->x509)) == NULL)) { SSLerr(SSL_F_SSL_RSA_PUBLIC_ENCRYPT,SSL_R_NO_PUBLICKEY); return(-1); @@ -993,4 +1001,10 @@ end: EVP_PKEY_free(pkey); return(i); } +#else /* !OPENSSL_NO_SSL2 */ + +# if PEDANTIC +static void *dummy=&dummy; +# endif +#endif