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.
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 94b6dea..2f43d2e 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -317,11 +317,23 @@
 				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 @@
 			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 @@
 			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 @@
 	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 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 @@
 			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;
 		}