From: Bodo Möller Date: Thu, 13 May 1999 15:09:38 +0000 (+0000) Subject: New structure type SESS_CERT used instead of CERT inside SSL_SESSION. X-Git-Tag: OpenSSL_0_9_3beta1~86 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=b56bce4fc72c99c1ac85ee7de4d0145fe026bb4e New structure type SESS_CERT used instead of CERT inside SSL_SESSION. While modifying the sources, I found some inconsistencies on the use of s->cert vs. s->session->sess_cert; I don't know if those could really have caused problems, but possibly this is a proper bug-fix and not just a clean-up. --- diff --git a/CHANGES b/CHANGES index a3a90ddc39..b8c3eeddb8 100644 --- a/CHANGES +++ b/CHANGES @@ -50,11 +50,12 @@ Changing settings for an SSL_CTX *ctx after having done s = SSL_new(ctx) does not influence s as it used to. - Projected further changes: In order to clean up things more thoroughly, inside SSL_SESSION - we should not use CERT any longer, but a new structure SESS_CERT - that holds per-session data, and CERT should hold only those - values that can have meaningful defaults in an SSL_CTX. + we don't use CERT any longer, but a new structure SESS_CERT + that holds per-session data (if available); currently, this is + the peer's certificate chain and, for clients, the server's certificate + and temporary key. CERT holds only those values that can have + meaningful defaults in an SSL_CTX. [Bodo Moeller] *) New function X509V3_EXT_i2d() to create an X509_EXTENSION structure diff --git a/apps/s_server.c b/apps/s_server.c index 42ca408ce3..2341949517 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -158,6 +158,7 @@ extern int verify_depth; static char *cipher=NULL; static int s_server_verify=SSL_VERIFY_NONE; +static int s_server_session_id_context = 1; /* anything will do */ static char *s_cert_file=TEST_CERT,*s_key_file=NULL; static char *s_dcert_file=NULL,*s_dkey_file=NULL; #ifdef FIONBIO @@ -521,6 +522,8 @@ bad: if (cipher != NULL) SSL_CTX_set_cipher_list(ctx,cipher); SSL_CTX_set_verify(ctx,s_server_verify,verify_callback); + SSL_CTX_set_session_id_context(ctx,(void*)&s_server_session_id_context, + sizeof s_server_session_id_context); SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile)); diff --git a/crypto/crypto.h b/crypto/crypto.h index 4345200f18..0582759e76 100644 --- a/crypto/crypto.h +++ b/crypto/crypto.h @@ -98,13 +98,14 @@ extern "C" { #define CRYPTO_LOCK_SSL_CTX 12 #define CRYPTO_LOCK_SSL_CERT 13 #define CRYPTO_LOCK_SSL_SESSION 14 -#define CRYPTO_LOCK_SSL 15 -#define CRYPTO_LOCK_RAND 16 -#define CRYPTO_LOCK_MALLOC 17 -#define CRYPTO_LOCK_BIO 18 -#define CRYPTO_LOCK_BIO_GETHOSTBYNAME 19 -#define CRYPTO_LOCK_RSA_BLINDING 20 -#define CRYPTO_NUM_LOCKS 21 +#define CRYPTO_LOCK_SSL_SESS_CERT 15 +#define CRYPTO_LOCK_SSL 16 +#define CRYPTO_LOCK_RAND 17 +#define CRYPTO_LOCK_MALLOC 18 +#define CRYPTO_LOCK_BIO 19 +#define CRYPTO_LOCK_BIO_GETHOSTBYNAME 20 +#define CRYPTO_LOCK_RSA_BLINDING 21 +#define CRYPTO_NUM_LOCKS 22 #define CRYPTO_LOCK 1 #define CRYPTO_UNLOCK 2 diff --git a/ssl/s2_clnt.c b/ssl/s2_clnt.c index 0f188ecaa4..1fe8bd627d 100644 --- a/ssl/s2_clnt.c +++ b/ssl/s2_clnt.c @@ -72,7 +72,7 @@ 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); #define BREAK break @@ -431,9 +431,10 @@ static int get_server_hello(SSL *s) s->session->cipher=sk_SSL_CIPHER_value(cl,i); } - if ((s->session != NULL) && (s->session->peer != NULL)) + if (s->session->peer != NULL) X509_free(s->session->peer); +#if 0 /* What is all this meant to accomplish?? */ /* 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); @@ -442,6 +443,11 @@ static int get_server_hello(SSL *s) /*CRYPTO_add(&s->session->peer->references,1,CRYPTO_LOCK_X509);*/ s->session->peer->references++; CRYPTO_w_unlock(CRYPTO_LOCK_X509); +#else + 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); +#endif s->s2->conn_id_length=s->s2->tmp.conn_id_length; memcpy(s->s2->conn_id,p,s->s2->tmp.conn_id_length); @@ -733,7 +739,7 @@ static int client_certificate(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->sess_cert->key->x509,&p); + n=i2d_X509(s->session->sess_cert->peer_key->x509,&p); EVP_SignUpdate(&ctx,buf,(unsigned int)n); p=buf; @@ -874,7 +880,7 @@ int ssl2_set_certificate(SSL *s, int type, int len, unsigned char *data) { STACK_OF(X509) *sk=NULL; EVP_PKEY *pkey=NULL; - CERT *c=NULL; + SESS_CERT *sc=NULL; int i; X509 *x509=NULL; int ret=0; @@ -900,22 +906,18 @@ int ssl2_set_certificate(SSL *s, int type, int len, unsigned char *data) goto err; } - /* 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->sess_cert) ssl_cert_free(s->session->sess_cert); - s->session->sess_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; @@ -930,7 +932,7 @@ int ssl2_set_certificate(SSL *s, int type, int len, 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: @@ -940,14 +942,14 @@ err: return(ret); } -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) { 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); diff --git a/ssl/s2_srvr.c b/ssl/s2_srvr.c index d5bf0dd62d..d283b22991 100644 --- a/ssl/s2_srvr.c +++ b/ssl/s2_srvr.c @@ -122,8 +122,7 @@ int ssl2_accept(SSL *s) if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->in_handshake++; - if (((s->session == NULL) || (s->session->sess_cert == NULL)) && - (s->cert == NULL)) + if (s->cert == NULL) { SSLerr(SSL_F_SSL2_ACCEPT,SSL_R_NO_CERTIFICATE_SET); return(-1); @@ -376,7 +375,7 @@ static int get_client_master_key(SSL *s) memcpy(s->session->key_arg,&(p[s->s2->tmp.clear+s->s2->tmp.enc]), (unsigned int)keya); - if (s->session->sess_cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL) + if (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL) { ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_NO_PRIVATEKEY); @@ -600,6 +599,30 @@ static int server_hello(SSL *s) *(p++)=SSL2_MT_SERVER_HELLO; /* type */ hit=s->hit; *(p++)=(unsigned char)hit; +#if 1 + if (!hit) + { + if (s->session->sess_cert != NULL) + /* This can't really happen because get_client_hello + * has called ssl_get_new_session, which does not set + * sess_cert. */ + ssl_sess_cert_free(s->session->sess_cert); + s->session->sess_cert = ssl_sess_cert_new(); + if (s->session->sess_cert == NULL) + { + SSLerr(SSL_F_SERVER_HELLO, ERR_R_MALLOC_FAILURE); + return(-1); + } + } + /* If 'hit' is set, then s->sess_cert may be non-NULL or NULL, + * depending on whether it survived in the internal cache + * or was retrieved from an external cache. + * If it is NULL, we cannot put any useful data in it anyway, + * so we don't touch it. + */ + +#else /* That's what used to be done when cert_st and sess_cert_st were + * the same. */ if (!hit) { /* else add cert to session */ CRYPTO_add(&s->cert->references,1,CRYPTO_LOCK_SSL_CERT); @@ -619,8 +642,9 @@ static int server_hello(SSL *s) s->session->sess_cert=s->cert; } } +#endif - if (s->session->sess_cert == NULL) + if (s->cert == NULL) { ssl2_return_error(s,SSL2_PE_NO_CERTIFICATE); SSLerr(SSL_F_SERVER_HELLO,SSL_R_NO_CERTIFICATE_SPECIFIED); @@ -873,7 +897,7 @@ static int request_certificate(SSL *s) (unsigned int)s->s2->key_material_length); EVP_VerifyUpdate(&ctx,ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH); - i=i2d_X509(s->session->sess_cert->pkeys[SSL_PKEY_RSA_ENC].x509,NULL); + i=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,NULL); buf2=(unsigned char *)Malloc((unsigned int)i); if (buf2 == NULL) { @@ -881,7 +905,7 @@ static int request_certificate(SSL *s) goto msg_end; } p2=buf2; - i=i2d_X509(s->session->sess_cert->pkeys[SSL_PKEY_RSA_ENC].x509,&p2); + i=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,&p2); EVP_VerifyUpdate(&ctx,buf2,(unsigned int)i); Free(buf2); diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 98c1f1828c..de07ac76c9 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -679,7 +679,7 @@ static int ssl3_get_server_certificate(SSL *s) X509 *x=NULL; unsigned char *p,*d,*q; STACK_OF(X509) *sk=NULL; - CERT *c; + SESS_CERT *sc; EVP_PKEY *pkey=NULL; n=ssl3_get_message(s, @@ -764,13 +764,13 @@ static int ssl3_get_server_certificate(SSL *s) goto f_err; } - c=ssl_cert_new(); - if (c == NULL) goto err; + sc=ssl_sess_cert_new(); + if (sc == NULL) goto err; - if (s->session->sess_cert) ssl_cert_free(s->session->sess_cert); - s->session->sess_cert=c; + if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert); + s->session->sess_cert=sc; - c->cert_chain=sk; + sc->cert_chain=sk; x=sk_X509_value(sk,0); sk=NULL; @@ -793,14 +793,16 @@ static int ssl3_get_server_certificate(SSL *s) goto f_err; } - c->cert_type=i; + sc->peer_cert_type=i; CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); - if (c->pkeys[i].x509 != NULL) - X509_free(c->pkeys[i].x509); - c->pkeys[i].x509=x; - c->key= &(c->pkeys[i]); - - if ((s->session != NULL) && (s->session->peer != NULL)) + if (sc->peer_pkeys[i].x509 != NULL) /* Why would this ever happen? + * We just created sc a couple of + * lines ago. */ + X509_free(sc->peer_pkeys[i].x509); + sc->peer_pkeys[i].x509=x; + sc->peer_key= &(sc->peer_pkeys[i]); + + if (s->session->peer != NULL) X509_free(s->session->peer); CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); s->session->peer=x; @@ -857,23 +859,23 @@ static int ssl3_get_key_exchange(SSL *s) if (s->session->sess_cert != NULL) { #ifndef NO_RSA - if (s->session->sess_cert->rsa_tmp != NULL) + if (s->session->sess_cert->peer_rsa_tmp != NULL) { - RSA_free(s->session->sess_cert->rsa_tmp); - s->session->sess_cert->rsa_tmp=NULL; + RSA_free(s->session->sess_cert->peer_rsa_tmp); + s->session->sess_cert->peer_rsa_tmp=NULL; } #endif #ifndef NO_DH - if (s->session->sess_cert->dh_tmp) + if (s->session->sess_cert->peer_dh_tmp) { - DH_free(s->session->sess_cert->dh_tmp); - s->session->sess_cert->dh_tmp=NULL; + DH_free(s->session->sess_cert->peer_dh_tmp); + s->session->sess_cert->peer_dh_tmp=NULL; } #endif } else { - s->session->sess_cert=ssl_cert_new(); + s->session->sess_cert=ssl_sess_cert_new(); } param_len=0; @@ -920,13 +922,13 @@ static int ssl3_get_key_exchange(SSL *s) /* this should be because we are using an export cipher */ if (alg & SSL_aRSA) - pkey=X509_get_pubkey(s->session->sess_cert->pkeys[SSL_PKEY_RSA_ENC].x509); + pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); else { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR); goto err; } - s->session->sess_cert->rsa_tmp=rsa; + s->session->sess_cert->peer_rsa_tmp=rsa; } else #endif @@ -986,16 +988,16 @@ static int ssl3_get_key_exchange(SSL *s) #ifndef NO_RSA if (alg & SSL_aRSA) - pkey=X509_get_pubkey(s->session->sess_cert->pkeys[SSL_PKEY_RSA_ENC].x509); + pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); else #endif #ifndef NO_DSA if (alg & SSL_aDSS) - pkey=X509_get_pubkey(s->session->sess_cert->pkeys[SSL_PKEY_DSA_SIGN].x509); + pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509); #endif /* else anonymous DH, so no certificate or pkey. */ - s->session->sess_cert->dh_tmp=dh; + s->session->sess_cert->peer_dh_tmp=dh; dh=NULL; } else if ((alg & SSL_kDHr) || (alg & SSL_kDHd)) @@ -1311,11 +1313,11 @@ static int ssl3_send_client_key_exchange(SSL *s) RSA *rsa; unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; - if (s->session->sess_cert->rsa_tmp != NULL) - rsa=s->session->sess_cert->rsa_tmp; + if (s->session->sess_cert->peer_rsa_tmp != NULL) + rsa=s->session->sess_cert->peer_rsa_tmp; else { - pkey=X509_get_pubkey(s->session->sess_cert->pkeys[SSL_PKEY_RSA_ENC].x509); + pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA) || (pkey->pkey.rsa == NULL)) @@ -1368,8 +1370,8 @@ static int ssl3_send_client_key_exchange(SSL *s) { DH *dh_srvr,*dh_clnt; - if (s->session->sess_cert->dh_tmp != NULL) - dh_srvr=s->session->sess_cert->dh_tmp; + if (s->session->sess_cert->peer_dh_tmp != NULL) + dh_srvr=s->session->sess_cert->peer_dh_tmp; else { /* we get them from the cert */ @@ -1597,7 +1599,7 @@ static int ssl3_check_cert_and_algorithm(SSL *s) int i,idx; long algs; EVP_PKEY *pkey=NULL; - CERT *c; + SESS_CERT *sc; #ifndef NO_RSA RSA *rsa; #endif @@ -1605,9 +1607,9 @@ static int ssl3_check_cert_and_algorithm(SSL *s) DH *dh; #endif - c=s->session->sess_cert; + sc=s->session->sess_cert; - if (c == NULL) + if (sc == NULL) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_INTERNAL_ERROR); goto err; @@ -1620,17 +1622,17 @@ static int ssl3_check_cert_and_algorithm(SSL *s) return(1); #ifndef NO_RSA - rsa=s->session->sess_cert->rsa_tmp; + rsa=s->session->sess_cert->peer_rsa_tmp; #endif #ifndef NO_DH - dh=s->session->sess_cert->dh_tmp; + dh=s->session->sess_cert->peer_dh_tmp; #endif /* This is the passed certificate */ - idx=c->cert_type; - pkey=X509_get_pubkey(c->pkeys[idx].x509); - i=X509_certificate_type(c->pkeys[idx].x509,pkey); + idx=sc->peer_cert_type; + pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509); + i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey); EVP_PKEY_free(pkey); diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index e15d135c85..9d2debf00d 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -110,7 +110,6 @@ int ssl3_accept(SSL *s) void (*cb)()=NULL; long num1; int ret= -1; - CERT *ct; int new_state,state,skip=0; RAND_seed(&Time,sizeof(Time)); @@ -126,17 +125,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->sess_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 (;;) { @@ -261,15 +254,6 @@ 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->sess_cert == NULL) - { - if (s->cert != NULL) - { - CRYPTO_add(&s->cert->references,1,CRYPTO_LOCK_SSL_CERT); - s->session->sess_cert=s->cert; - } - } - ct=s->session->sess_cert; /* clear this, it may get reset by * send_server_key_exchange */ @@ -283,9 +267,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 + && (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) ) ) ) @@ -898,7 +882,7 @@ static int ssl3_send_server_key_exchange(SSL *s) if (s->state == SSL3_ST_SW_KEY_EXCH_A) { type=s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK; - cert=s->session->sess_cert; + cert=s->cert; buf=s->init_buf; @@ -1207,11 +1191,7 @@ static int ssl3_get_client_key_exchange(SSL *s) /* FIX THIS UP EAY EAY EAY EAY */ if (s->s3->tmp.use_rsa_tmp) { - if ((s->session->sess_cert != NULL) && - (s->session->sess_cert->rsa_tmp != NULL)) - rsa=s->session->sess_cert->rsa_tmp; - else if ((s->cert != NULL) && - (s->cert->rsa_tmp != NULL)) + 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 */ @@ -1643,11 +1623,23 @@ 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); + /* 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; diff --git a/ssl/ssl.h b/ssl/ssl.h index c0f95473c1..3d05809150 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -241,11 +241,10 @@ typedef struct ssl_session_st int not_resumable; /* The cert is the certificate used to establish this connection */ - struct cert_st /* CERT */ *sess_cert; - /* XXX should be struct sess_cert_st *sess_cert */ + struct sess_cert_st /* SESS_CERT */ *sess_cert; /* This is the cert for the other end. - * On clients, it will be the same as sess_cert->key->x509 + * On clients, it will be the same as sess_cert->peer_key->x509 * (the latter is not enough as sess_cert is not retained * in the external representation of sessions, see ssl_asn1.c). */ X509 *peer; @@ -1215,6 +1214,7 @@ int SSL_COMP_add_compression_method(int id,char *cm); #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 188 #define SSL_F_SSL_SESSION_NEW 189 #define SSL_F_SSL_SESSION_PRINT_FP 190 +#define SSL_F_SSL_SESS_CERT_NEW 225 #define SSL_F_SSL_SET_CERT 191 #define SSL_F_SSL_SET_FD 192 #define SSL_F_SSL_SET_PKEY 193 diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 3e5eba7605..9a752c3d20 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -318,12 +318,9 @@ void ssl_cert_free(CERT *c) EVP_PKEY_free(c->pkeys[i].publickey); #endif } - if (c->cert_chain != NULL) - sk_X509_pop_free(c->cert_chain,X509_free); Free(c); } -#if 1 int ssl_cert_inst(CERT **o) { /* Create a CERT if there isn't already one @@ -352,32 +349,76 @@ int ssl_cert_inst(CERT **o) return(1); } -#else /* Not needed any longer: SSL's always have their own copy */ -int ssl_cert_instantiate(CERT **o, CERT *d) + +SESS_CERT *ssl_sess_cert_new(void) { - CERT *n; - if (o == NULL) + SESS_CERT *ret; + + ret = Malloc(sizeof *ret); + if (ret == NULL) { - SSLerr(SSL_F_SSL_CERT_INSTANTIATE, ERR_R_PASSED_NULL_PARAMETER); - return(0); + SSLerr(SSL_F_SSL_SESS_CERT_NEW, ERR_R_MALLOC_FAILURE); + return NULL; } - if (*o != NULL && (d == NULL || *o != d)) - return(1); - if ((n = ssl_cert_new()) == NULL) + + memset(ret, 0 ,sizeof *ret); + ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA_ENC]); + ret->references = 1; + + return ret; + } + +void ssl_sess_cert_free(SESS_CERT *sc) + { + int i; + + if (sc == NULL) + return; + + i = CRYPTO_add(&sc->references, -1, CRYPTO_LOCK_SSL_SESS_CERT); +#ifdef REF_PRINT + REF_PRINT("SESS_CERT", sc); +#endif + if (i > 0) + return; +#ifdef REF_CHECK + if (i < 0) { - SSLerr(SSL_F_SSL_CERT_INSTANTIATE, ERR_R_MALLOC_FAILURE); - return(0); + fprintf(stderr,"ssl_sess_cert_free, bad reference count\n"); + abort(); /* ok */ } - if (*o != NULL) - ssl_cert_free(*o); - *o = n; - return(1); - } #endif -int ssl_set_cert_type(CERT *c,int type) + /* i == 0 */ + if (sc->cert_chain != NULL) + sk_X509_pop_free(sc->cert_chain, X509_free); + for (i = 0; i < SSL_PKEY_NUM; i++) + { + if (sc->peer_pkeys[i].x509 != NULL) + X509_free(sc->peer_pkeys[i].x509); +#if 0 /* We don't have the peer's private key. These lines are just + * here as a reminder that we're still using a not-quite-appropriate + * data structure. */ + if (sc->peer_pkeys[i].privatekey != NULL) + EVP_PKEY_free(sc->peer_pkeys[i].privatekey); +#endif + } + +#ifndef NO_RSA + if (sc->peer_rsa_tmp != NULL) + RSA_free(sc->peer_rsa_tmp); +#endif +#ifndef NO_DH + if (sc->peer_dh_tmp != NULL) + DH_free(sc->peer_dh_tmp); +#endif + + Free(sc); + } + +int ssl_set_peer_cert_type(SESS_CERT *sc,int type) { - c->cert_type=type; + sc->peer_cert_type = type; return(1); } diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 1f3bf15b62..358abef1e6 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -165,6 +165,7 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_PACK(0,SSL_F_SSL_RSA_PUBLIC_ENCRYPT,0), "SSL_RSA_PUBLIC_ENCRYPT"}, {ERR_PACK(0,SSL_F_SSL_SESSION_NEW,0), "SSL_SESSION_new"}, {ERR_PACK(0,SSL_F_SSL_SESSION_PRINT_FP,0), "SSL_SESSION_print_fp"}, +{ERR_PACK(0,SSL_F_SSL_SESS_CERT_NEW,0), "SSL_SESS_CERT_NEW"}, {ERR_PACK(0,SSL_F_SSL_SET_CERT,0), "SSL_SET_CERT"}, {ERR_PACK(0,SSL_F_SSL_SET_FD,0), "SSL_set_fd"}, {ERR_PACK(0,SSL_F_SSL_SET_PKEY,0), "SSL_SET_PKEY"}, diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index fa48f0ef8b..b063be276d 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -275,19 +275,32 @@ typedef struct cert_st CERT_PKEY pkeys[SSL_PKEY_NUM]; - STACK_OF(X509) *cert_chain; /* XXX should only exist in sess_cert_st */ - int references; /* >1 only if SSL_copy_session_id is used */ } CERT; -#if 0 /* XXX not yet */ typedef struct sess_cert_st -{ - /* anything that we want to keep per session */ -} SESS_CERT; + { + STACK_OF(X509) *cert_chain; /* as received from peer (not for SSL2) */ + + /* The 'peer_...' members are used only by clients. */ + int peer_cert_type; + + CERT_PKEY *peer_key; /* points to an element of peer_pkeys (never NULL!) */ + CERT_PKEY peer_pkeys[SSL_PKEY_NUM]; + /* Obviously we don't have the private keys of these, + * so maybe we shouldn't even use the CERT_PKEY type here. */ + +#ifndef NO_RSA + RSA *peer_rsa_tmp; /* not used for SSL 2 */ +#endif +#ifndef NO_DH + DH *peer_dh_tmp; /* not used for SSL 2 */ #endif + int references; /* actually always 1 at the moment */ + } SESS_CERT; + /*#define MAC_DEBUG */ @@ -353,13 +366,11 @@ void ssl_clear_cipher_ctx(SSL *s); int ssl_clear_bad_session(SSL *s); CERT *ssl_cert_new(void); CERT *ssl_cert_dup(CERT *cert); -#if 1 int ssl_cert_inst(CERT **o); -#else -int ssl_cert_instantiate(CERT **o, CERT *d); -#endif void ssl_cert_free(CERT *c); -int ssl_set_cert_type(CERT *c, int type); +SESS_CERT *ssl_sess_cert_new(void); +void ssl_sess_cert_free(SESS_CERT *sc); +int ssl_set_peer_cert_type(SESS_CERT *c, int type); int ssl_get_new_session(SSL *s, int session); int ssl_get_prev_session(SSL *s, unsigned char *session,int len); int ssl_cipher_id_cmp(SSL_CIPHER *a,SSL_CIPHER *b); diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 88d4b50c75..259725c7a1 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -115,6 +115,8 @@ SSL_SESSION *SSL_SESSION_new(void) int ssl_get_new_session(SSL *s, int session) { + /* This gets used by clients and servers. */ + SSL_SESSION *ss=NULL; if ((ss=SSL_SESSION_new()) == NULL) return(0); @@ -183,6 +185,8 @@ int ssl_get_new_session(SSL *s, int session) int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len) { + /* This is used only by servers. */ + SSL_SESSION *ret=NULL,data; int copy=1; @@ -377,7 +381,7 @@ void SSL_SESSION_free(SSL_SESSION *ss) memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH); memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH); memset(ss->session_id,0,SSL_MAX_SSL_SESSION_ID_LENGTH); - if (ss->sess_cert != NULL) ssl_cert_free(ss->sess_cert); + if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert); if (ss->peer != NULL) X509_free(ss->peer); if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers); memset(ss,0,sizeof(*ss));