New structure type SESS_CERT used instead of CERT inside SSL_SESSION.
authorBodo Möller <bodo@openssl.org>
Thu, 13 May 1999 15:09:38 +0000 (15:09 +0000)
committerBodo Möller <bodo@openssl.org>
Thu, 13 May 1999 15:09:38 +0000 (15:09 +0000)
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.

12 files changed:
CHANGES
apps/s_server.c
crypto/crypto.h
ssl/s2_clnt.c
ssl/s2_srvr.c
ssl/s3_clnt.c
ssl/s3_srvr.c
ssl/ssl.h
ssl/ssl_cert.c
ssl/ssl_err.c
ssl/ssl_locl.h
ssl/ssl_sess.c

diff --git a/CHANGES b/CHANGES
index a3a90dd..b8c3eed 100644 (file)
--- a/CHANGES
+++ b/CHANGES
      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
index 42ca408..2341949 100644 (file)
@@ -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));
 
index 4345200..0582759 100644 (file)
@@ -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
index 0f188ec..1fe8bd6 100644 (file)
@@ -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);
index d5bf0dd..d283b22 100644 (file)
@@ -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);
 
index 98c1f18..de07ac7 100644 (file)
@@ -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);
 
        
index e15d135..9d2debf 100644 (file)
@@ -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;
index c0f9547..3d05809 100644 (file)
--- 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
index 3e5eba7..9a752c3 100644 (file)
@@ -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);
        }
 
index 1f3bf15..358abef 100644 (file)
@@ -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"},
index fa48f0e..b063be2 100644 (file)
@@ -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);
index 88d4b50..259725c 100644 (file)
@@ -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));