Additional "chain_cert" functions.

PR#3169

This patch, which currently applies successfully against master and
1_0_2, adds the following functions:

SSL_[CTX_]select_current_cert() - set the current certificate without
disturbing the existing structure.

SSL_[CTX_]get0_chain_certs() - get the current certificate's chain.

SSL_[CTX_]clear_chain_certs() - clear the current certificate's chain.

The patch also adds these functions to, and fixes some existing errors
in, SSL_CTX_add1_chain_cert.pod.
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 2205337..7114304 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3424,6 +3424,13 @@
 		else
 			return ssl_cert_add0_chain_cert(s->cert, (X509 *)parg);
 
+	case SSL_CTRL_GET_CHAIN_CERTS:
+		*(STACK_OF(X509) **)parg = s->cert->key->chain;
+		break;
+
+	case SSL_CTRL_SELECT_CURRENT_CERT:
+		return ssl_cert_select_current(s->cert, (X509 *)parg);
+
 #ifndef OPENSSL_NO_EC
 	case SSL_CTRL_GET_CURVES:
 		{
@@ -3923,6 +3930,13 @@
 		else
 			return ssl_cert_add0_chain_cert(ctx->cert, (X509 *)parg);
 
+	case SSL_CTRL_GET_CHAIN_CERTS:
+		*(STACK_OF(X509) **)parg = ctx->cert->key->chain;
+		break;
+
+	case SSL_CTRL_SELECT_CURRENT_CERT:
+		return ssl_cert_select_current(ctx->cert, (X509 *)parg);
+
 	default:
 		return(0);
 		}
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 013345e..be33b66 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -1935,6 +1935,9 @@
 #define SSL_CTRL_GET_RAW_CIPHERLIST		110
 #define SSL_CTRL_GET_EC_POINT_FORMATS		111
 
+#define SSL_CTRL_GET_CHAIN_CERTS		115
+#define SSL_CTRL_SELECT_CURRENT_CERT		116
+
 #define DTLSv1_get_timeout(ssl, arg) \
 	SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
 #define DTLSv1_handle_timeout(ssl) \
@@ -1984,8 +1987,14 @@
 	SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509)
 #define SSL_CTX_add1_chain_cert(ctx,x509) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509)
+#define SSL_CTX_get0_chain_certs(ctx,px509) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
+#define SSL_CTX_clear_chain_certs(ctx) \
+	SSL_CTX_set0_chain(ctx,NULL)
 #define SSL_CTX_build_cert_chain(ctx, flags) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
+#define SSL_CTX_select_current_cert(ctx,x509) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)x509)
 
 #define SSL_CTX_set0_verify_cert_store(ctx,st) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st)
@@ -2004,8 +2013,15 @@
 	SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509)
 #define SSL_add1_chain_cert(ctx,x509) \
 	SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509)
+#define SSL_get0_chain_certs(ctx,px509) \
+	SSL_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
+#define SSL_clear_chain_certs(ctx) \
+	SSL_set0_chain(ctx,NULL)
 #define SSL_build_cert_chain(s, flags) \
 	SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
+#define SSL_select_current_cert(ctx,x509) \
+	SSL_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)x509)
+
 #define SSL_set0_verify_cert_store(s,st) \
 	SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st)
 #define SSL_set1_verify_cert_store(s,st) \
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index d442e54..9d77ef7 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -599,6 +599,20 @@
 	return 1;
 	}
 
+int ssl_cert_select_current(CERT *c, X509 *x)
+	{
+	int i;
+	for (i = 0; i < SSL_PKEY_NUM; i++)
+		{
+		if (c->pkeys[i].x509 == x)
+			{
+			c->key = &c->pkeys[i];
+			return 1;
+			}
+		}
+	return 0;
+	}
+
 void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg)
 	{
 	c->cert_cb = cb;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index ce4c348..51e8891 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -996,6 +996,7 @@
 int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain);
 int ssl_cert_add0_chain_cert(CERT *c, X509 *x);
 int ssl_cert_add1_chain_cert(CERT *c, X509 *x);
+int ssl_cert_select_current(CERT *c, X509 *x);
 void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg);
 
 int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk);