From 0090a686c0620e5f7d72aef2e74f4a0e01c53e3e Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Thu, 6 Dec 2012 18:43:40 +0000 Subject: [PATCH] Add code to download CRLs based on CRLDP extension. Just a sample, real world applications would have to be cleverer. --- CHANGES | 4 +++ apps/apps.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++- apps/apps.h | 4 ++- apps/s_apps.h | 4 +-- apps/s_cb.c | 24 +++++++-------- apps/s_client.c | 8 +++-- apps/s_server.c | 6 ++-- apps/verify.c | 6 ++++ 8 files changed, 113 insertions(+), 22 deletions(-) diff --git a/CHANGES b/CHANGES index c4a7cb4fd1..89dfaf0885 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,10 @@ Changes between 1.0.x and 1.1.0 [xx XXX xxxx] + *) New option -crl_download in several openssl utilities to download CRLs + from CRLDP extension in certificates. + [Steve Henson] + *) Integrate hostname, email address and IP address checking with certificate verification. New verify options supporting checking in opensl utility. [Steve Henson] diff --git a/apps/apps.c b/apps/apps.c index adf78665b0..7f057fb4b2 100644 --- a/apps/apps.c +++ b/apps/apps.c @@ -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; @@ -2974,6 +2974,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, >ype); + 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 e9d21d545a..d9debd128a 100644 --- a/apps/apps.h +++ b/apps/apps.h @@ -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 diff --git a/apps/s_apps.h b/apps/s_apps.h index f6e85ee562..83526eca30 100644 --- a/apps/s_apps.h +++ b/apps/s_apps.h @@ -197,9 +197,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 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 8ba8a041a6..96bc5dba5a 100644 --- a/apps/s_cb.c +++ b/apps/s_cb.c @@ -1660,32 +1660,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; @@ -1696,6 +1692,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) { diff --git a/apps/s_client.c b/apps/s_client.c index 27c1696bf3..1646556547 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -635,6 +635,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_client_method(); @@ -711,6 +712,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; else if (strcmp(*argv,"-sess_out") == 0) { if (--argc < 1) goto bad; @@ -1192,7 +1195,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); @@ -1254,7 +1258,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, NULL, build_chain)) goto end; diff --git a/apps/s_server.c b/apps/s_server.c index 2de8565367..dc0cc36fb0 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -1715,12 +1715,12 @@ 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)) 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 @@ 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)) goto end; diff --git a/apps/verify.c b/apps/verify.c index 8f897cf485..bcca114efe 100644 --- a/apps/verify.c +++ b/apps/verify.c @@ -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) { @@ -222,6 +225,9 @@ int MAIN(int argc, char **argv) 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