}
}
ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
+ ret->ecdh_tmp_auto = cert->ecdh_tmp_auto;
#endif
for (i = 0; i < SSL_PKEY_NUM; i++)
{
- if (cert->pkeys[i].x509 != NULL)
+ CERT_PKEY *cpk = cert->pkeys + i;
+ CERT_PKEY *rpk = ret->pkeys + i;
+ if (cpk->x509 != NULL)
{
- ret->pkeys[i].x509 = cert->pkeys[i].x509;
- CRYPTO_add(&ret->pkeys[i].x509->references, 1,
- CRYPTO_LOCK_X509);
+ rpk->x509 = cpk->x509;
+ CRYPTO_add(&rpk->x509->references, 1, CRYPTO_LOCK_X509);
}
- if (cert->pkeys[i].privatekey != NULL)
+ if (cpk->privatekey != NULL)
{
- ret->pkeys[i].privatekey = cert->pkeys[i].privatekey;
- CRYPTO_add(&ret->pkeys[i].privatekey->references, 1,
+ rpk->privatekey = cpk->privatekey;
+ CRYPTO_add(&cpk->privatekey->references, 1,
CRYPTO_LOCK_EVP_PKEY);
switch(i)
SSLerr(SSL_F_SSL_CERT_DUP, SSL_R_LIBRARY_BUG);
}
}
+
+ if (cpk->chain)
+ {
+ int j;
+ rpk->chain = sk_X509_dup(cpk->chain);
+ if (!rpk->chain)
+ {
+ SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ for (j = 0; j < sk_X509_num(rpk->chain); j++)
+ {
+ X509 *x = sk_X509_value(rpk->chain, j);
+ 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.
*/
ssl_cert_set_default_md(ret);
+ /* Sigalgs set to NULL as we get these from handshake too */
+ ret->sigalgs = NULL;
+ ret->sigalgslen = 0;
+
+ ret->cert_cb = cert->cert_cb;
+ ret->cert_cb_arg = cert->cert_cb_arg;
return(ret);
EC_KEY_free(ret->ecdh_tmp);
#endif
- for (i = 0; i < SSL_PKEY_NUM; i++)
- {
- if (ret->pkeys[i].x509 != NULL)
- X509_free(ret->pkeys[i].x509);
- if (ret->pkeys[i].privatekey != NULL)
- EVP_PKEY_free(ret->pkeys[i].privatekey);
- }
+ ssl_cert_clear_certs(ret);
return NULL;
}
+/* Free up and clear all certificates and chains */
+
+void ssl_cert_clear_certs(CERT *c)
+ {
+ int i;
+ 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;
+ }
+ }
+ }
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++)
- {
- if (c->pkeys[i].x509 != NULL)
- X509_free(c->pkeys[i].x509);
- if (c->pkeys[i].privatekey != NULL)
- EVP_PKEY_free(c->pkeys[i].privatekey);
-#if 0
- if (c->pkeys[i].publickey != NULL)
- EVP_PKEY_free(c->pkeys[i].publickey);
-#endif
- }
+ ssl_cert_clear_certs(c);
+
+ if (c->sigalgs)
+ OPENSSL_free(c->sigalgs);
OPENSSL_free(c);
}
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;
+ }
+
+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)
{
}
/* Add certificate chain to internal SSL BUF_MEM strcuture */
-int ssl_add_cert_chain(SSL *s, X509 *x, unsigned long *l)
+int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l)
{
BUF_MEM *buf = s->init_buf;
int no_chain;
int i;
- if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs)
+ X509 *x;
+ STACK_OF(X509) *extra_certs;
+
+ if (cpk)
+ x = cpk->x509;
+ else
+ x = NULL;
+
+ /* 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;
{
x = sk_X509_value(xs_ctx.chain, i);
- if (ssl_add_cert_to_buf(buf, l, x))
+ if (!ssl_add_cert_to_buf(buf, l, x))
{
X509_STORE_CTX_cleanup(&xs_ctx);
return 0;
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;
}