Add option to allow in-band CRL loading in verify utility. Add function
load_crls and tidy up load_certs. Remove useless purpose variable from
verify utility: now done with args_verify.
diff --git a/CHANGES b/CHANGES
index 7c0664e..fc7c0ad 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,10 @@
 
  Changes between 0.9.8k and 1.0  [xx XXX xxxx]
 
+  *) Add load_crls() function to apps tidying load_certs() too. Add option
+     to verify utility to allow additional CRLs to be included.
+     [Steve Henson]
+
   *) Update OCSP request code to permit adding custom headers to the request:
      some responders need this.
      [Steve Henson]
diff --git a/apps/apps.c b/apps/apps.c
index 09d9df2..5dccea7 100644
--- a/apps/apps.c
+++ b/apps/apps.c
@@ -1095,76 +1095,120 @@
 	}
 #endif /* ndef OPENSSL_NO_RC4 */
 
-STACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
-	const char *pass, ENGINE *e, const char *cert_descrip)
+static int load_certs_crls(BIO *err, const char *file, int format,
+	const char *pass, ENGINE *e, const char *desc,
+	STACK_OF(X509) **pcerts, STACK_OF(X509_CRL) **pcrls)
 	{
-	BIO *certs;
 	int i;
-	STACK_OF(X509) *othercerts = NULL;
-	STACK_OF(X509_INFO) *allcerts = NULL;
+	BIO *bio;
+	STACK_OF(X509_INFO) *xis = NULL;
 	X509_INFO *xi;
 	PW_CB_DATA cb_data;
+	int rv = 0;
 
 	cb_data.password = pass;
 	cb_data.prompt_info = file;
 
-	if((certs = BIO_new(BIO_s_file())) == NULL)
+	if (format != FORMAT_PEM)
 		{
-		ERR_print_errors(err);
-		goto end;
+		BIO_printf(err,"bad input format specified for %s\n", desc);
+		return 0;
 		}
 
 	if (file == NULL)
-		BIO_set_fp(certs,stdin,BIO_NOCLOSE);
+		bio = BIO_new_fp(stdin,BIO_NOCLOSE);
 	else
+		bio = BIO_new_file(file, "r");
+
+	if (bio == NULL)
 		{
-		if (BIO_read_filename(certs,file) <= 0)
-			{
-			BIO_printf(err, "Error opening %s %s\n",
-				cert_descrip, file);
-			ERR_print_errors(err);
+		BIO_printf(err, "Error opening %s %s\n",
+				desc, file ? file : "stdin");
+		ERR_print_errors(err);
+		return 0;
+		}
+
+	xis = PEM_X509_INFO_read_bio(bio, NULL,
+				(pem_password_cb *)password_callback, &cb_data);
+
+	BIO_free(bio);
+
+	if (pcerts)
+		{
+		*pcerts = sk_X509_new_null();
+		if (!*pcerts)
 			goto end;
+		}
+
+	if (pcrls)
+		{
+		*pcrls = sk_X509_CRL_new_null();
+		if (!*pcrls)
+			goto end;
+		}
+
+	for(i = 0; i < sk_X509_INFO_num(xis); i++)
+		{
+		xi = sk_X509_INFO_value (xis, i);
+		if (xi->x509 && pcerts)
+			{
+			if (!sk_X509_push(*pcerts, xi->x509))
+				goto end;
+			xi->x509 = NULL;
+			}
+		if (xi->crl && pcrls)
+			{
+			if (!sk_X509_CRL_push(*pcrls, xi->crl))
+				goto end;
+			xi->crl = NULL;
 			}
 		}
 
-	if      (format == FORMAT_PEM)
+	if (pcerts && sk_X509_num(*pcerts) > 0)
+		rv = 1;
+
+	if (pcrls && sk_X509_CRL_num(*pcrls) > 0)
+		rv = 1;
+
+	end:
+
+	if (xis)
+		sk_X509_INFO_pop_free(xis, X509_INFO_free);
+
+	if (rv == 0)
 		{
-		othercerts = sk_X509_new_null();
-		if(!othercerts)
+		if (pcerts)
 			{
-			sk_X509_free(othercerts);
-			othercerts = NULL;
-			goto end;
+			sk_X509_pop_free(*pcerts, X509_free);
+			*pcerts = NULL;
 			}
-		allcerts = PEM_X509_INFO_read_bio(certs, NULL,
-				(pem_password_cb *)password_callback, &cb_data);
-		for(i = 0; i < sk_X509_INFO_num(allcerts); i++)
+		if (pcrls)
 			{
-			xi = sk_X509_INFO_value (allcerts, i);
-			if (xi->x509)
-				{
-				sk_X509_push(othercerts, xi->x509);
-				xi->x509 = NULL;
-				}
+			sk_X509_CRL_pop_free(*pcrls, X509_CRL_free);
+			*pcrls = NULL;
 			}
-		goto end;
-		}
-	else	{
-		BIO_printf(err,"bad input format specified for %s\n",
-			cert_descrip);
-		goto end;
-		}
-end:
-	if (othercerts == NULL)
-		{
-		BIO_printf(err,"unable to load certificates\n");
+		BIO_printf(err,"unable to load %s\n",
+				pcerts ? "certificates" : "CRLs");
 		ERR_print_errors(err);
 		}
-	if (allcerts) sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
-	if (certs != NULL) BIO_free(certs);
-	return(othercerts);
+	return rv;
 	}
 
+STACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
+	const char *pass, ENGINE *e, const char *desc)
+	{
+	STACK_OF(X509) *certs;
+	load_certs_crls(err, file, format, pass, e, desc, &certs, NULL);
+	return certs;
+	}	
+
+STACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format,
+	const char *pass, ENGINE *e, const char *desc)
+	{
+	STACK_OF(X509_CRL) *crls;
+	load_certs_crls(err, file, format, pass, e, desc, NULL, &crls);
+	return crls;
+	}	
 
 #define X509V3_EXT_UNKNOWN_MASK		(0xfL << 16)
 /* Return error for unknown extensions */
diff --git a/apps/apps.h b/apps/apps.h
index 35a0266..596a39a 100644
--- a/apps/apps.h
+++ b/apps/apps.h
@@ -251,6 +251,8 @@
 	const char *pass, ENGINE *e, const char *key_descrip);
 STACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
 	const char *pass, ENGINE *e, const char *cert_descrip);
+STACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format,
+	const char *pass, ENGINE *e, const char *cert_descrip);
 X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath);
 #ifndef OPENSSL_NO_ENGINE
 ENGINE *setup_engine(BIO *err, const char *engine, int debug);
diff --git a/apps/verify.c b/apps/verify.c
index 96fcfb4..c0be253 100644
--- a/apps/verify.c
+++ b/apps/verify.c
@@ -70,8 +70,9 @@
 #define PROG	verify_main
 
 static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx);
-static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, int purpose, ENGINE *e);
-static STACK_OF(X509) *load_untrusted(char *file);
+static int check(X509_STORE *ctx, char *file,
+		STACK_OF(X509) *uchain, STACK_OF(X509) *tchain,
+		STACK_OF(X509_CRL) *crls, ENGINE *e);
 static int v_verbose=0, vflags = 0;
 
 int MAIN(int, char **);
@@ -80,10 +81,10 @@
 	{
 	ENGINE *e = NULL;
 	int i,ret=1, badarg = 0;
-	int purpose = -1;
 	char *CApath=NULL,*CAfile=NULL;
-	char *untfile = NULL, *trustfile = NULL;
+	char *untfile = NULL, *trustfile = NULL, *crlfile = NULL;
 	STACK_OF(X509) *untrusted = NULL, *trusted = NULL;
+	STACK_OF(X509_CRL) *crls = NULL;
 	X509_STORE *cert_ctx=NULL;
 	X509_LOOKUP *lookup=NULL;
 	X509_VERIFY_PARAM *vpm = NULL;
@@ -139,6 +140,11 @@
 				if (argc-- < 1) goto end;
 				trustfile= *(++argv);
 				}
+			else if (strcmp(*argv,"-CRLfile") == 0)
+				{
+				if (argc-- < 1) goto end;
+				crlfile= *(++argv);
+				}
 #ifndef OPENSSL_NO_ENGINE
 			else if (strcmp(*argv,"-engine") == 0)
 				{
@@ -192,26 +198,34 @@
 
 	ERR_clear_error();
 
-	if(untfile) {
-		if(!(untrusted = load_untrusted(untfile))) {
-			BIO_printf(bio_err, "Error loading untrusted file %s\n", untfile);
-			ERR_print_errors(bio_err);
+	if(untfile)
+		{
+		untrusted = load_certs(bio_err, untfile, FORMAT_PEM,
+					NULL, e, "untrusted certificates");
+		if(!untrusted)
 			goto end;
 		}
-	}
 
-	if(trustfile) {
-		if(!(trusted = load_untrusted(trustfile))) {
-			BIO_printf(bio_err, "Error loading untrusted file %s\n", trustfile);
-			ERR_print_errors(bio_err);
+	if(trustfile)
+		{
+		trusted = load_certs(bio_err, trustfile, FORMAT_PEM,
+					NULL, e, "trusted certificates");
+		if(!trusted)
 			goto end;
 		}
-	}
 
-	if (argc < 1) check(cert_ctx, NULL, untrusted, trusted, purpose, e);
+	if(crlfile)
+		{
+		crls = load_crls(bio_err, crlfile, FORMAT_PEM,
+					NULL, e, "other CRLs");
+		if(!crls)
+			goto end;
+		}
+
+	if (argc < 1) check(cert_ctx, NULL, untrusted, trusted, crls, e);
 	else
 		for (i=0; i<argc; i++)
-			check(cert_ctx,argv[i], untrusted, trusted, purpose, e);
+			check(cert_ctx,argv[i], untrusted, trusted, crls, e);
 	ret=0;
 end:
 	if (ret == 1) {
@@ -232,11 +246,14 @@
 	if (cert_ctx != NULL) X509_STORE_free(cert_ctx);
 	sk_X509_pop_free(untrusted, X509_free);
 	sk_X509_pop_free(trusted, X509_free);
+	sk_X509_CRL_pop_free(crls, X509_CRL_free);
 	apps_shutdown();
 	OPENSSL_EXIT(ret);
 	}
 
-static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, int purpose, ENGINE *e)
+static int check(X509_STORE *ctx, char *file,
+		STACK_OF(X509) *uchain, STACK_OF(X509) *tchain,
+		STACK_OF(X509_CRL) *crls, ENGINE *e)
 	{
 	X509 *x=NULL;
 	int i=0,ret=0;
@@ -260,7 +277,8 @@
 		goto end;
 		}
 	if(tchain) X509_STORE_CTX_trusted_stack(csc, tchain);
-	if(purpose >= 0) X509_STORE_CTX_set_purpose(csc, purpose);
+	if (crls)
+		X509_STORE_CTX_set0_crls(csc, crls);
 	i=X509_verify_cert(csc);
 	X509_STORE_CTX_free(csc);
 
@@ -278,52 +296,6 @@
 	return(ret);
 	}
 
-static STACK_OF(X509) *load_untrusted(char *certfile)
-{
-	STACK_OF(X509_INFO) *sk=NULL;
-	STACK_OF(X509) *stack=NULL, *ret=NULL;
-	BIO *in=NULL;
-	X509_INFO *xi;
-
-	if(!(stack = sk_X509_new_null())) {
-		BIO_printf(bio_err,"memory allocation failure\n");
-		goto end;
-	}
-
-	if(!(in=BIO_new_file(certfile, "r"))) {
-		BIO_printf(bio_err,"error opening the file, %s\n",certfile);
-		goto end;
-	}
-
-	/* This loads from a file, a stack of x509/crl/pkey sets */
-	if(!(sk=PEM_X509_INFO_read_bio(in,NULL,NULL,NULL))) {
-		BIO_printf(bio_err,"error reading the file, %s\n",certfile);
-		goto end;
-	}
-
-	/* scan over it and pull out the certs */
-	while (sk_X509_INFO_num(sk))
-		{
-		xi=sk_X509_INFO_shift(sk);
-		if (xi->x509 != NULL)
-			{
-			sk_X509_push(stack,xi->x509);
-			xi->x509=NULL;
-			}
-		X509_INFO_free(xi);
-		}
-	if(!sk_X509_num(stack)) {
-		BIO_printf(bio_err,"no certificates in file, %s\n",certfile);
-		sk_X509_free(stack);
-		goto end;
-	}
-	ret=stack;
-end:
-	BIO_free(in);
-	sk_X509_INFO_free(sk);
-	return(ret);
-	}
-
 static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx)
 	{
 	int cert_error = X509_STORE_CTX_get_error(ctx);