In article <[EMAIL PROTECTED]> you wrote:
> Ralf S. Engelschall wrote:
>> What makes you thinking that the settings are blown away by
>> SSL_use_certificate and friends? These functions already have checks like ``if
>> ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert))'' which
>> prevents them from blowing away the settings, Ben.

> Scrambled brains. You are right.

> A related point: I really object to all this duplicated code, such as
> the above. It really ought to be wrapped up in some function somewhere.
> In fact, I'll bet if all the duplicated code were removed from OpenSSL
> it would be 50% of the size or less. As well as much easier to maintain.

Good suggestion. Your wish is my pleasure. I've changed my patch to use a
ssl_cert_renew() function which and also reduced all six occurences in
ssl_rsa.c of the redundant code by calls to this new function (yes, it reduces
the amount of code lines dramatically). Votes for the appended take 3 of my
patch?

                                       Ralf S. Engelschall
                                       [EMAIL PROTECTED]
                                       www.engelschall.com

Index: CHANGES
===================================================================
RCS file: /e/openssl/cvs/openssl/CHANGES,v
retrieving revision 1.99
diff -u -r1.99 CHANGES
--- CHANGES     1999/02/25 11:03:17     1.99
+++ CHANGES     1999/02/25 13:12:12
@@ -5,6 +5,19 @@
 
  Changes between 0.9.1c and 0.9.2
 
+  *) Add a bunch of SSL_xxx() functions for configuring the temporary RSA and
+     DH private keys and callback functions which directly correspond to their
+     SSL_CTX_xxx() functions but work on a per-connection basis. This is
+     needed for applications which have to configure certificates on a
+     per-connection basis (e.g. mod_ssl) instead of a per-context basis (e.g.
+     s_server). For the RSA certificate situation is makes no difference, but
+     for the DSA certificate situation this fixes the "no shared cipher"
+     problem where the cipher selection procedure failed because the
+     temporary keys are not overtaken from the context.  The new functions
+     are in detail: SSL_need_tmp_RSA, SSL_set_tmp_rsa, SSL_set_tmp_dh,
+     SSL_set_tmp_rsa_callback and SSL_set_tmp_dh_callback.
+     [Ralf S. Engelschall]
+
   *) Fix the cipher decision scheme for export ciphers: the export bits are
      *not* within SSL_MKEY_MASK or SSL_AUTH_MASK, they are within
      SSL_EXP_MASK.  So, the original variable has to be used instead of the
Index: ssl/s3_lib.c
===================================================================
RCS file: /e/openssl/cvs/openssl/ssl/s3_lib.c,v
retrieving revision 1.13
diff -u -r1.13 s3_lib.c
--- ssl/s3_lib.c        1999/02/25 11:03:18     1.13
+++ ssl/s3_lib.c        1999/02/25 13:05:36
@@ -546,6 +546,26 @@
        {
        int ret=0;
 
+#if !defined(NO_DSA) || !defined(NO_RSA)
+       if (
+#ifndef NO_RSA
+           cmd == SSL_CTRL_SET_TMP_RSA ||
+           cmd == SSL_CTRL_SET_TMP_RSA_CB ||
+#endif
+#ifndef NO_DSA
+           cmd == SSL_CTRL_SET_TMP_DH ||
+           cmd == SSL_CTRL_SET_TMP_DH_CB ||
+#endif
+               0)
+               {
+               if (!ssl_cert_renew(&s->cert, s->ctx->default_cert)) 
+                       {
+                       SSLerr(SSL_F_SSL3_CTRL, ERR_R_MALLOC_FAILURE);
+                       return(0);
+                       }
+               }
+#endif
+
        switch (cmd)
                {
        case SSL_CTRL_GET_SESSION_REUSED:
@@ -566,6 +586,69 @@
        case SSL_CTRL_GET_FLAGS:
                ret=(int)(s->s3->flags);
                break;
+#ifndef NO_RSA
+       case SSL_CTRL_NEED_TMP_RSA:
+               if ((s->cert != NULL) && (s->cert->rsa_tmp == NULL) &&
+                   ((s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL) ||
+                    (EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey) > 
+(512/8))))
+                       ret = 1;
+               break;
+       case SSL_CTRL_SET_TMP_RSA:
+               {
+                       RSA *rsa = (RSA *)parg;
+                       if (rsa == NULL) {
+                               SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+                               return(ret);
+                       }
+                       if ((rsa = RSAPrivateKey_dup(rsa)) == NULL) {
+                               SSLerr(SSL_F_SSL3_CTRL, ERR_R_RSA_LIB);
+                               return(ret);
+                       }
+                       if (s->cert->rsa_tmp != NULL)
+                               RSA_free(s->cert->rsa_tmp);
+                       s->cert->rsa_tmp = rsa;
+                       ret = 1;
+               }
+               break;
+       case SSL_CTRL_SET_TMP_RSA_CB:
+#ifndef NOPROTO
+               s->cert->rsa_tmp_cb = (RSA *(*)(SSL *, int, int))parg;
+#else
+               s->cert->rsa_tmp_cb = (RSA *(*)())parg;
+#endif
+               break;
+#endif
+#ifndef NO_DH
+       case SSL_CTRL_SET_TMP_DH:
+               {
+                       DH *dh = (DH *)parg;
+                       if (dh == NULL) {
+                               SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+                               return(ret);
+                       }
+                       if ((dh = DHparams_dup(dh)) == NULL) {
+                               SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
+                               return(ret);
+                       }
+                       if (!DH_generate_key(dh)) {
+                               DH_free(dh);
+                               SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
+                               return(ret);
+                       }
+                       if (s->cert->dh_tmp != NULL)
+                               DH_free(s->cert->dh_tmp);
+                       s->cert->dh_tmp = dh;
+                       ret = 1;
+               }
+               break;
+       case SSL_CTRL_SET_TMP_DH_CB:
+#ifndef NOPROTO
+               s->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))parg;
+#else
+               s->cert->dh_tmp_cb = (DH *(*)())parg;
+#endif
+               break;
+#endif
        default:
                break;
                }
Index: ssl/ssl.err
===================================================================
RCS file: /e/openssl/cvs/openssl/ssl/ssl.err,v
retrieving revision 1.3
diff -u -r1.3 ssl.err
--- ssl/ssl.err 1999/02/20 11:50:07     1.3
+++ ssl/ssl.err 1999/02/25 09:49:02
@@ -113,6 +113,7 @@
 #define SSL_F_TLS1_ENC                                  210
 #define SSL_F_TLS1_SETUP_KEY_BLOCK                      211
 #define SSL_F_WRITE_PENDING                             212
+#define SSL_F_SSL3_CTRL                                         213
 
 /* Reason codes. */
 #define SSL_R_APP_DATA_IN_HANDSHAKE                     100
Index: ssl/ssl.h
===================================================================
RCS file: /e/openssl/cvs/openssl/ssl/ssl.h,v
retrieving revision 1.10
diff -u -r1.10 ssl.h
--- ssl/ssl.h   1999/02/21 21:58:59     1.10
+++ ssl/ssl.h   1999/02/25 09:49:04
@@ -784,6 +784,13 @@
 #define SSL_CTX_set_tmp_dh(ctx,dh) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
 
+#define SSL_need_tmp_RSA(ssl) \
+       SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL)
+#define SSL_set_tmp_rsa(ssl,rsa) \
+       SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
+#define SSL_set_tmp_dh(ssl,dh) \
+       SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
+
 #define SSL_CTX_add_extra_chain_cert(ctx,x509) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509)
 
@@ -1029,6 +1036,12 @@
 void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
                                 DH *(*dh)(SSL *ssl,int export,int keylength));
 
+void SSL_set_tmp_rsa_callback(SSL *ssl,
+                                 RSA *(*cb)(SSL *ssl,int export,
+                                            int keylength));
+void SSL_set_tmp_dh_callback(SSL *ssl,
+                                DH *(*dh)(SSL *ssl,int export,int keylength));
+
 #ifdef HEADER_COMP_H
 int SSL_COMP_add_compression_method(int id,COMP_METHOD *cm);
 #else
@@ -1258,6 +1271,9 @@
 void SSL_CTX_set_tmp_rsa_callback();
 void SSL_CTX_set_tmp_dh_callback();
 
+void SSL_set_tmp_rsa_callback();
+void SSL_set_tmp_dh_callback();
+
 /* #endif */
 
 #endif
@@ -1378,6 +1394,7 @@
 #define SSL_F_TLS1_ENC                                  210
 #define SSL_F_TLS1_SETUP_KEY_BLOCK                      211
 #define SSL_F_WRITE_PENDING                             212
+#define SSL_F_SSL3_CTRL                                         213
 
 /* Reason codes. */
 #define SSL_R_APP_DATA_IN_HANDSHAKE                     100
Index: ssl/ssl_cert.c
===================================================================
RCS file: /e/openssl/cvs/openssl/ssl/ssl_cert.c,v
retrieving revision 1.3
diff -u -r1.3 ssl_cert.c
--- ssl/ssl_cert.c      1999/01/07 19:15:58     1.3
+++ ssl/ssl_cert.c      1999/02/25 13:06:42
@@ -144,6 +144,21 @@
        Free(c);
        }
 
+int ssl_cert_renew(CERT **o, CERT *d)
+       {
+       CERT *n;
+       if (o == NULL)
+           return(0);
+       if (*o != NULL && d != NULL && *o != d)
+           return(1);
+       if ((n = ssl_cert_new()) == NULL)
+           return(0);
+       if (*o != NULL) 
+           ssl_cert_free(*o);
+       *o = n;
+       return(1);
+       }
+
 int ssl_set_cert_type(c, type)
 CERT *c;
 int type;
Index: ssl/ssl_err.c
===================================================================
RCS file: /e/openssl/cvs/openssl/ssl/ssl_err.c,v
retrieving revision 1.3
diff -u -r1.3 ssl_err.c
--- ssl/ssl_err.c       1999/02/20 11:50:07     1.3
+++ ssl/ssl_err.c       1999/02/25 09:49:04
@@ -175,6 +175,7 @@
 {ERR_PACK(0,SSL_F_TLS1_ENC,0), "TLS1_ENC"},
 {ERR_PACK(0,SSL_F_TLS1_SETUP_KEY_BLOCK,0),     "TLS1_SETUP_KEY_BLOCK"},
 {ERR_PACK(0,SSL_F_WRITE_PENDING,0),    "WRITE_PENDING"},
+{ERR_PACK(0,SSL_F_SSL3_CTRL,0),        "SSL3_CTRL"},
 {0,NULL},
        };
 
Index: ssl/ssl_lib.c
===================================================================
RCS file: /e/openssl/cvs/openssl/ssl/ssl_lib.c,v
retrieving revision 1.12
diff -u -r1.12 ssl_lib.c
--- ssl/ssl_lib.c       1999/02/21 21:58:59     1.12
+++ ssl/ssl_lib.c       1999/02/25 09:42:48
@@ -1899,6 +1899,14 @@
                                                        int keylength))
     { SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,0,(char *)dh); }
 
+void SSL_set_tmp_rsa_callback(SSL *ssl,RSA *(*cb)(SSL *ssl,int export,
+                                                         int keylength))
+    { SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA_CB,0,(char *)cb); }
+
+void SSL_set_tmp_dh_callback(SSL *ssl,DH *(*dh)(SSL *ssl,int export,
+                                                       int keylength))
+    { SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH_CB,0,(char *)dh); }
+
 #if defined(_WINDLL) && defined(WIN16)
 #include "../crypto/bio/bss_file.c"
 #endif
Index: ssl/ssl_locl.h
===================================================================
RCS file: /e/openssl/cvs/openssl/ssl/ssl_locl.h,v
retrieving revision 1.7
diff -u -r1.7 ssl_locl.h
--- ssl/ssl_locl.h      1999/02/21 21:58:59     1.7
+++ ssl/ssl_locl.h      1999/02/25 12:55:43
@@ -348,6 +348,7 @@
 void ssl_clear_cipher_ctx(SSL *s);
 int ssl_clear_bad_session(SSL *s);
 CERT *ssl_cert_new(void);
+int ssl_cert_renew(CERT **o, CERT *d);
 void ssl_cert_free(CERT *c);
 int ssl_set_cert_type(CERT *c, int type);
 int ssl_get_new_session(SSL *s, int session);
@@ -483,6 +484,7 @@
 void ssl_clear_cipher_ctx();
 int ssl_clear_bad_session();
 CERT *ssl_cert_new();
+int ssl_cert_renew();
 void ssl_cert_free();
 int ssl_set_cert_type();
 int ssl_get_new_session();
Index: ssl/ssl_rsa.c
===================================================================
RCS file: /e/openssl/cvs/openssl/ssl/ssl_rsa.c,v
retrieving revision 1.3
diff -u -r1.3 ssl_rsa.c
--- ssl/ssl_rsa.c       1999/02/16 09:22:21     1.3
+++ ssl/ssl_rsa.c       1999/02/25 13:03:59
@@ -76,27 +76,17 @@
 SSL *ssl;
 X509 *x;
        {
-       CERT *c;
-
        if (x == NULL)
                {
                SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER);
                return(0);
                }
-       if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert))
+       if (!ssl_cert_renew(&ssl->cert, ssl->ctx->default_cert)) 
                {
-               c=ssl_cert_new();
-               if (c == NULL)
-                       {
-                       SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE);
-                       return(0);
-                       }
-               if (ssl->cert != NULL) ssl_cert_free(ssl->cert);
-               ssl->cert=c;
+               SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+               return(0);
                }
-       c=ssl->cert;
-
-       return(ssl_set_cert(c,x));
+       return(ssl_set_cert(ssl->cert,x));
        }
 
 #ifndef NO_STDIO
@@ -177,7 +167,6 @@
 SSL *ssl;
 RSA *rsa;
        {
-       CERT *c;
        EVP_PKEY *pkey;
        int ret;
 
@@ -186,19 +175,11 @@
                SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
                return(0);
                }
-
-        if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert))
-                {
-                c=ssl_cert_new();
-               if (c == NULL)
-                       {
-                       SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE);
-                       return(0);
-                       }
-                if (ssl->cert != NULL) ssl_cert_free(ssl->cert);
-               ssl->cert=c;
+       if (!ssl_cert_renew(&ssl->cert, ssl->ctx->default_cert)) 
+               {
+               SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE);
+               return(0);
                }
-       c=ssl->cert;
        if ((pkey=EVP_PKEY_new()) == NULL)
                {
                SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB);
@@ -208,7 +189,7 @@
        CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA);
        EVP_PKEY_assign_RSA(pkey,rsa);
 
-       ret=ssl_set_pkey(c,pkey);
+       ret=ssl_set_pkey(ssl->cert,pkey);
        EVP_PKEY_free(pkey);
        return(ret);
        }
@@ -366,7 +347,6 @@
 SSL *ssl;
 EVP_PKEY *pkey;
        {
-       CERT *c;
        int ret;
 
        if (pkey == NULL)
@@ -374,21 +354,12 @@
                SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
                return(0);
                }
-
-        if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert))
-                {
-                c=ssl_cert_new();
-               if (c == NULL)
-                       {
-                       SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE);
-                       return(0);
-                       }
-                if (ssl->cert != NULL) ssl_cert_free(ssl->cert);
-               ssl->cert=c;
+       if (!ssl_cert_renew(&ssl->cert, ssl->ctx->default_cert)) 
+               {
+               SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE);
+               return(0);
                }
-       c=ssl->cert;
-
-       ret=ssl_set_pkey(c,pkey);
+       ret=ssl_set_pkey(ssl->cert,pkey);
        return(ret);
        }
 
@@ -464,27 +435,17 @@
 SSL_CTX *ctx;
 X509 *x;
        {
-       CERT *c;
-
        if (x == NULL)
                {
                SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER);
                return(0);
                }
-
-       if (ctx->default_cert == NULL)
+       if (!ssl_cert_renew(&ctx->default_cert, NULL))
                {
-               c=ssl_cert_new();
-               if (c == NULL)
-                       {
-                       SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE);
-                       return(0);
-                       }
-               ctx->default_cert=c;
+               SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+               return(0);
                }
-       c=ctx->default_cert;
-
-       return(ssl_set_cert(c,x));
+       return(ssl_set_cert(ctx->default_cert,x));
        }
 
 static int ssl_set_cert(c,x)
@@ -648,7 +609,6 @@
 RSA *rsa;
        {
        int ret;
-       CERT *c;
        EVP_PKEY *pkey;
 
        if (rsa == NULL)
@@ -656,18 +616,11 @@
                SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
                return(0);
                }
-       if (ctx->default_cert == NULL)
+       if (!ssl_cert_renew(&ctx->default_cert, NULL))
                {
-               c=ssl_cert_new();
-               if (c == NULL)
-                       {
-                       SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE);
-                       return(0);
-                       }
-               ctx->default_cert=c;
+               SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE);
+               return(0);
                }
-       c=ctx->default_cert;
-
        if ((pkey=EVP_PKEY_new()) == NULL)
                {
                SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB);
@@ -677,7 +630,7 @@
        CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA);
        EVP_PKEY_assign_RSA(pkey,rsa);
 
-       ret=ssl_set_pkey(c,pkey);
+       ret=ssl_set_pkey(ctx->default_cert,pkey);
        EVP_PKEY_free(pkey);
        return(ret);
        }
@@ -759,27 +712,17 @@
 SSL_CTX *ctx;
 EVP_PKEY *pkey;
        {
-       CERT *c;
-
        if (pkey == NULL)
                {
                SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
                return(0);
                }
-               
-       if (ctx->default_cert == NULL)
+       if (!ssl_cert_renew(&ctx->default_cert, NULL))
                {
-               c=ssl_cert_new();
-               if (c == NULL)
-                       {
-                       SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE);
-                       return(0);
-                       }
-               ctx->default_cert=c;
+               SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE);
+               return(0);
                }
-       c=ctx->default_cert;
-
-       return(ssl_set_pkey(c,pkey));
+       return(ssl_set_pkey(ctx->default_cert,pkey));
        }
 
 #ifndef NO_STDIO
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to