/* * openssl crl -in ca.crl -text */ void show_crl(char * ca_name) { X509_CRL * crl ; X509_REVOKED * rev ; int i, total ; STACK_OF(X509_REVOKED) * rev_list ; BIO * out ; if ((crl = load_crl(ca_name))==NULL) { printf("No CRL found\n"); return ; } rev_list = X509_CRL_get_REVOKED(crl); total = sk_X509_REVOKED_num(rev_list); out = BIO_new(BIO_s_file()); out = BIO_new_fp(stdout, BIO_NOCLOSE); BIO_printf(out, "-- Revoked certificates found in CRL\n"); for (i=0 ; i<total ; i++) { rev=sk_X509_REVOKED_value(rev_list, i); BIO_printf(out, "serial: "); i2a_ASN1_INTEGER(out, rev->serialNumber); BIO_printf(out, "\n date: "); ASN1_TIME_print(out, rev->revocationDate); BIO_printf(out, "\n\n"); } X509_CRL_free(crl); BIO_free_all(out); return ; }
int hx509_revoke_add_crl(hx509_context context, hx509_revoke_ctx ctx, const char *path) { void *data; size_t i; int ret; if (strncmp(path, "FILE:", 5) != 0) { hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, "unsupport type in %s", path); return HX509_UNSUPPORTED_OPERATION; } path += 5; for (i = 0; i < ctx->crls.len; i++) { if (strcmp(ctx->crls.val[i].path, path) == 0) return 0; } data = realloc(ctx->crls.val, (ctx->crls.len + 1) * sizeof(ctx->crls.val[0])); if (data == NULL) { hx509_clear_error_string(context); return ENOMEM; } ctx->crls.val = data; memset(&ctx->crls.val[ctx->crls.len], 0, sizeof(ctx->crls.val[0])); ctx->crls.val[ctx->crls.len].path = strdup(path); if (ctx->crls.val[ctx->crls.len].path == NULL) { hx509_clear_error_string(context); return ENOMEM; } ret = load_crl(path, &ctx->crls.val[ctx->crls.len].last_modfied, &ctx->crls.val[ctx->crls.len].crl); if (ret) { free(ctx->crls.val[ctx->crls.len].path); return ret; } ctx->crls.len++; return ret; }
int MAIN(int argc, char **argv) { X509_CRL *x=NULL; char *CAfile = NULL, *CApath = NULL; int ret=1,i,num,badops=0; BIO *out=NULL; int informat,outformat; char *infile=NULL,*outfile=NULL; int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0; int fingerprint = 0; char **pp,buf[256]; X509_STORE *store = NULL; X509_STORE_CTX ctx; X509_LOOKUP *lookup = NULL; X509_OBJECT xobj; EVP_PKEY *pkey; int do_ver = 0; const EVP_MD *md_alg,*digest=EVP_md5(); apps_startup(); if (bio_err == NULL) if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); if (bio_out == NULL) if ((bio_out=BIO_new(BIO_s_file())) != NULL) { BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); #ifdef VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); bio_out = BIO_push(tmpbio, bio_out); } #endif } informat=FORMAT_PEM; outformat=FORMAT_PEM; argc--; argv++; num=0; while (argc >= 1) { #ifdef undef if (strcmp(*argv,"-p") == 0) { if (--argc < 1) goto bad; if (!args_from_file(++argv,Nargc,Nargv)) { goto end; }*/ } #endif if (strcmp(*argv,"-inform") == 0) { if (--argc < 1) goto bad; informat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-outform") == 0) { if (--argc < 1) goto bad; outformat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-in") == 0) { if (--argc < 1) goto bad; infile= *(++argv); } else if (strcmp(*argv,"-out") == 0) { if (--argc < 1) goto bad; outfile= *(++argv); } else if (strcmp(*argv,"-CApath") == 0) { if (--argc < 1) goto bad; CApath = *(++argv); do_ver = 1; } else if (strcmp(*argv,"-CAfile") == 0) { if (--argc < 1) goto bad; CAfile = *(++argv); do_ver = 1; } else if (strcmp(*argv,"-verify") == 0) do_ver = 1; else if (strcmp(*argv,"-text") == 0) text = 1; else if (strcmp(*argv,"-hash") == 0) hash= ++num; else if (strcmp(*argv,"-issuer") == 0) issuer= ++num; else if (strcmp(*argv,"-lastupdate") == 0) lastupdate= ++num; else if (strcmp(*argv,"-nextupdate") == 0) nextupdate= ++num; else if (strcmp(*argv,"-noout") == 0) noout= ++num; else if (strcmp(*argv,"-fingerprint") == 0) fingerprint= ++num; else if ((md_alg=EVP_get_digestbyname(*argv + 1))) { /* ok */ digest=md_alg; } else { BIO_printf(bio_err,"unknown option %s\n",*argv); badops=1; break; } argc--; argv++; } if (badops) { bad: for (pp=crl_usage; (*pp != NULL); pp++) BIO_printf(bio_err,*pp); goto end; } ERR_load_crypto_strings(); x=load_crl(infile,informat); if (x == NULL) { goto end; } if(do_ver) { store = X509_STORE_new(); lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file()); if (lookup == NULL) goto end; if (!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT); lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir()); if (lookup == NULL) goto end; if (!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); ERR_clear_error(); X509_STORE_CTX_init(&ctx, store, NULL, NULL); i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, X509_CRL_get_issuer(x), &xobj); if(i <= 0) { BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); goto end; } pkey = X509_get_pubkey(xobj.data.x509); X509_OBJECT_free_contents(&xobj); if(!pkey) { BIO_printf(bio_err, "Error getting CRL issuer public key\n"); goto end; } i = X509_CRL_verify(x, pkey); EVP_PKEY_free(pkey); if(i < 0) goto end; if(i == 0) BIO_printf(bio_err, "verify failure\n"); else BIO_printf(bio_err, "verify OK\n"); } if (num) { for (i=1; i<=num; i++) { if (issuer == i) { X509_NAME_oneline(X509_CRL_get_issuer(x), buf,256); BIO_printf(bio_out,"issuer= %s\n",buf); } if (hash == i) { BIO_printf(bio_out,"%08lx\n", X509_NAME_hash(X509_CRL_get_issuer(x))); } if (lastupdate == i) { BIO_printf(bio_out,"lastUpdate="); ASN1_TIME_print(bio_out, X509_CRL_get_lastUpdate(x)); BIO_printf(bio_out,"\n"); } if (nextupdate == i) { BIO_printf(bio_out,"nextUpdate="); if (X509_CRL_get_nextUpdate(x)) ASN1_TIME_print(bio_out, X509_CRL_get_nextUpdate(x)); else BIO_printf(bio_out,"NONE"); BIO_printf(bio_out,"\n"); } if (fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; if (!X509_CRL_digest(x,digest,md,&n)) { BIO_printf(bio_err,"out of memory\n"); goto end; } BIO_printf(bio_out,"%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(digest))); for (j=0; j<(int)n; j++) { BIO_printf(bio_out,"%02X%c",md[j], (j+1 == (int)n) ?'\n':':'); } } } } out=BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (outfile == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); #ifdef VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outfile) <= 0) { perror(outfile); goto end; } } if (text) X509_CRL_print(out, x); if (noout) goto end; if (outformat == FORMAT_ASN1) i=(int)i2d_X509_CRL_bio(out,x); else if (outformat == FORMAT_PEM) i=PEM_write_bio_X509_CRL(out,x); else { BIO_printf(bio_err,"bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err,"unable to write CRL\n"); goto end; } ret=0; end: BIO_free_all(out); BIO_free_all(bio_out); bio_out=NULL; X509_CRL_free(x); if(store) { X509_STORE_CTX_cleanup(&ctx); X509_STORE_free(store); } EXIT(ret); }
int crl_main(int argc, char **argv) { X509_CRL *x = NULL; BIO *out = NULL; X509_STORE *store = NULL; X509_STORE_CTX *ctx = NULL; X509_LOOKUP *lookup = NULL; X509_OBJECT *xobj = NULL; EVP_PKEY *pkey; const EVP_MD *digest = EVP_sha1(); unsigned long nmflag = 0; char nmflag_set = 0; char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL; const char *CAfile = NULL, *CApath = NULL, *prog; OPTION_CHOICE o; int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = 0; int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; int ret = 1, num = 0, badsig = 0, fingerprint = 0, crlnumber = 0; int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0; int i; #ifndef OPENSSL_NO_MD5 int hash_old = 0; #endif prog = opt_init(argc, argv, crl_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(crl_options); ret = 0; goto end; case OPT_INFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) goto opthelp; break; case OPT_IN: infile = opt_arg(); break; case OPT_OUTFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) goto opthelp; break; case OPT_OUT: outfile = opt_arg(); break; case OPT_KEYFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat)) goto opthelp; break; case OPT_KEY: keyfile = opt_arg(); break; case OPT_GENDELTA: crldiff = opt_arg(); break; case OPT_CAPATH: CApath = opt_arg(); do_ver = 1; break; case OPT_CAFILE: CAfile = opt_arg(); do_ver = 1; break; case OPT_NOCAPATH: noCApath = 1; break; case OPT_NOCAFILE: noCAfile = 1; break; case OPT_HASH_OLD: #ifndef OPENSSL_NO_MD5 hash_old = ++num; #endif break; case OPT_VERIFY: do_ver = 1; break; case OPT_TEXT: text = 1; break; case OPT_HASH: hash = ++num; break; case OPT_ISSUER: issuer = ++num; break; case OPT_LASTUPDATE: lastupdate = ++num; break; case OPT_NEXTUPDATE: nextupdate = ++num; break; case OPT_NOOUT: noout = ++num; break; case OPT_FINGERPRINT: fingerprint = ++num; break; case OPT_CRLNUMBER: crlnumber = ++num; break; case OPT_BADSIG: badsig = 1; break; case OPT_NAMEOPT: nmflag_set = 1; if (!set_name_ex(&nmflag, opt_arg())) goto opthelp; break; case OPT_MD: if (!opt_md(opt_unknown(), &digest)) goto opthelp; } } argc = opt_num_rest(); if (argc != 0) goto opthelp; if (!nmflag_set) nmflag = XN_FLAG_ONELINE; x = load_crl(infile, informat); if (x == NULL) goto end; if (do_ver) { if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) goto end; lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); if (lookup == NULL) goto end; ctx = X509_STORE_CTX_new(); if (ctx == NULL || !X509_STORE_CTX_init(ctx, store, NULL, NULL)) { BIO_printf(bio_err, "Error initialising X509 store\n"); goto end; } xobj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, X509_CRL_get_issuer(x)); if (xobj == NULL) { BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); goto end; } pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj)); X509_OBJECT_free(xobj); if (!pkey) { BIO_printf(bio_err, "Error getting CRL issuer public key\n"); goto end; } i = X509_CRL_verify(x, pkey); EVP_PKEY_free(pkey); if (i < 0) goto end; if (i == 0) BIO_printf(bio_err, "verify failure\n"); else BIO_printf(bio_err, "verify OK\n"); } if (crldiff) { X509_CRL *newcrl, *delta; if (!keyfile) { BIO_puts(bio_err, "Missing CRL signing key\n"); goto end; } newcrl = load_crl(crldiff, informat); if (!newcrl) goto end; pkey = load_key(keyfile, keyformat, 0, NULL, NULL, "CRL signing key"); if (!pkey) { X509_CRL_free(newcrl); goto end; } delta = X509_CRL_diff(x, newcrl, pkey, digest, 0); X509_CRL_free(newcrl); EVP_PKEY_free(pkey); if (delta) { X509_CRL_free(x); x = delta; } else { BIO_puts(bio_err, "Error creating delta CRL\n"); goto end; } } if (badsig) { const ASN1_BIT_STRING *sig; X509_CRL_get0_signature(x, &sig, NULL); corrupt_signature(sig); } if (num) { for (i = 1; i <= num; i++) { if (issuer == i) { print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); } if (crlnumber == i) { ASN1_INTEGER *crlnum; crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL); BIO_printf(bio_out, "crlNumber="); if (crlnum) { i2a_ASN1_INTEGER(bio_out, crlnum); ASN1_INTEGER_free(crlnum); } else BIO_puts(bio_out, "<NONE>"); BIO_printf(bio_out, "\n"); } if (hash == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash(X509_CRL_get_issuer(x))); } #ifndef OPENSSL_NO_MD5 if (hash_old == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash_old(X509_CRL_get_issuer(x))); } #endif if (lastupdate == i) { BIO_printf(bio_out, "lastUpdate="); ASN1_TIME_print(bio_out, X509_CRL_get0_lastUpdate(x)); BIO_printf(bio_out, "\n"); } if (nextupdate == i) { BIO_printf(bio_out, "nextUpdate="); if (X509_CRL_get0_nextUpdate(x)) ASN1_TIME_print(bio_out, X509_CRL_get0_nextUpdate(x)); else BIO_printf(bio_out, "NONE"); BIO_printf(bio_out, "\n"); } if (fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; if (!X509_CRL_digest(x, digest, md, &n)) { BIO_printf(bio_err, "out of memory\n"); goto end; } BIO_printf(bio_out, "%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(digest))); for (j = 0; j < (int)n; j++) { BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); } } } } out = bio_open_default(outfile, 'w', outformat); if (out == NULL) goto end; if (text) X509_CRL_print(out, x); if (noout) { ret = 0; goto end; } if (outformat == FORMAT_ASN1) i = (int)i2d_X509_CRL_bio(out, x); else i = PEM_write_bio_X509_CRL(out, x); if (!i) { BIO_printf(bio_err, "unable to write CRL\n"); goto end; } ret = 0; end: if (ret != 0) ERR_print_errors(bio_err); BIO_free_all(out); X509_CRL_free(x); X509_STORE_CTX_free(ctx); X509_STORE_free(store); return (ret); }
int MAIN(int argc, char **argv) { unsigned long nmflag = 0; X509_CRL *x = NULL; char *CAfile = NULL, *CApath = NULL; int ret = 1, i, num, badops = 0, badsig = 0; BIO *out = NULL; int informat, outformat, keyformat; char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL; int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = 0, text = 0; #ifndef OPENSSL_NO_MD5 int hash_old = 0; #endif int fingerprint = 0, crlnumber = 0; const char **pp; X509_STORE *store = NULL; X509_STORE_CTX ctx; X509_LOOKUP *lookup = NULL; X509_OBJECT xobj; EVP_PKEY *pkey; int do_ver = 0; const EVP_MD *md_alg, *digest = EVP_sha1(); apps_startup(); if (bio_err == NULL) if ((bio_err = BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); if (!load_config(bio_err, NULL)) goto end; if (bio_out == NULL) if ((bio_out = BIO_new(BIO_s_file())) != NULL) { BIO_set_fp(bio_out, stdout, BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); bio_out = BIO_push(tmpbio, bio_out); } #endif } informat = FORMAT_PEM; outformat = FORMAT_PEM; keyformat = FORMAT_PEM; argc--; argv++; num = 0; while (argc >= 1) { #ifdef undef if (sgx_strcmp(*argv, "-p") == 0) { if (--argc < 1) goto bad; if (!args_from_file(++argv, Nargc, Nargv)) { goto end; } */} #endif if (sgx_strcmp(*argv, "-inform") == 0) { if (--argc < 1) goto bad; informat = str2fmt(*(++argv)); } else if (sgx_strcmp(*argv, "-outform") == 0) { if (--argc < 1) goto bad; outformat = str2fmt(*(++argv)); } else if (sgx_strcmp(*argv, "-in") == 0) { if (--argc < 1) goto bad; infile = *(++argv); } else if (sgx_strcmp(*argv, "-gendelta") == 0) { if (--argc < 1) goto bad; crldiff = *(++argv); } else if (sgx_strcmp(*argv, "-key") == 0) { if (--argc < 1) goto bad; keyfile = *(++argv); } else if (sgx_strcmp(*argv, "-keyform") == 0) { if (--argc < 1) goto bad; keyformat = str2fmt(*(++argv)); } else if (sgx_strcmp(*argv, "-out") == 0) { if (--argc < 1) goto bad; outfile = *(++argv); } else if (sgx_strcmp(*argv, "-CApath") == 0) { if (--argc < 1) goto bad; CApath = *(++argv); do_ver = 1; } else if (sgx_strcmp(*argv, "-CAfile") == 0) { if (--argc < 1) goto bad; CAfile = *(++argv); do_ver = 1; } else if (sgx_strcmp(*argv, "-verify") == 0) do_ver = 1; else if (sgx_strcmp(*argv, "-text") == 0) text = 1; else if (sgx_strcmp(*argv, "-hash") == 0) hash = ++num; #ifndef OPENSSL_NO_MD5 else if (sgx_strcmp(*argv, "-hash_old") == 0) hash_old = ++num; #endif else if (sgx_strcmp(*argv, "-nameopt") == 0) { if (--argc < 1) goto bad; if (!set_name_ex(&nmflag, *(++argv))) goto bad; } else if (sgx_strcmp(*argv, "-issuer") == 0) issuer = ++num; else if (sgx_strcmp(*argv, "-lastupdate") == 0) lastupdate = ++num; else if (sgx_strcmp(*argv, "-nextupdate") == 0) nextupdate = ++num; else if (sgx_strcmp(*argv, "-noout") == 0) noout = ++num; else if (sgx_strcmp(*argv, "-fingerprint") == 0) fingerprint = ++num; else if (sgx_strcmp(*argv, "-crlnumber") == 0) crlnumber = ++num; else if (sgx_strcmp(*argv, "-badsig") == 0) badsig = 1; else if ((md_alg = EVP_get_digestbyname(*argv + 1))) { /* ok */ digest = md_alg; } else { BIO_printf(bio_err, "unknown option %s\n", *argv); badops = 1; break; } argc--; argv++; } if (badops) { bad: for (pp = crl_usage; (*pp != NULL); pp++) BIO_printf(bio_err, "%s", *pp); goto end; } ERR_load_crypto_strings(); x = load_crl(infile, informat); if (x == NULL) { goto end; } if (do_ver) { store = X509_STORE_new(); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); if (lookup == NULL) goto end; if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); if (lookup == NULL) goto end; if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); ERR_clear_error(); if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) { BIO_printf(bio_err, "Error initialising X509 store\n"); goto end; } i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, X509_CRL_get_issuer(x), &xobj); if (i <= 0) { BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); goto end; } pkey = X509_get_pubkey(xobj.data.x509); X509_OBJECT_free_contents(&xobj); if (!pkey) { BIO_printf(bio_err, "Error getting CRL issuer public key\n"); goto end; } i = X509_CRL_verify(x, pkey); EVP_PKEY_free(pkey); if (i < 0) goto end; if (i == 0) BIO_printf(bio_err, "verify failure\n"); else BIO_printf(bio_err, "verify OK\n"); } if (crldiff) { X509_CRL *newcrl, *delta; if (!keyfile) { BIO_puts(bio_err, "Missing CRL signing key\n"); goto end; } newcrl = load_crl(crldiff, informat); if (!newcrl) goto end; pkey = load_key(bio_err, keyfile, keyformat, 0, NULL, NULL, "CRL signing key"); if (!pkey) { X509_CRL_free(newcrl); goto end; } delta = X509_CRL_diff(x, newcrl, pkey, digest, 0); X509_CRL_free(newcrl); EVP_PKEY_free(pkey); if (delta) { X509_CRL_free(x); x = delta; } else { BIO_puts(bio_err, "Error creating delta CRL\n"); goto end; } } if (num) { for (i = 1; i <= num; i++) { if (issuer == i) { print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); } if (crlnumber == i) { ASN1_INTEGER *crlnum; crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL); BIO_printf(bio_out, "crlNumber="); if (crlnum) { i2a_ASN1_INTEGER(bio_out, crlnum); ASN1_INTEGER_free(crlnum); } else BIO_puts(bio_out, "<NONE>"); BIO_printf(bio_out, "\n"); } if (hash == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash(X509_CRL_get_issuer(x))); } #ifndef OPENSSL_NO_MD5 if (hash_old == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash_old(X509_CRL_get_issuer(x))); } #endif if (lastupdate == i) { BIO_printf(bio_out, "lastUpdate="); ASN1_TIME_print(bio_out, X509_CRL_get_lastUpdate(x)); BIO_printf(bio_out, "\n"); } if (nextupdate == i) { BIO_printf(bio_out, "nextUpdate="); if (X509_CRL_get_nextUpdate(x)) ASN1_TIME_print(bio_out, X509_CRL_get_nextUpdate(x)); else BIO_printf(bio_out, "NONE"); BIO_printf(bio_out, "\n"); } if (fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; if (!X509_CRL_digest(x, digest, md, &n)) { BIO_printf(bio_err, "out of memory\n"); goto end; } BIO_printf(bio_out, "%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(digest))); for (j = 0; j < (int)n; j++) { BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); } } } } out = BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (outfile == NULL) { BIO_set_fp(out, stdout, BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out, outfile) <= 0) { perror(outfile); goto end; } } if (text) X509_CRL_print(out, x); if (noout) { ret = 0; goto end; } if (badsig) x->signature->data[x->signature->length - 1] ^= 0x1; if (outformat == FORMAT_ASN1) i = (int)i2d_X509_CRL_bio(out, x); else if (outformat == FORMAT_PEM) i = PEM_write_bio_X509_CRL(out, x); else { BIO_printf(bio_err, "bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err, "unable to write CRL\n"); goto end; } ret = 0; end: if (ret != 0) ERR_print_errors(bio_err); BIO_free_all(out); BIO_free_all(bio_out); bio_out = NULL; X509_CRL_free(x); if (store) { X509_STORE_CTX_cleanup(&ctx); X509_STORE_free(store); } apps_shutdown(); OPENSSL_EXIT(ret); }
int crl_main(int argc, char **argv) { unsigned long nmflag = 0; X509_CRL *x = NULL; int ret = 1, i; BIO *out = NULL; X509_STORE *store = NULL; X509_STORE_CTX ctx; X509_LOOKUP *lookup = NULL; X509_OBJECT xobj; EVP_PKEY *pkey; const EVP_MD *digest; char *digest_name = NULL; if (single_execution) { if (pledge("stdio cpath wpath rpath", NULL) == -1) { perror("pledge"); exit(1); } } if (bio_out == NULL) { if ((bio_out = BIO_new(BIO_s_file())) != NULL) { BIO_set_fp(bio_out, stdout, BIO_NOCLOSE); } } digest = EVP_sha256(); memset(&crl_config, 0, sizeof(crl_config)); crl_config.informat = FORMAT_PEM; crl_config.outformat = FORMAT_PEM; if (options_parse(argc, argv, crl_options, &digest_name, NULL) != 0) { crl_usage(); goto end; } if (crl_config.cafile != NULL || crl_config.capath != NULL) crl_config.verify = 1; if (crl_config.nameopt != NULL) { if (set_name_ex(&nmflag, crl_config.nameopt) != 1) { fprintf(stderr, "Invalid -nameopt argument '%s'\n", crl_config.nameopt); goto end; } } if (digest_name != NULL) { if ((digest = EVP_get_digestbyname(digest_name)) == NULL) { fprintf(stderr, "Unknown message digest algorithm '%s'\n", digest_name); goto end; } } x = load_crl(crl_config.infile, crl_config.informat); if (x == NULL) goto end; if (crl_config.verify) { store = X509_STORE_new(); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); if (lookup == NULL) goto end; if (!X509_LOOKUP_load_file(lookup, crl_config.cafile, X509_FILETYPE_PEM)) X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); if (lookup == NULL) goto end; if (!X509_LOOKUP_add_dir(lookup, crl_config.capath, X509_FILETYPE_PEM)) X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); ERR_clear_error(); if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) { BIO_printf(bio_err, "Error initialising X509 store\n"); goto end; } i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, X509_CRL_get_issuer(x), &xobj); if (i <= 0) { BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); goto end; } pkey = X509_get_pubkey(xobj.data.x509); X509_OBJECT_free_contents(&xobj); if (!pkey) { BIO_printf(bio_err, "Error getting CRL issuer public key\n"); goto end; } i = X509_CRL_verify(x, pkey); EVP_PKEY_free(pkey); if (i < 0) goto end; if (i == 0) BIO_printf(bio_err, "verify failure\n"); else BIO_printf(bio_err, "verify OK\n"); } /* Print requested information the order that the flags were given. */ for (i = 1; i <= argc; i++) { if (crl_config.issuer == i) { print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); } if (crl_config.crlnumber == i) { ASN1_INTEGER *crlnum; crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL); BIO_printf(bio_out, "crlNumber="); if (crlnum) { i2a_ASN1_INTEGER(bio_out, crlnum); ASN1_INTEGER_free(crlnum); } else BIO_puts(bio_out, "<NONE>"); BIO_printf(bio_out, "\n"); } if (crl_config.hash == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash(X509_CRL_get_issuer(x))); } #ifndef OPENSSL_NO_MD5 if (crl_config.hash_old == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash_old(X509_CRL_get_issuer(x))); } #endif if (crl_config.lastupdate == i) { BIO_printf(bio_out, "lastUpdate="); ASN1_TIME_print(bio_out, X509_CRL_get_lastUpdate(x)); BIO_printf(bio_out, "\n"); } if (crl_config.nextupdate == i) { BIO_printf(bio_out, "nextUpdate="); if (X509_CRL_get_nextUpdate(x)) ASN1_TIME_print(bio_out, X509_CRL_get_nextUpdate(x)); else BIO_printf(bio_out, "NONE"); BIO_printf(bio_out, "\n"); } if (crl_config.fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; if (!X509_CRL_digest(x, digest, md, &n)) { BIO_printf(bio_err, "out of memory\n"); goto end; } BIO_printf(bio_out, "%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(digest))); for (j = 0; j < (int) n; j++) { BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); } } } out = BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (crl_config.outfile == NULL) { BIO_set_fp(out, stdout, BIO_NOCLOSE); } else { if (BIO_write_filename(out, crl_config.outfile) <= 0) { perror(crl_config.outfile); goto end; } } if (crl_config.text) X509_CRL_print(out, x); if (crl_config.noout) { ret = 0; goto end; } if (crl_config.outformat == FORMAT_ASN1) i = (int) i2d_X509_CRL_bio(out, x); else if (crl_config.outformat == FORMAT_PEM) i = PEM_write_bio_X509_CRL(out, x); else { BIO_printf(bio_err, "bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err, "unable to write CRL\n"); goto end; } ret = 0; end: BIO_free_all(out); BIO_free_all(bio_out); bio_out = NULL; X509_CRL_free(x); if (store) { X509_STORE_CTX_cleanup(&ctx); X509_STORE_free(store); } return (ret); }
/* * initialize tls virtual domains */ static int init_tls_domains(struct tls_domain *d) { struct tls_domain *dom; dom = d; while (d) { if (d->name.len) { LM_INFO("Processing TLS domain '%.*s'\n", d->name.len, ZSW(d->name.s)); } else { LM_INFO("Processing TLS domain [%s:%d]\n", ip_addr2a(&d->addr), d->port); } /* * set method */ if (d->method == TLS_METHOD_UNSPEC) { LM_DBG("no method for tls[%s:%d], using default\n", ip_addr2a(&d->addr), d->port); d->method = tls_default_method; } /* * create context */ d->ctx = SSL_CTX_new(ssl_methods[d->method - 1]); if (d->ctx == NULL) { LM_ERR("cannot create ssl context for " "tls[%s:%d]\n", ip_addr2a(&d->addr), d->port); return -1; } if (init_ssl_ctx_behavior( d ) < 0) return -1; /* * load certificate */ if (!d->cert_file) { LM_NOTICE("no certificate for tls[%s:%d] defined, using default" "'%s'\n", ip_addr2a(&d->addr), d->port, tls_cert_file); d->cert_file = tls_cert_file; } if (load_certificate(d->ctx, d->cert_file) < 0) return -1; /** * load crl from directory */ if (!d->crl_directory) { LM_NOTICE("no crl for tls, using none"); } else { if(load_crl(d->ctx, d->crl_directory, d->crl_check_all) < 0) return -1; } /* * load ca */ if (!d->ca_file) { LM_NOTICE("no CA for tls[%s:%d] defined, " "using default '%s'\n", ip_addr2a(&d->addr), d->port, tls_ca_file); d->ca_file = tls_ca_file; } if (d->ca_file && load_ca(d->ctx, d->ca_file) < 0) return -1; /* * load ca from directory */ if (!d->ca_directory) { LM_NOTICE("no CA for tls[%s:%d] defined, " "using default '%s'\n", ip_addr2a(&d->addr), d->port, tls_ca_dir); d->ca_directory = tls_ca_dir; } if (d->ca_directory && load_ca_dir(d->ctx, d->ca_directory) < 0) return -1; d = d->next; } /* * load all private keys as the last step (may prompt for password) */ d = dom; while (d) { if (!d->pkey_file) { LM_NOTICE("no private key for tls[%s:%d] defined, using default" "'%s'\n", ip_addr2a(&d->addr), d->port, tls_pkey_file); d->pkey_file = tls_pkey_file; } if (load_private_key(d->ctx, d->pkey_file) < 0) return -1; d = d->next; } return 0; }
int hx509_revoke_verify(hx509_context context, hx509_revoke_ctx ctx, hx509_certs certs, time_t now, hx509_cert cert, hx509_cert parent_cert) { const Certificate *c = _hx509_get_cert(cert); const Certificate *p = _hx509_get_cert(parent_cert); unsigned long i, j, k; int ret; hx509_clear_error_string(context); for (i = 0; i < ctx->ocsps.len; i++) { struct revoke_ocsp *ocsp = &ctx->ocsps.val[i]; struct stat sb; /* check this ocsp apply to this cert */ /* check if there is a newer version of the file */ ret = stat(ocsp->path, &sb); if (ret == 0 && ocsp->last_modfied != sb.st_mtime) { ret = load_ocsp(context, ocsp); if (ret) continue; } /* verify signature in ocsp if not already done */ if (ocsp->signer == NULL) { ret = verify_ocsp(context, ocsp, now, certs, parent_cert); if (ret) continue; } for (j = 0; j < ocsp->ocsp.tbsResponseData.responses.len; j++) { heim_octet_string os; ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[j].certID.serialNumber, &c->tbsCertificate.serialNumber); if (ret != 0) continue; /* verify issuer hashes hash */ ret = _hx509_verify_signature(context, NULL, &ocsp->ocsp.tbsResponseData.responses.val[i].certID.hashAlgorithm, &c->tbsCertificate.issuer._save, &ocsp->ocsp.tbsResponseData.responses.val[i].certID.issuerNameHash); if (ret != 0) continue; os.data = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; os.length = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8; ret = _hx509_verify_signature(context, NULL, &ocsp->ocsp.tbsResponseData.responses.val[j].certID.hashAlgorithm, &os, &ocsp->ocsp.tbsResponseData.responses.val[j].certID.issuerKeyHash); if (ret != 0) continue; switch (ocsp->ocsp.tbsResponseData.responses.val[j].certStatus.element) { case choice_OCSPCertStatus_good: break; case choice_OCSPCertStatus_revoked: hx509_set_error_string(context, 0, HX509_CERT_REVOKED, "Certificate revoked by issuer in OCSP"); return HX509_CERT_REVOKED; case choice_OCSPCertStatus_unknown: continue; } /* don't allow the update to be in the future */ if (ocsp->ocsp.tbsResponseData.responses.val[j].thisUpdate > now + context->ocsp_time_diff) continue; /* don't allow the next update to be in the past */ if (ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate) { if (*ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate < now) continue; } /* else should force a refetch, but can we ? */ return 0; } } for (i = 0; i < ctx->crls.len; i++) { struct revoke_crl *crl = &ctx->crls.val[i]; struct stat sb; int diff; /* check if cert.issuer == crls.val[i].crl.issuer */ ret = _hx509_name_cmp(&c->tbsCertificate.issuer, &crl->crl.tbsCertList.issuer, &diff); if (ret || diff) continue; ret = stat(crl->path, &sb); if (ret == 0 && crl->last_modfied != sb.st_mtime) { CRLCertificateList cl; ret = load_crl(crl->path, &crl->last_modfied, &cl); if (ret == 0) { free_CRLCertificateList(&crl->crl); crl->crl = cl; crl->verified = 0; crl->failed_verify = 0; } } if (crl->failed_verify) continue; /* verify signature in crl if not already done */ if (crl->verified == 0) { ret = verify_crl(context, ctx, &crl->crl, now, certs, parent_cert); if (ret) { crl->failed_verify = 1; continue; } crl->verified = 1; } if (crl->crl.tbsCertList.crlExtensions) { for (j = 0; j < crl->crl.tbsCertList.crlExtensions->len; j++) { if (crl->crl.tbsCertList.crlExtensions->val[j].critical) { hx509_set_error_string(context, 0, HX509_CRL_UNKNOWN_EXTENSION, "Unknown CRL extension"); return HX509_CRL_UNKNOWN_EXTENSION; } } } if (crl->crl.tbsCertList.revokedCertificates == NULL) return 0; /* check if cert is in crl */ for (j = 0; j < crl->crl.tbsCertList.revokedCertificates->len; j++) { time_t t; ret = der_heim_integer_cmp(&crl->crl.tbsCertList.revokedCertificates->val[j].userCertificate, &c->tbsCertificate.serialNumber); if (ret != 0) continue; t = _hx509_Time2time_t(&crl->crl.tbsCertList.revokedCertificates->val[j].revocationDate); if (t > now) continue; if (crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions) for (k = 0; k < crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions->len; k++) if (crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions->val[k].critical) return HX509_CRL_UNKNOWN_EXTENSION; hx509_set_error_string(context, 0, HX509_CERT_REVOKED, "Certificate revoked by issuer in CRL"); return HX509_CERT_REVOKED; } return 0; } if (context->flags & HX509_CTX_VERIFY_MISSING_OK) return 0; hx509_set_error_string(context, HX509_ERROR_APPEND, HX509_REVOKE_STATUS_MISSING, "No revoke status found for " "certificates"); return HX509_REVOKE_STATUS_MISSING; }
/* * Revoke one certificate at a time * No check performed to see if certificate already revoked. */ void revoke_cert(char * ca_name, char * name) { char filename[FIELD_SZ+5]; FILE * f ; X509_CRL * crl ; X509 * cert ; ASN1_INTEGER * r_serial ; ASN1_INTEGER * crlnum ; X509_REVOKED * rev ; ASN1_TIME * tm ; identity ca ; BIO * out ; BIGNUM * b_crlnum ; /* Find requested certificate by name */ sprintf(filename, "%s.crt", name); if ((f=fopen(filename, "r"))==NULL) { fprintf(stderr, "Cannot find: %s\n", filename); return ; } cert = PEM_read_X509(f, NULL, NULL, NULL); fclose(f); /* Get certificate serial number */ r_serial = X509_get_serialNumber(cert); /* Find out if if was already revoked */ /* Make a revoked object with that serial */ rev = X509_REVOKED_new(); X509_REVOKED_set_serialNumber(rev, r_serial); X509_free(cert); /* Set reason to unspecified */ rev->reason = ASN1_ENUMERATED_get(CRL_REASON_UNSPECIFIED); /* Load or create new CRL */ if ((crl = load_crl(ca_name))==NULL) { crl = X509_CRL_new(); X509_CRL_set_version(crl, 1); /* Set CRL number */ crlnum = ASN1_INTEGER_new(); ASN1_INTEGER_set(crlnum, 1); X509_CRL_add1_ext_i2d(crl, NID_crl_number, crlnum, 0, 0); ASN1_INTEGER_free(crlnum); } else { crlnum = X509_CRL_get_ext_d2i(crl, NID_crl_number, 0, 0); b_crlnum = ASN1_INTEGER_to_BN(crlnum, NULL); BN_add_word(b_crlnum, 1); BN_to_ASN1_INTEGER(b_crlnum, crlnum); BN_free(b_crlnum); X509_CRL_add1_ext_i2d(crl, NID_crl_number, crlnum, 0, X509V3_ADD_REPLACE_EXISTING); ASN1_INTEGER_free(crlnum); } /* What time is it? */ tm = ASN1_TIME_new(); X509_gmtime_adj(tm, 0); X509_REVOKED_set_revocationDate(rev, tm); X509_CRL_set_lastUpdate(crl, tm); /* Set CRL next update to a year from now */ X509_gmtime_adj(tm, 365*24*60*60); X509_CRL_set_nextUpdate(crl, tm); ASN1_TIME_free(tm); /* Add revoked to CRL */ X509_CRL_add0_revoked(crl, rev); X509_CRL_sort(crl); /* Load root key to sign CRL */ if (load_ca(ca_name, &ca)!=0) { fprintf(stderr, "Cannot find CA key/crt\n"); return ; } X509_CRL_set_issuer_name(crl, X509_get_subject_name(ca.cert)); X509_free(ca.cert); /* Sign CRL */ X509_CRL_sign(crl, ca.key, EVP_sha256()); EVP_PKEY_free(ca.key); /* Dump CRL */ sprintf(filename, "%s.crl", ca_name); if ((f = fopen(filename, "wb"))==NULL) { fprintf(stderr, "Cannot write %s: aborting\n", filename); X509_CRL_free(crl); return ; } out = BIO_new(BIO_s_file()); BIO_set_fp(out, f, BIO_NOCLOSE); PEM_write_bio_X509_CRL(out, crl); BIO_free_all(out); fclose(f); X509_CRL_free(crl); return ; }