version 1.1, 2014/08/26 17:47:24 |
version 1.2, 2014/08/28 14:01:32 |
|
|
|
|
#define POSTFIX ".rvk" |
#define POSTFIX ".rvk" |
|
|
static const char *crl_usage[] = { |
static struct { |
"usage: crl args\n", |
char *cafile; |
"\n", |
char *capath; |
" -inform arg - input format - default PEM (DER or PEM)\n", |
int crlnumber; |
" -outform arg - output format - default PEM\n", |
int fingerprint; |
" -text - print out a text format version\n", |
int hash; |
" -in arg - input file - default stdin\n", |
int hash_old; |
" -out arg - output file - default stdout\n", |
char *infile; |
" -hash - print hash value\n", |
int informat; |
#ifndef OPENSSL_NO_MD5 |
int issuer; |
" -hash_old - print old-style (MD5) hash value\n", |
int lastupdate; |
#endif |
char *nameopt; |
" -fingerprint - print the crl fingerprint\n", |
int nextupdate; |
" -issuer - print issuer DN\n", |
int noout; |
" -lastupdate - lastUpdate field\n", |
char *outfile; |
" -nextupdate - nextUpdate field\n", |
int outformat; |
" -crlnumber - print CRL number\n", |
int text; |
" -noout - no CRL output\n", |
int verify; |
" -CAfile name - verify CRL using certificates in file \"name\"\n", |
} crl_config; |
" -CApath dir - verify CRL using certificates in \"dir\"\n", |
|
" -nameopt arg - various certificate name options\n", |
static struct option crl_options[] = { |
NULL |
{ |
|
.name = "CAfile", |
|
.argname = "file", |
|
.desc = "Verify the CRL using certificates in the given file", |
|
.type = OPTION_ARG, |
|
.opt.arg = &crl_config.cafile, |
|
}, |
|
{ |
|
.name = "CApath", |
|
.argname = "path", |
|
.desc = "Verify the CRL using certificates in the given path", |
|
.type = OPTION_ARG, |
|
.opt.arg = &crl_config.capath, |
|
}, |
|
{ |
|
.name = "crlnumber", |
|
.desc = "Print the CRL number", |
|
.type = OPTION_FLAG_ORD, |
|
.opt.flag = &crl_config.crlnumber, |
|
}, |
|
{ |
|
.name = "fingerprint", |
|
.desc = "Print the CRL fingerprint", |
|
.type = OPTION_FLAG_ORD, |
|
.opt.flag = &crl_config.fingerprint, |
|
}, |
|
{ |
|
.name = "hash", |
|
.desc = "Print the hash of the issuer name", |
|
.type = OPTION_FLAG_ORD, |
|
.opt.flag = &crl_config.hash, |
|
}, |
|
{ |
|
.name = "hash_old", |
|
.desc = "Print an old-style (MD5) hash of the issuer name", |
|
.type = OPTION_FLAG_ORD, |
|
.opt.flag = &crl_config.hash_old, |
|
}, |
|
{ |
|
.name = "in", |
|
.argname = "file", |
|
.desc = "Input file to read from (stdin if unspecified)", |
|
.type = OPTION_ARG, |
|
.opt.arg = &crl_config.infile, |
|
}, |
|
{ |
|
.name = "inform", |
|
.argname = "format", |
|
.desc = "Input format (DER or PEM)", |
|
.type = OPTION_ARG_FORMAT, |
|
.opt.value = &crl_config.informat, |
|
}, |
|
{ |
|
.name = "issuer", |
|
.desc = "Print the issuer name", |
|
.type = OPTION_FLAG_ORD, |
|
.opt.flag = &crl_config.issuer, |
|
}, |
|
{ |
|
.name = "lastupdate", |
|
.desc = "Print the lastUpdate field", |
|
.type = OPTION_FLAG_ORD, |
|
.opt.flag = &crl_config.lastupdate, |
|
}, |
|
{ |
|
.name = "nameopt", |
|
.argname = "options", |
|
.desc = "Specify certificate name options", |
|
.type = OPTION_ARG, |
|
.opt.arg = &crl_config.nameopt, |
|
}, |
|
{ |
|
.name = "nextupdate", |
|
.desc = "Print the nextUpdate field", |
|
.type = OPTION_FLAG_ORD, |
|
.opt.flag = &crl_config.nextupdate, |
|
}, |
|
{ |
|
.name = "noout", |
|
.desc = "Do not output the encoded version of the CRL", |
|
.type = OPTION_FLAG, |
|
.opt.flag = &crl_config.noout, |
|
}, |
|
{ |
|
.name = "out", |
|
.argname = "file", |
|
.desc = "Output file to write to (stdout if unspecified)", |
|
.type = OPTION_ARG, |
|
.opt.arg = &crl_config.outfile, |
|
}, |
|
{ |
|
.name = "outform", |
|
.argname = "format", |
|
.desc = "Output format (DER or PEM)", |
|
.type = OPTION_ARG_FORMAT, |
|
.opt.value = &crl_config.outformat, |
|
}, |
|
{ |
|
.name = "text", |
|
.desc = "Print out the CRL in text form", |
|
.type = OPTION_FLAG, |
|
.opt.flag = &crl_config.text, |
|
}, |
|
{ |
|
.name = "verify", |
|
.desc = "Verify the signature on the CRL", |
|
.type = OPTION_FLAG, |
|
.opt.flag = &crl_config.verify, |
|
}, |
|
{}, |
}; |
}; |
|
|
|
static void |
|
crl_usage(void) |
|
{ |
|
fprintf(stderr, |
|
"usage: crl [-CAfile file] [-CApath dir] [-fingerprint] [-hash]\n" |
|
" [-in file] [-inform DER | PEM] [-issuer] [-lastupdate]\n" |
|
" [-nextupdate] [-noout] [-out file] [-outform DER | PEM]\n" |
|
" [-text]\n\n"); |
|
options_usage(crl_options); |
|
} |
|
|
static X509_CRL *load_crl(char *file, int format); |
static X509_CRL *load_crl(char *file, int format); |
static BIO *bio_out = NULL; |
static BIO *bio_out = NULL; |
|
|
|
|
{ |
{ |
unsigned long nmflag = 0; |
unsigned long nmflag = 0; |
X509_CRL *x = NULL; |
X509_CRL *x = NULL; |
char *CAfile = NULL, *CApath = NULL; |
int ret = 1, i; |
int ret = 1, i, num, badops = 0; |
|
BIO *out = NULL; |
BIO *out = NULL; |
int informat, outformat; |
|
char *infile = NULL, *outfile = 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 *store = NULL; |
X509_STORE_CTX ctx; |
X509_STORE_CTX ctx; |
X509_LOOKUP *lookup = NULL; |
X509_LOOKUP *lookup = NULL; |
X509_OBJECT xobj; |
X509_OBJECT xobj; |
EVP_PKEY *pkey; |
EVP_PKEY *pkey; |
int do_ver = 0; |
const EVP_MD *digest; |
const EVP_MD *md_alg, *digest = EVP_sha1(); |
char *digest_name = NULL; |
|
|
if (bio_out == NULL) |
if (bio_out == NULL) { |
if ((bio_out = BIO_new(BIO_s_file())) != NULL) { |
if ((bio_out = BIO_new(BIO_s_file())) != NULL) { |
BIO_set_fp(bio_out, stdout, BIO_NOCLOSE); |
BIO_set_fp(bio_out, stdout, BIO_NOCLOSE); |
} |
} |
informat = FORMAT_PEM; |
} |
outformat = FORMAT_PEM; |
|
|
|
argc--; |
digest = EVP_sha1(); |
argv++; |
|
num = 0; |
memset(&crl_config, 0, sizeof(crl_config)); |
while (argc >= 1) { |
crl_config.informat = FORMAT_PEM; |
#ifdef undef |
crl_config.outformat = FORMAT_PEM; |
if (strcmp(*argv, "-p") == 0) { |
|
if (--argc < 1) |
if (options_parse(argc, argv, crl_options, &digest_name) != 0) { |
goto bad; |
crl_usage(); |
if (!args_from_file(++argv, Nargc, Nargv)) { |
goto end; |
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; |
} |
} |
#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; |
|
#ifndef OPENSSL_NO_MD5 |
|
else if (strcmp(*argv, "-hash_old") == 0) |
|
hash_old = ++num; |
|
#endif |
|
else if (strcmp(*argv, "-nameopt") == 0) { |
|
if (--argc < 1) |
|
goto bad; |
|
if (!set_name_ex(&nmflag, *(++argv))) |
|
goto bad; |
|
} 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 (strcmp(*argv, "-crlnumber") == 0) |
|
crlnumber = ++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) { |
if (digest_name != NULL) { |
bad: |
if ((digest = EVP_get_digestbyname(digest_name)) == NULL) { |
for (pp = crl_usage; (*pp != NULL); pp++) |
fprintf(stderr, |
BIO_printf(bio_err, "%s", *pp); |
"Unknown message digest algorithm '%s'\n", |
goto end; |
digest_name); |
|
goto end; |
|
} |
} |
} |
|
|
ERR_load_crypto_strings(); |
ERR_load_crypto_strings(); |
x = load_crl(infile, informat); |
x = load_crl(crl_config.infile, crl_config.informat); |
if (x == NULL) { |
if (x == NULL) |
goto end; |
goto end; |
} |
|
if (do_ver) { |
if (crl_config.verify) { |
store = X509_STORE_new(); |
store = X509_STORE_new(); |
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); |
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); |
if (lookup == NULL) |
if (lookup == NULL) |
goto end; |
goto end; |
if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) |
if (!X509_LOOKUP_load_file(lookup, crl_config.cafile, |
|
X509_FILETYPE_PEM)) |
X509_LOOKUP_load_file(lookup, NULL, |
X509_LOOKUP_load_file(lookup, NULL, |
X509_FILETYPE_DEFAULT); |
X509_FILETYPE_DEFAULT); |
|
|
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); |
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); |
if (lookup == NULL) |
if (lookup == NULL) |
goto end; |
goto end; |
if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) |
if (!X509_LOOKUP_add_dir(lookup, crl_config.capath, |
|
X509_FILETYPE_PEM)) |
X509_LOOKUP_add_dir(lookup, NULL, |
X509_LOOKUP_add_dir(lookup, NULL, |
X509_FILETYPE_DEFAULT); |
X509_FILETYPE_DEFAULT); |
ERR_clear_error(); |
ERR_clear_error(); |
|
|
else |
else |
BIO_printf(bio_err, "verify OK\n"); |
BIO_printf(bio_err, "verify OK\n"); |
} |
} |
if (num) { |
|
for (i = 1; i <= num; i++) { |
/* Print requested information the order that the flags were given. */ |
if (issuer == i) { |
for (i = 1; i <= argc; i++) { |
print_name(bio_out, "issuer=", |
if (crl_config.issuer == i) { |
X509_CRL_get_issuer(x), nmflag); |
print_name(bio_out, "issuer=", |
} |
X509_CRL_get_issuer(x), nmflag); |
if (crlnumber == i) { |
} |
ASN1_INTEGER *crlnum; |
if (crl_config.crlnumber == i) { |
crlnum = X509_CRL_get_ext_d2i(x, |
ASN1_INTEGER *crlnum; |
NID_crl_number, NULL, NULL); |
crlnum = X509_CRL_get_ext_d2i(x, |
BIO_printf(bio_out, "crlNumber="); |
NID_crl_number, NULL, NULL); |
if (crlnum) { |
BIO_printf(bio_out, "crlNumber="); |
i2a_ASN1_INTEGER(bio_out, crlnum); |
if (crlnum) { |
ASN1_INTEGER_free(crlnum); |
i2a_ASN1_INTEGER(bio_out, crlnum); |
} else |
ASN1_INTEGER_free(crlnum); |
BIO_puts(bio_out, "<NONE>"); |
} else |
BIO_printf(bio_out, "\n"); |
BIO_puts(bio_out, "<NONE>"); |
} |
BIO_printf(bio_out, "\n"); |
if (hash == i) { |
} |
BIO_printf(bio_out, "%08lx\n", |
if (crl_config.hash == i) { |
X509_NAME_hash(X509_CRL_get_issuer(x))); |
BIO_printf(bio_out, "%08lx\n", |
} |
X509_NAME_hash(X509_CRL_get_issuer(x))); |
|
} |
#ifndef OPENSSL_NO_MD5 |
#ifndef OPENSSL_NO_MD5 |
if (hash_old == i) { |
if (crl_config.hash_old == i) { |
BIO_printf(bio_out, "%08lx\n", |
BIO_printf(bio_out, "%08lx\n", |
X509_NAME_hash_old(X509_CRL_get_issuer(x))); |
X509_NAME_hash_old(X509_CRL_get_issuer(x))); |
} |
} |
#endif |
#endif |
if (lastupdate == i) { |
if (crl_config.lastupdate == i) { |
BIO_printf(bio_out, "lastUpdate="); |
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, |
ASN1_TIME_print(bio_out, |
X509_CRL_get_lastUpdate(x)); |
X509_CRL_get_nextUpdate(x)); |
BIO_printf(bio_out, "\n"); |
else |
} |
BIO_printf(bio_out, "NONE"); |
if (nextupdate == i) { |
BIO_printf(bio_out, "\n"); |
BIO_printf(bio_out, "nextUpdate="); |
} |
if (X509_CRL_get_nextUpdate(x)) |
if (crl_config.fingerprint == i) { |
ASN1_TIME_print(bio_out, |
int j; |
X509_CRL_get_nextUpdate(x)); |
unsigned int n; |
else |
unsigned char md[EVP_MAX_MD_SIZE]; |
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)) { |
if (!X509_CRL_digest(x, digest, md, &n)) { |
BIO_printf(bio_err, "out of memory\n"); |
BIO_printf(bio_err, "out of memory\n"); |
goto end; |
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' : ':'); |
|
} |
|
} |
} |
|
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()); |
out = BIO_new(BIO_s_file()); |
if (out == NULL) { |
if (out == NULL) { |
ERR_print_errors(bio_err); |
ERR_print_errors(bio_err); |
goto end; |
goto end; |
} |
} |
if (outfile == NULL) { |
if (crl_config.outfile == NULL) { |
BIO_set_fp(out, stdout, BIO_NOCLOSE); |
BIO_set_fp(out, stdout, BIO_NOCLOSE); |
} else { |
} else { |
if (BIO_write_filename(out, outfile) <= 0) { |
if (BIO_write_filename(out, crl_config.outfile) <= 0) { |
perror(outfile); |
perror(crl_config.outfile); |
goto end; |
goto end; |
} |
} |
} |
} |
|
|
if (text) |
if (crl_config.text) |
X509_CRL_print(out, x); |
X509_CRL_print(out, x); |
|
|
if (noout) { |
if (crl_config.noout) { |
ret = 0; |
ret = 0; |
goto end; |
goto end; |
} |
} |
if (outformat == FORMAT_ASN1) |
if (crl_config.outformat == FORMAT_ASN1) |
i = (int) i2d_X509_CRL_bio(out, x); |
i = (int) i2d_X509_CRL_bio(out, x); |
else if (outformat == FORMAT_PEM) |
else if (crl_config.outformat == FORMAT_PEM) |
i = PEM_write_bio_X509_CRL(out, x); |
i = PEM_write_bio_X509_CRL(out, x); |
else { |
else { |
BIO_printf(bio_err, |
BIO_printf(bio_err, |