New function SSL_CTX_use_certificate_chain_file.

Submitted by:
Reviewed by:
PR:
diff --git a/ssl/ssl.h b/ssl/ssl.h
index b041341..0f4fbe8 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -874,6 +874,7 @@
 int	SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, char *file, int type);
 int	SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, char *file, int type);
 int	SSL_CTX_use_certificate_file(SSL_CTX *ctx, char *file, int type);
+int	SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */
 STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
 int	SSL_add_file_cert_subjects_to_stack(STACK *stackCAs,
 					    const char *file);
@@ -1168,6 +1169,7 @@
 #define SSL_F_SSL_CTX_SET_SSL_VERSION			 170
 #define SSL_F_SSL_CTX_USE_CERTIFICATE			 171
 #define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1		 172
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE	 220
 #define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE		 173
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY			 174
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1		 175
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 3d9a835..eae7ad7 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -142,6 +142,7 @@
 {ERR_PACK(0,SSL_F_SSL_CTX_SET_SSL_VERSION,0),	"SSL_CTX_set_ssl_version"},
 {ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE,0),	"SSL_CTX_use_certificate"},
 {ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1,0),	"SSL_CTX_use_certificate_ASN1"},
+{ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,0),	"SSL_CTX_USE_CERTIFICATE_CHAIN_FILE"},
 {ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,0),	"SSL_CTX_use_certificate_file"},
 {ERR_PACK(0,SSL_F_SSL_CTX_USE_PRIVATEKEY,0),	"SSL_CTX_use_PrivateKey"},
 {ERR_PACK(0,SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1,0),	"SSL_CTX_use_PrivateKey_ASN1"},
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index a2db46e..0f87752 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -735,3 +735,81 @@
 	}
 
 
+#ifndef NO_STDIO
+/* Read a file that contains our certificate in "PEM" format,
+ * possibly followed by a sequence of CA certificates that should be
+ * sent to the peer in the Certificate message.
+ */
+int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file)
+	{
+	BIO *in;
+	int ret=0;
+	X509 *x=NULL;
+
+	in=BIO_new(BIO_s_file_internal());
+	if (in == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_BUF_LIB);
+		goto end;
+		}
+
+	if (BIO_read_filename(in,file) <= 0)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_SYS_LIB);
+		goto end;
+		}
+
+	x=PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback);
+	if (x == NULL)
+		{
+		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_PEM_LIB);
+		goto end;
+		}
+
+	ret=SSL_CTX_use_certificate(ctx,x);
+	if (ERR_peek_error() != 0)
+		ret = 0;  /* Key/certificate mismatch doesn't imply ret==0 ... */
+	if (ret)
+		{
+		/* If we could set up our certificate, now proceed to
+		 * the CA certificates.
+		 */
+		X509 *ca;
+		int r;
+		unsigned long err;
+		
+		if (ctx->extra_certs != NULL) 
+			{
+			sk_X509_pop_free(ctx->extra_certs, X509_free);
+			ctx->extra_certs = NULL;
+			}
+
+		while ((ca = PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback))
+			!= NULL)
+			{
+			r = SSL_CTX_add_extra_chain_cert(ctx, ca);
+			if (!r) 
+				{
+				X509_free(ca);
+				ret = 0;
+				goto end;
+				}
+			/* Note that we must not free r if it was succesully
+			 * added to the chain (while we must free the main
+			 * certificate, since its reference count is increased
+			 * by SSL_CTX_use_certificate). */
+			}
+		/* When the while loop ends, it's usually just EOF. */
+		err = ERR_peek_error();
+		if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
+			(void) ERR_get_error();
+		else 
+			ret = 0; /* some real error */
+		}
+
+end:
+	if (x != NULL) X509_free(x);
+	if (in != NULL) BIO_free(in);
+	return(ret);
+	}
+#endif