Add code to download CRLs based on CRLDP extension.

Just a sample, real world applications would have to be cleverer.
diff --git a/apps/apps.c b/apps/apps.c
index adf7866..7f057fb 100644
--- a/apps/apps.c
+++ b/apps/apps.c
@@ -929,7 +929,7 @@
 	return(x);
 	}
 
-X509_CRL *load_crl(char *infile, int format)
+X509_CRL *load_crl(const char *infile, int format)
 	{
 	X509_CRL *x=NULL;
 	BIO *in=NULL;
@@ -2974,6 +2974,83 @@
 		}
 	}
 
+/* Get first http URL from a DIST_POINT structure */
+
+static const char *get_dp_url(DIST_POINT *dp)
+	{
+	GENERAL_NAMES *gens;
+	GENERAL_NAME *gen;
+	int i, gtype;
+	ASN1_STRING *uri;
+	if (!dp->distpoint || dp->distpoint->type != 0)
+		return NULL;
+	gens = dp->distpoint->name.fullname;
+	for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
+		{
+		gen = sk_GENERAL_NAME_value(gens, i);
+		uri = GENERAL_NAME_get0_value(gen, &gtype);
+		if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6)
+			{
+			char *uptr = (char *)ASN1_STRING_data(uri);
+			if (!strncmp(uptr, "http://", 7))
+				return uptr;
+			}
+		}		
+	return NULL;
+	}
+		
+
+/* Look through a CRLDP structure and attempt to find an http URL to downloads
+ * a CRL from.
+ */
+
+static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp)
+	{
+	int i;
+	const char *urlptr = NULL;
+	for (i = 0; i < sk_DIST_POINT_num(crldp); i++)
+		{
+		DIST_POINT *dp = sk_DIST_POINT_value(crldp, i);
+		urlptr = get_dp_url(dp);
+		if (urlptr)
+			return load_crl(urlptr, FORMAT_HTTP);
+		}
+	return NULL;
+	}
+
+/* Example of downloading CRLs from CRLDP: not usable for real world
+ * as it always downloads, doesn't support non-blocking I/O and doesn't
+ * cache anything.
+ */
+
+static STACK_OF(X509_CRL) *crls_http_cb(X509_STORE_CTX *ctx, X509_NAME *nm)
+	{
+	X509 *x;
+	STACK_OF(X509_CRL) *crls = NULL;
+	X509_CRL *crl;
+	STACK_OF(DIST_POINT) *crldp;
+	x = X509_STORE_CTX_get_current_cert(ctx);
+	crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
+	crl = load_crl_crldp(crldp);
+	sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
+	if (!crl)
+		return NULL;
+	crls = sk_X509_CRL_new_null();
+	sk_X509_CRL_push(crls, crl);
+	/* Try to download delta CRL */
+	crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL);
+	crl = load_crl_crldp(crldp);
+	sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
+	if (crl)
+		sk_X509_CRL_push(crls, crl);
+	return crls;
+	}
+
+void store_setup_crl_download(X509_STORE *st)
+	{
+	X509_STORE_set_lookup_crls_cb(st, crls_http_cb);
+	}
+
 /*
  * Platform-specific sections
  */
diff --git a/apps/apps.h b/apps/apps.h
index e9d21d5..d9debd1 100644
--- a/apps/apps.h
+++ b/apps/apps.h
@@ -245,7 +245,7 @@
 int add_oid_section(BIO *err, CONF *conf);
 X509 *load_cert(BIO *err, const char *file, int format,
 	const char *pass, ENGINE *e, const char *cert_descrip);
-X509_CRL *load_crl(char *infile, int format);
+X509_CRL *load_crl(const char *infile, int format);
 int load_cert_crl_http(const char *url, BIO *err,
 					X509 **pcert, X509_CRL **pcrl);
 EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin,
@@ -343,6 +343,8 @@
 				const unsigned char *checkemail,
 				const char *checkip);
 
+void store_setup_crl_download(X509_STORE *st);
+
 #define FORMAT_UNDEF    0
 #define FORMAT_ASN1     1
 #define FORMAT_TEXT     2
diff --git a/apps/s_apps.h b/apps/s_apps.h
index f6e85ee..83526ec 100644
--- a/apps/s_apps.h
+++ b/apps/s_apps.h
@@ -197,9 +197,9 @@
 			int *badarg, BIO *err, STACK_OF(OPENSSL_STRING) **pstr);
 int args_ssl_call(SSL_CTX *ctx, BIO *err, SSL_CONF_CTX *cctx,
 				STACK_OF(OPENSSL_STRING) *str, int no_ecdhe);
-int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls);
+int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download);
 int ssl_load_stores(SSL_CTX *ctx,
 			const char *vfyCApath, const char *vfyCAfile,
 			const char *chCApath, const char *chCAfile,
-			STACK_OF(X509_CRL) *crls);
+			STACK_OF(X509_CRL) *crls, int crl_download);
 #endif
diff --git a/apps/s_cb.c b/apps/s_cb.c
index 8ba8a04..96bc5db 100644
--- a/apps/s_cb.c
+++ b/apps/s_cb.c
@@ -1660,32 +1660,28 @@
 	{
 	X509_CRL *crl;
 	int i;
-	if (crls)
+	for (i = 0; i < sk_X509_CRL_num(crls); i++)
 		{
-		for (i = 0; i < sk_X509_CRL_num(crls); i++)
-			{
-			crl = sk_X509_CRL_value(crls, i);
-			X509_STORE_add_crl(st, crl);
-			}
+		crl = sk_X509_CRL_value(crls, i);
+		X509_STORE_add_crl(st, crl);
 		}
 	return 1;
 	}
 
-int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls)
+int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download)
 	{
 	X509_STORE *st;
-	if (crls)
-		{
-		st = SSL_CTX_get_cert_store(ctx);
-		add_crls_store(st, crls);
-		}
+	st = SSL_CTX_get_cert_store(ctx);
+	add_crls_store(st, crls);
+	if (crl_download)
+		store_setup_crl_download(st);
 	return 1;
 	}
 
 int ssl_load_stores(SSL_CTX *ctx,
 			const char *vfyCApath, const char *vfyCAfile,
 			const char *chCApath, const char *chCAfile,
-			STACK_OF(X509_CRL) *crls)
+			STACK_OF(X509_CRL) *crls, int crl_download)
 	{
 	X509_STORE *vfy = NULL, *ch = NULL;
 	int rv = 0;
@@ -1696,6 +1692,8 @@
 			goto err;
 		add_crls_store(vfy, crls);
 		SSL_CTX_set1_verify_cert_store(ctx, vfy);
+		if (crl_download)
+			store_setup_crl_download(vfy);
 		}
 	if (chCApath || chCAfile)
 		{
diff --git a/apps/s_client.c b/apps/s_client.c
index 27c1696..1646556 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -635,6 +635,7 @@
 
 	char *crl_file = NULL;
 	int crl_format = FORMAT_PEM;
+	int crl_download = 0;
 	STACK_OF(X509_CRL) *crls = NULL;
 
 	meth=SSLv23_client_method();
@@ -711,6 +712,8 @@
 			if (--argc < 1) goto bad;
 			crl_file= *(++argv);
 			}
+		else if	(strcmp(*argv,"-crl_download") == 0)
+			crl_download = 1;
 		else if	(strcmp(*argv,"-sess_out") == 0)
 			{
 			if (--argc < 1) goto bad;
@@ -1192,7 +1195,8 @@
 		goto end;
 		}
 
-	if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile, crls))
+	if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile,
+						crls, crl_download))
 		{
 		BIO_printf(bio_err, "Error loading store locations\n");
 		ERR_print_errors(bio_err);
@@ -1254,7 +1258,7 @@
 		/* goto end; */
 		}
 
-	ssl_ctx_add_crls(ctx, crls);
+	ssl_ctx_add_crls(ctx, crls, crl_download);
 
 	if (!set_cert_key_stuff(ctx,cert,key, NULL, build_chain))
 		goto end;
diff --git a/apps/s_server.c b/apps/s_server.c
index 2de8565..dc0cc36 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -1715,12 +1715,12 @@
 	if (vpm)
 		SSL_CTX_set1_param(ctx, vpm);
 
-	ssl_ctx_add_crls(ctx, crls);
+	ssl_ctx_add_crls(ctx, crls, 0);
 
 	if (!args_ssl_call(ctx, bio_err, cctx, ssl_args, no_ecdhe))
 		goto end;
 
-	if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile, crls))
+	if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile, crls, 0))
 		{
 		BIO_printf(bio_err, "Error loading store locations\n");
 		ERR_print_errors(bio_err);
@@ -1783,7 +1783,7 @@
 		if (vpm)
 			SSL_CTX_set1_param(ctx2, vpm);
 
-		ssl_ctx_add_crls(ctx2, crls);
+		ssl_ctx_add_crls(ctx2, crls, 0);
 
 		if (!args_ssl_call(ctx2, bio_err, cctx, ssl_args, no_ecdhe))
 			goto end;
diff --git a/apps/verify.c b/apps/verify.c
index 8f897cf..bcca114 100644
--- a/apps/verify.c
+++ b/apps/verify.c
@@ -88,6 +88,7 @@
 	X509_STORE *cert_ctx=NULL;
 	X509_LOOKUP *lookup=NULL;
 	X509_VERIFY_PARAM *vpm = NULL;
+	int crl_download = 0;
 #ifndef OPENSSL_NO_ENGINE
 	char *engine=NULL;
 #endif
@@ -145,6 +146,8 @@
 				if (argc-- < 1) goto end;
 				crlfile= *(++argv);
 				}
+			else if (strcmp(*argv,"-crl_download") == 0)
+				crl_download = 1;
 #ifndef OPENSSL_NO_ENGINE
 			else if (strcmp(*argv,"-engine") == 0)
 				{
@@ -222,6 +225,9 @@
 			goto end;
 		}
 
+	if (crl_download)
+		store_setup_crl_download(cert_ctx);
+
 	if (argc < 1) check(cert_ctx, NULL, untrusted, trusted, crls, e);
 	else
 		for (i=0; i<argc; i++)