Add new ctrl to retrieve client certificate types, print out
[openssl.git] / ssl / ssl_cert.c
index 222f703284355ba821c09a32f2bd07d960e239c2..59a8544431e15ae0f809e2c100e3ad7ce4b3f118 100644 (file)
@@ -160,18 +160,18 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void)
        return ssl_x509_store_ctx_idx;
        }
 
-static void ssl_cert_set_default_md(CERT *cert)
+void ssl_cert_set_default_md(CERT *cert)
        {
        /* Set digest values to defaults */
 #ifndef OPENSSL_NO_DSA
-       cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_dss1();
+       cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
 #endif
 #ifndef OPENSSL_NO_RSA
        cert->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
        cert->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
 #endif
 #ifndef OPENSSL_NO_ECDSA
-       cert->pkeys[SSL_PKEY_ECC].digest = EVP_ecdsa();
+       cert->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
 #endif
        }
 
@@ -334,6 +334,23 @@ CERT *ssl_cert_dup(CERT *cert)
                                CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
                                }
                        }
+               rpk->valid_flags = 0;
+                if (cert->pkeys[i].authz != NULL)
+                       {
+                       /* Just copy everything. */
+                       ret->pkeys[i].authz_length =
+                               cert->pkeys[i].authz_length;
+                       ret->pkeys[i].authz =
+                               OPENSSL_malloc(ret->pkeys[i].authz_length);
+                       if (ret->pkeys[i].authz == NULL)
+                               {
+                               SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
+                               return(NULL);
+                               }
+                       memcpy(ret->pkeys[i].authz,
+                              cert->pkeys[i].authz,
+                              cert->pkeys[i].authz_length);
+                       }
                }
        
        ret->references=1;
@@ -341,9 +358,50 @@ CERT *ssl_cert_dup(CERT *cert)
         * will be set during handshake.
         */
        ssl_cert_set_default_md(ret);
-       /* Sigalgs set to NULL as we get these from handshake too */
-       ret->sigalgs = NULL;
-       ret->sigalgslen = 0;
+       /* Peer sigalgs set to NULL as we get these from handshake too */
+       ret->peer_sigalgs = NULL;
+       ret->peer_sigalgslen = 0;
+       /* Configured sigalgs however we copy across */
+
+       if (cert->conf_sigalgs)
+               {
+               ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen);
+               if (!ret->conf_sigalgs)
+                       goto err;
+               memcpy(ret->conf_sigalgs, cert->conf_sigalgs,
+                                               cert->conf_sigalgslen);
+               ret->conf_sigalgslen = cert->conf_sigalgslen;
+               }
+       else
+               ret->conf_sigalgs = NULL;
+
+       if (cert->client_sigalgs)
+               {
+               ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen);
+               if (!ret->client_sigalgs)
+                       goto err;
+               memcpy(ret->client_sigalgs, cert->client_sigalgs,
+                                               cert->client_sigalgslen);
+               ret->client_sigalgslen = cert->client_sigalgslen;
+               }
+       else
+               ret->client_sigalgs = NULL;
+       /* Shared sigalgs also NULL */
+       ret->shared_sigalgs = NULL;
+       /* Copy any custom client certificate types */
+       if (cert->ctypes)
+               {
+               ret->ctypes = OPENSSL_malloc(cert->ctype_num);
+               if (!ret->ctypes)
+                       goto err;
+               memcpy(ret->ctypes, cert->ctypes, cert->ctype_num);
+               ret->ctype_num = cert->ctype_num;
+               }
+
+       ret->cert_flags = cert->cert_flags;
+
+       ret->cert_cb = cert->cert_cb;
+       ret->cert_cb_arg = cert->cert_cb_arg;
 
        return(ret);
        
@@ -363,21 +421,43 @@ err:
                EC_KEY_free(ret->ecdh_tmp);
 #endif
 
-       for (i = 0; i < SSL_PKEY_NUM; i++)
-               {
-               CERT_PKEY *rpk = ret->pkeys + i;
-               if (rpk->x509 != NULL)
-                       X509_free(rpk->x509);
-               if (rpk->privatekey != NULL)
-                       EVP_PKEY_free(rpk->privatekey);
-               if (rpk->chain)
-                       sk_X509_pop_free(rpk->chain, X509_free);
-               }
-
+       ssl_cert_clear_certs(ret);
 
        return NULL;
        }
 
+/* Free up and clear all certificates and chains */
+
+void ssl_cert_clear_certs(CERT *c)
+       {
+       int i;
+       if (c == NULL)
+               return;
+       for (i = 0; i<SSL_PKEY_NUM; i++)
+               {
+               CERT_PKEY *cpk = c->pkeys + i;
+               if (cpk->x509)
+                       {
+                       X509_free(cpk->x509);
+                       cpk->x509 = NULL;
+                       }
+               if (cpk->privatekey)
+                       {
+                       EVP_PKEY_free(cpk->privatekey);
+                       cpk->privatekey = NULL;
+                       }
+               if (cpk->chain)
+                       {
+                       sk_X509_pop_free(cpk->chain, X509_free);
+                       cpk->chain = NULL;
+                       }
+#ifndef OPENSSL_NO_TLSEXT
+                if (cpk->authz != NULL)
+                       OPENSSL_free(cpk->authz);
+#endif
+               cpk->valid_flags = 0;
+               }
+       }
 
 void ssl_cert_free(CERT *c)
        {
@@ -409,22 +489,17 @@ void ssl_cert_free(CERT *c)
        if (c->ecdh_tmp) EC_KEY_free(c->ecdh_tmp);
 #endif
 
-       for (i=0; i<SSL_PKEY_NUM; i++)
-               {
-               CERT_PKEY *cpk = c->pkeys + i;
-               if (cpk->x509 != NULL)
-                       X509_free(cpk->x509);
-               if (cpk->privatekey != NULL)
-                       EVP_PKEY_free(cpk->privatekey);
-               if (cpk->chain)
-                       sk_X509_pop_free(cpk->chain, X509_free);
-#if 0
-               if (c->pkeys[i].publickey != NULL)
-                       EVP_PKEY_free(c->pkeys[i].publickey);
-#endif
-               }
-       if (c->sigalgs)
-               OPENSSL_free(c->sigalgs);
+       ssl_cert_clear_certs(c);
+       if (c->peer_sigalgs)
+               OPENSSL_free(c->peer_sigalgs);
+       if (c->conf_sigalgs)
+               OPENSSL_free(c->conf_sigalgs);
+       if (c->client_sigalgs)
+               OPENSSL_free(c->client_sigalgs);
+       if (c->shared_sigalgs)
+               OPENSSL_free(c->shared_sigalgs);
+       if (c->ctypes)
+               OPENSSL_free(c->ctypes);
        OPENSSL_free(c);
        }
 
@@ -510,6 +585,12 @@ int ssl_cert_add1_chain_cert(CERT *c, X509 *x)
        return 1;
        }
 
+void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg)
+       {
+       c->cert_cb = cb;
+       c->cert_cb_arg = arg;
+       }
+
 SESS_CERT *ssl_sess_cert_new(void)
        {
        SESS_CERT *ret;