Add code to download CRLs based on CRLDP extension.
authorDr. Stephen Henson <steve@openssl.org>
Thu, 6 Dec 2012 18:43:40 +0000 (18:43 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 18 Jan 2013 15:38:13 +0000 (15:38 +0000)
Just a sample, real world applications would have to be cleverer.

CHANGES
apps/apps.c
apps/apps.h
apps/s_apps.h
apps/s_cb.c
apps/s_client.c
apps/s_server.c
apps/verify.c

diff --git a/CHANGES b/CHANGES
index 918fec366c9d8b9fd384f7b439f1652d2cceefc1..7d332674dbe1defbf55c3e302d03dfb523f4640c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,10 @@
 
  Changes between 1.0.1 and 1.0.2 [xx XXX xxxx]
 
+  *) New option -crl_download in several openssl utilities to download CRLs
+     from CRLDP extension in certificates.
+     [Steve Henson]
+
   *) New options -CRL and -CRLform for s_client and s_server for CRLs.
      [Steve Henson]
 
index 3c6efbc7cb338138bc9a2cf95b4e86c536d38a7f..ae5b00f2c25b56b667856506cd02984f2afda2c8 100644 (file)
@@ -929,7 +929,7 @@ end:
        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;
@@ -2963,6 +2963,83 @@ void print_cert_checks(BIO *bio, X509 *x,
                }
        }
 
+/* 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
  */
index 8a38fe70aad6caf490ee1ea0672615bc2b8112bb..6a71b8323a1a9b2a39ebd39a773c59597dfabea5 100644 (file)
@@ -245,7 +245,7 @@ int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2);
 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 @@ void print_cert_checks(BIO *bio, X509 *x,
                                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
index 92bb4949f950b9682a0c52108fb9c1ffcb914a85..0a150b791e76e1a58590ad024fe22834b6d2e440 100644 (file)
@@ -196,9 +196,9 @@ int args_ssl(char ***pargs, int *pargc, SSL_CONF_CTX *cctx,
                        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 no_jpake);
-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
index 710c99d076e382c76961a55c0cfb33706a75e0b3..865aa383e84801ecd84cff458ca003d930ac1367 100644 (file)
@@ -1603,32 +1603,28 @@ static int add_crls_store(X509_STORE *st, STACK_OF(X509_CRL) *crls)
        {
        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;
@@ -1639,6 +1635,8 @@ int ssl_load_stores(SSL_CTX *ctx,
                        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)
                {
index edd06fc02bd8dc330c4913cc1d40bb2487ec4f10..8fe2c56f2a828e731912a83593496c0f321708fa 100644 (file)
@@ -638,6 +638,7 @@ static char *jpake_secret = NULL;
 
        char *crl_file = NULL;
        int crl_format = FORMAT_PEM;
+       int crl_download = 0;
        STACK_OF(X509_CRL) *crls = NULL;
 
        meth=SSLv23_client_method();
@@ -714,6 +715,8 @@ static char *jpake_secret = NULL;
                        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;
@@ -1193,7 +1196,8 @@ bad:
                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);
@@ -1255,7 +1259,7 @@ bad:
                /* goto end; */
                }
 
-       ssl_ctx_add_crls(ctx, crls);
+       ssl_ctx_add_crls(ctx, crls, crl_download);
        if (!set_cert_key_stuff(ctx,cert,key,chain,build_chain))
                goto end;
 
index 5a7c24fe92bf915cd5e7fdf8742fdbdb8df4bddb..a90a506258915e375b9644a65fabdd35555ee56c 100644 (file)
@@ -987,6 +987,7 @@ int MAIN(int argc, char *argv[])
 
        char *crl_file = NULL;
        int crl_format = FORMAT_PEM;
+       int crl_download = 0;
        STACK_OF(X509_CRL) *crls = NULL;
 
        meth=SSLv23_server_method();
@@ -1059,6 +1060,8 @@ int MAIN(int argc, char *argv[])
                        if (--argc < 1) goto bad;
                        crl_file= *(++argv);
                        }
+               else if (strcmp(*argv,"-crl_download") == 0)
+                       crl_download = 1;
 #ifndef OPENSSL_NO_TLSEXT
                else if (strcmp(*argv,"-authz") == 0)
                        {
@@ -1674,12 +1677,13 @@ bad:
        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, no_jpake))
                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);
@@ -1740,7 +1744,7 @@ bad:
                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, no_jpake))
                        goto end;
index 893670ff41321317e7a057e0a8c3fd64cb7d048a..18fba46545ec78f07e7a27e1c202f12f9cd1ff34 100644 (file)
@@ -88,6 +88,7 @@ int MAIN(int argc, char **argv)
        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 @@ int MAIN(int argc, char **argv)
                                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)
                                {
@@ -223,6 +226,9 @@ int MAIN(int argc, char **argv)
                }
 
        ret = 0;
+
+       if (crl_download)
+               store_setup_crl_download(cert_ctx);
        if (argc < 1)
                { 
                if (1 != check(cert_ctx, NULL, untrusted, trusted, crls, e))