summaryrefslogtreecommitdiffstats
path: root/ssl/ssl_cert.c
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2012-04-06 17:22:48 +0000
committerDr. Stephen Henson <steve@openssl.org>2012-04-06 17:22:48 +0000
commit37b16c84bbf06a804d74e017507008fafaef9c89 (patch)
tree10c71df30a2ba81ecb5d676554f6899cf6df3cd9 /ssl/ssl_cert.c
parent0ac89e8f5472dbca4c1dd2cfbbe13968c31c505d (diff)
Add support for distinct certificate chains per key type and per SSL
structure. Before this the only way to add a custom chain was in the parent SSL_CTX (which is shared by all key types and SSL structures) or rely on auto chain building (which is performed on each handshake) from the trust store. (backport from HEAD)
Diffstat (limited to 'ssl/ssl_cert.c')
-rw-r--r--ssl/ssl_cert.c91
1 files changed, 84 insertions, 7 deletions
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 571839c9b4..c48aa20923 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -317,11 +317,23 @@ CERT *ssl_cert_dup(CERT *cert)
SSLerr(SSL_F_SSL_CERT_DUP, SSL_R_LIBRARY_BUG);
}
}
+
+ if (cpk->chain)
+ {
+ rpk->chain = sk_X509_dup(cpk->chain);
+ if (!rpk->chain)
+ {
+ SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ for (i = 0; i < sk_X509_num(rpk->chain); i++)
+ {
+ X509 *x = sk_X509_value(rpk->chain, i);
+ CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+ }
+ }
}
- /* ret->extra_certs *should* exist, but currently the own certificate
- * chain is held inside SSL_CTX */
-
ret->references=1;
/* Set digests to defaults. NB: we don't copy existing values as they
* will be set during handshake.
@@ -353,6 +365,8 @@ err:
X509_free(rpk->x509);
if (rpk->privatekey != NULL)
EVP_PKEY_free(rpk->privatekey);
+ if (rpk->chain)
+ sk_X509_pop_free(rpk->chain, X509_free);
}
@@ -397,6 +411,8 @@ void ssl_cert_free(CERT *c)
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);
@@ -433,6 +449,59 @@ int ssl_cert_inst(CERT **o)
return(1);
}
+int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain)
+ {
+ CERT_PKEY *cpk = c->key;
+ if (!cpk)
+ return 0;
+ if (cpk->chain)
+ sk_X509_pop_free(cpk->chain, X509_free);
+ cpk->chain = chain;
+ return 1;
+ }
+
+int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain)
+ {
+ STACK_OF(X509) *dchain;
+ X509 *x;
+ int i;
+ if (!chain)
+ return ssl_cert_set0_chain(c, NULL);
+ dchain = sk_X509_dup(chain);
+ if (!dchain)
+ return 0;
+ for (i = 0; i < sk_X509_num(dchain); i++)
+ {
+ x = sk_X509_value(dchain, i);
+ CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+ }
+ if (!ssl_cert_set0_chain(c, dchain))
+ {
+ sk_X509_pop_free(dchain, X509_free);
+ return 0;
+ }
+ return 1;
+ }
+
+int ssl_cert_add0_chain_cert(CERT *c, X509 *x)
+ {
+ CERT_PKEY *cpk = c->key;
+ if (!cpk)
+ return 0;
+ if (!cpk->chain)
+ cpk->chain = sk_X509_new_null();
+ if (!cpk->chain || !sk_X509_push(cpk->chain, x))
+ return 0;
+ return 1;
+ }
+
+int ssl_cert_add1_chain_cert(CERT *c, X509 *x)
+ {
+ if (!ssl_cert_add0_chain_cert(c, x))
+ return 0;
+ CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+ return 1;
+ }
SESS_CERT *ssl_sess_cert_new(void)
{
@@ -884,13 +953,22 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l)
int i;
X509 *x;
+ STACK_OF(X509) *extra_certs;
if (cpk)
x = cpk->x509;
else
x = NULL;
- if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs)
+ /* If we have a certificate specific chain use it, else use
+ * parent ctx.
+ */
+ if (cpk && cpk->chain)
+ extra_certs = cpk->chain;
+ else
+ extra_certs = s->ctx->extra_certs;
+
+ if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs)
no_chain = 1;
else
no_chain = 0;
@@ -933,10 +1011,9 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l)
X509_STORE_CTX_cleanup(&xs_ctx);
}
}
- /* Thawte special :-) */
- for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++)
+ for (i=0; i<sk_X509_num(extra_certs); i++)
{
- x=sk_X509_value(s->ctx->extra_certs,i);
+ x=sk_X509_value(extra_certs,i);
if (!ssl_add_cert_to_buf(buf, l, x))
return 0;
}