crl.c revision 194206
1145522Sdarrenr/* apps/crl.c */ 2145522Sdarrenr/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 353642Sguido * All rights reserved. 4255332Scy * 553642Sguido * This package is an SSL implementation written 680482Sdarrenr * by Eric Young (eay@cryptsoft.com). 7255332Scy * The implementation was written so as to conform with Netscapes SSL. 8255332Scy * 9255332Scy * This library is free for commercial and non-commercial use as long as 10255332Scy * the following conditions are aheared to. The following conditions 11255332Scy * apply to all code found in this distribution, be it the RC4, RSA, 1253642Sguido * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13145522Sdarrenr * included with this distribution is covered by the same copyright terms 14145522Sdarrenr * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15145522Sdarrenr * 16145522Sdarrenr * Copyright remains Eric Young's, and as such any Copyright notices in 17145522Sdarrenr * the code are not to be removed. 1892685Sdarrenr * If this package is used in a product, Eric Young should be given attribution 1953642Sguido * as the author of the parts of the library used. 2053642Sguido * This can be in the form of a textual message at program startup or 2153642Sguido * in documentation (online or textual) provided with the package. 2253642Sguido * 23369277Scy * Redistribution and use in source and binary forms, with or without 24145522Sdarrenr * modification, are permitted provided that the following conditions 2563523Sdarrenr * are met: 2663523Sdarrenr * 1. Redistributions of source code must retain the copyright 2753642Sguido * notice, this list of conditions and the following disclaimer. 2853642Sguido * 2. Redistributions in binary form must reproduce the above copyright 2953642Sguido * notice, this list of conditions and the following disclaimer in the 3053642Sguido * documentation and/or other materials provided with the distribution. 31344833Scy * 3. All advertising materials mentioning features or use of this software 32170268Sdarrenr * must display the following acknowledgement: 33170268Sdarrenr * "This product includes cryptographic software written by 34153876Sguido * Eric Young (eay@cryptsoft.com)" 35145522Sdarrenr * The word 'cryptographic' can be left out if the rouines from the library 3653642Sguido * being used are not cryptographic related :-). 37145522Sdarrenr * 4. If you include any Windows specific code (or a derivative thereof) from 3853642Sguido * the apps directory (application code) you must include an acknowledgement: 3953642Sguido * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4053642Sguido * 4153642Sguido * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42145522Sdarrenr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43145522Sdarrenr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44145522Sdarrenr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45145522Sdarrenr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46145522Sdarrenr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4753642Sguido * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48344833Scy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49145522Sdarrenr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50145522Sdarrenr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51369246Scy * SUCH DAMAGE. 52145522Sdarrenr * 5353642Sguido * The licence and distribution terms for any publically available version or 5453642Sguido * derivative of this code cannot be changed. i.e. this code cannot simply be 5553642Sguido * copied and put under another distribution licence 5653642Sguido * [including the GNU Public Licence.] 57145522Sdarrenr */ 5853642Sguido 5953642Sguido#include <stdio.h> 6053642Sguido#include <stdlib.h> 6153642Sguido#include <string.h> 6253642Sguido#include "apps.h" 6353642Sguido#include <openssl/bio.h> 6453642Sguido#include <openssl/err.h> 6553642Sguido#include <openssl/x509.h> 66145522Sdarrenr#include <openssl/x509v3.h> 67145522Sdarrenr#include <openssl/pem.h> 6853642Sguido 6960850Sdarrenr#undef PROG 7060850Sdarrenr#define PROG crl_main 71344833Scy 7260850Sdarrenr#undef POSTFIX 7360850Sdarrenr#define POSTFIX ".rvk" 7460850Sdarrenr 7553642Sguidostatic const char *crl_usage[]={ 7653642Sguido"usage: crl args\n", 7753642Sguido"\n", 7853642Sguido" -inform arg - input format - default PEM (DER or PEM)\n", 7992685Sdarrenr" -outform arg - output format - default PEM\n", 8053642Sguido" -text - print out a text format version\n", 81145522Sdarrenr" -in arg - input file - default stdin\n", 82145522Sdarrenr" -out arg - output file - default stdout\n", 83145522Sdarrenr" -hash - print hash value\n", 84255332Scy" -fingerprint - print the crl fingerprint\n", 85255332Scy" -issuer - print issuer DN\n", 86145522Sdarrenr" -lastupdate - lastUpdate field\n", 87145522Sdarrenr" -nextupdate - nextUpdate field\n", 88145522Sdarrenr" -crlnumber - print CRL number\n", 89145522Sdarrenr" -noout - no CRL output\n", 90145522Sdarrenr" -CAfile name - verify CRL using certificates in file \"name\"\n", 91145522Sdarrenr" -CApath dir - verify CRL using certificates in \"dir\"\n", 92145522Sdarrenr" -nameopt arg - various certificate name options\n", 93145522SdarrenrNULL 94369277Scy}; 95145522Sdarrenr 9653642Sguidostatic X509_CRL *load_crl(char *file, int format); 9753642Sguidostatic BIO *bio_out=NULL; 98255332Scy 99255332Scyint MAIN(int, char **); 100255332Scy 101255332Scyint MAIN(int argc, char **argv) 102255332Scy { 103145522Sdarrenr unsigned long nmflag = 0; 10453642Sguido X509_CRL *x=NULL; 10580482Sdarrenr char *CAfile = NULL, *CApath = NULL; 10680482Sdarrenr int ret=1,i,num,badops=0; 10780482Sdarrenr BIO *out=NULL; 108172776Sdarrenr int informat,outformat; 10980482Sdarrenr char *infile=NULL,*outfile=NULL; 11080482Sdarrenr int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0; 11153642Sguido int fingerprint = 0, crlnumber = 0; 11253642Sguido const char **pp; 11353642Sguido X509_STORE *store = NULL; 11453642Sguido X509_STORE_CTX ctx; 115255332Scy X509_LOOKUP *lookup = NULL; 11653642Sguido X509_OBJECT xobj; 11753642Sguido EVP_PKEY *pkey; 118363769Scy int do_ver = 0; 119363769Scy const EVP_MD *md_alg,*digest=EVP_sha1(); 120255332Scy 121255332Scy apps_startup(); 12253642Sguido 123369245Sgit2svn if (bio_err == NULL) 124369245Sgit2svn if ((bio_err=BIO_new(BIO_s_file())) != NULL) 125369245Sgit2svn BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); 126369245Sgit2svn 127255332Scy if (!load_config(bio_err, NULL)) 128369245Sgit2svn goto end; 12953642Sguido 130369245Sgit2svn if (bio_out == NULL) 131369245Sgit2svn if ((bio_out=BIO_new(BIO_s_file())) != NULL) 132369245Sgit2svn { 133369245Sgit2svn BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); 134369245Sgit2svn#ifdef OPENSSL_SYS_VMS 135369245Sgit2svn { 136369245Sgit2svn BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 137369245Sgit2svn bio_out = BIO_push(tmpbio, bio_out); 138369245Sgit2svn } 139369245Sgit2svn#endif 140369245Sgit2svn } 141369245Sgit2svn 142369245Sgit2svn informat=FORMAT_PEM; 143369245Sgit2svn outformat=FORMAT_PEM; 144369245Sgit2svn 145369245Sgit2svn argc--; 146369245Sgit2svn argv++; 147369245Sgit2svn num=0; 148369245Sgit2svn while (argc >= 1) 149369245Sgit2svn { 150369245Sgit2svn#ifdef undef 151369245Sgit2svn if (strcmp(*argv,"-p") == 0) 152369245Sgit2svn { 153369245Sgit2svn if (--argc < 1) goto bad; 154369245Sgit2svn if (!args_from_file(++argv,Nargc,Nargv)) { goto end; }*/ 155369245Sgit2svn } 156369245Sgit2svn#endif 157369245Sgit2svn if (strcmp(*argv,"-inform") == 0) 158369245Sgit2svn { 159369245Sgit2svn if (--argc < 1) goto bad; 160369245Sgit2svn informat=str2fmt(*(++argv)); 161369245Sgit2svn } 162369245Sgit2svn else if (strcmp(*argv,"-outform") == 0) 163369245Sgit2svn { 164369245Sgit2svn if (--argc < 1) goto bad; 165369245Sgit2svn outformat=str2fmt(*(++argv)); 166369245Sgit2svn } 167369245Sgit2svn else if (strcmp(*argv,"-in") == 0) 168369245Sgit2svn { 169369245Sgit2svn if (--argc < 1) goto bad; 170369245Sgit2svn infile= *(++argv); 171369245Sgit2svn } 172369245Sgit2svn else if (strcmp(*argv,"-out") == 0) 173369245Sgit2svn { 174369245Sgit2svn if (--argc < 1) goto bad; 175369245Sgit2svn outfile= *(++argv); 176369245Sgit2svn } 177369245Sgit2svn else if (strcmp(*argv,"-CApath") == 0) 178369245Sgit2svn { 179369245Sgit2svn if (--argc < 1) goto bad; 180255332Scy CApath = *(++argv); 181369245Sgit2svn do_ver = 1; 182344833Scy } 183255332Scy else if (strcmp(*argv,"-CAfile") == 0) 184145522Sdarrenr { 18553642Sguido if (--argc < 1) goto bad; 18653642Sguido CAfile = *(++argv); 18753642Sguido do_ver = 1; 18853642Sguido } 189145522Sdarrenr else if (strcmp(*argv,"-verify") == 0) 190145522Sdarrenr do_ver = 1; 191145522Sdarrenr else if (strcmp(*argv,"-text") == 0) 19253642Sguido text = 1; 193351468Scy else if (strcmp(*argv,"-hash") == 0) 19453642Sguido hash= ++num; 19553642Sguido else if (strcmp(*argv,"-nameopt") == 0) 19653642Sguido { 19753642Sguido if (--argc < 1) goto bad; 19853642Sguido if (!set_name_ex(&nmflag, *(++argv))) goto bad; 19953642Sguido } 20053642Sguido else if (strcmp(*argv,"-issuer") == 0) 20153642Sguido issuer= ++num; 20253642Sguido else if (strcmp(*argv,"-lastupdate") == 0) 20353642Sguido lastupdate= ++num; 20453642Sguido else if (strcmp(*argv,"-nextupdate") == 0) 20553642Sguido nextupdate= ++num; 20653642Sguido else if (strcmp(*argv,"-noout") == 0) 20753642Sguido noout= ++num; 20853642Sguido else if (strcmp(*argv,"-fingerprint") == 0) 20953642Sguido fingerprint= ++num; 21053642Sguido else if (strcmp(*argv,"-crlnumber") == 0) 21153642Sguido crlnumber= ++num; 21253642Sguido else if ((md_alg=EVP_get_digestbyname(*argv + 1))) 21353642Sguido { 21453642Sguido /* ok */ 21553642Sguido digest=md_alg; 216145522Sdarrenr } 217275199Scy else 218145522Sdarrenr { 219145522Sdarrenr BIO_printf(bio_err,"unknown option %s\n",*argv); 220145522Sdarrenr badops=1; 221145522Sdarrenr break; 222145522Sdarrenr } 223145522Sdarrenr argc--; 224145522Sdarrenr argv++; 225145522Sdarrenr } 226153876Sguido 227145522Sdarrenr if (badops) 228145522Sdarrenr { 229145522Sdarrenrbad: 230145522Sdarrenr for (pp=crl_usage; (*pp != NULL); pp++) 23153642Sguido BIO_printf(bio_err,"%s",*pp); 23253642Sguido goto end; 23353642Sguido } 234351468Scy 23553642Sguido ERR_load_crypto_strings(); 23653642Sguido x=load_crl(infile,informat); 23753642Sguido if (x == NULL) { goto end; } 23853642Sguido 23953642Sguido if(do_ver) { 24053642Sguido store = X509_STORE_new(); 24153642Sguido lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file()); 24253642Sguido if (lookup == NULL) goto end; 24353642Sguido if (!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) 24453642Sguido X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT); 245255332Scy 24653642Sguido lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir()); 247255332Scy if (lookup == NULL) goto end; 248255332Scy if (!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) 249255332Scy X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); 250255332Scy ERR_clear_error(); 251255332Scy 252255332Scy if(!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) { 253255332Scy BIO_printf(bio_err, 254255332Scy "Error initialising X509 store\n"); 255255332Scy goto end; 256255332Scy } 257255332Scy 258255332Scy i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, 259255332Scy X509_CRL_get_issuer(x), &xobj); 260255332Scy if(i <= 0) { 261255332Scy BIO_printf(bio_err, 262255332Scy "Error getting CRL issuer certificate\n"); 263255332Scy goto end; 264255332Scy } 265255332Scy pkey = X509_get_pubkey(xobj.data.x509); 266255332Scy X509_OBJECT_free_contents(&xobj); 267255332Scy if(!pkey) { 268255332Scy BIO_printf(bio_err, 269255332Scy "Error getting CRL issuer public key\n"); 270255332Scy goto end; 271255332Scy } 272255332Scy i = X509_CRL_verify(x, pkey); 273255332Scy EVP_PKEY_free(pkey); 27453642Sguido if(i < 0) goto end; 275145522Sdarrenr if(i == 0) BIO_printf(bio_err, "verify failure\n"); 27653642Sguido else BIO_printf(bio_err, "verify OK\n"); 277255332Scy } 278255332Scy 279255332Scy if (num) 280255332Scy { 281255332Scy for (i=1; i<=num; i++) 282255332Scy { 283255332Scy if (issuer == i) 284255332Scy { 285255332Scy print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); 286255332Scy } 287255332Scy if (crlnumber == i) 288255332Scy { 289255332Scy ASN1_INTEGER *crlnum; 290255332Scy crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, 291255332Scy NULL, NULL); 292255332Scy BIO_printf(bio_out,"crlNumber="); 293255332Scy if (crlnum) 294255332Scy { 295255332Scy i2a_ASN1_INTEGER(bio_out, crlnum); 296255332Scy ASN1_INTEGER_free(crlnum); 297255332Scy } 298255332Scy else 299255332Scy BIO_puts(bio_out, "<NONE>"); 300255332Scy BIO_printf(bio_out,"\n"); 301255332Scy } 302255332Scy if (hash == i) 303255332Scy { 304255332Scy BIO_printf(bio_out,"%08lx\n", 305255332Scy X509_NAME_hash(X509_CRL_get_issuer(x))); 306255332Scy } 307255332Scy if (lastupdate == i) 308255332Scy { 309255332Scy BIO_printf(bio_out,"lastUpdate="); 310255332Scy ASN1_TIME_print(bio_out, 311255332Scy X509_CRL_get_lastUpdate(x)); 312255332Scy BIO_printf(bio_out,"\n"); 313255332Scy } 314255332Scy if (nextupdate == i) 315255332Scy { 316255332Scy BIO_printf(bio_out,"nextUpdate="); 317255332Scy if (X509_CRL_get_nextUpdate(x)) 318255332Scy ASN1_TIME_print(bio_out, 319255332Scy X509_CRL_get_nextUpdate(x)); 320255332Scy else 321255332Scy BIO_printf(bio_out,"NONE"); 322255332Scy BIO_printf(bio_out,"\n"); 323255332Scy } 324255332Scy if (fingerprint == i) 325255332Scy { 326255332Scy int j; 327255332Scy unsigned int n; 328255332Scy unsigned char md[EVP_MAX_MD_SIZE]; 329255332Scy 330255332Scy if (!X509_CRL_digest(x,digest,md,&n)) 331255332Scy { 332255332Scy BIO_printf(bio_err,"out of memory\n"); 333255332Scy goto end; 334255332Scy } 335255332Scy BIO_printf(bio_out,"%s Fingerprint=", 336255332Scy OBJ_nid2sn(EVP_MD_type(digest))); 337255332Scy for (j=0; j<(int)n; j++) 338255332Scy { 339255332Scy BIO_printf(bio_out,"%02X%c",md[j], 340255332Scy (j+1 == (int)n) 341255332Scy ?'\n':':'); 342255332Scy } 343255332Scy } 344255332Scy } 345255332Scy } 346255332Scy 347255332Scy out=BIO_new(BIO_s_file()); 348255332Scy if (out == NULL) 349255332Scy { 350255332Scy ERR_print_errors(bio_err); 351255332Scy goto end; 352255332Scy } 353255332Scy 354255332Scy if (outfile == NULL) 355255332Scy { 356255332Scy BIO_set_fp(out,stdout,BIO_NOCLOSE); 357255332Scy#ifdef OPENSSL_SYS_VMS 358255332Scy { 359255332Scy BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 360255332Scy out = BIO_push(tmpbio, out); 361255332Scy } 362255332Scy#endif 363255332Scy } 364255332Scy else 365255332Scy { 366255332Scy if (BIO_write_filename(out,outfile) <= 0) 367255332Scy { 368255332Scy perror(outfile); 369255332Scy goto end; 370255332Scy } 371255332Scy } 372255332Scy 373255332Scy if (text) X509_CRL_print(out, x); 374255332Scy 375255332Scy if (noout) 376255332Scy { 377145522Sdarrenr ret = 0; 378255332Scy goto end; 379255332Scy } 380255332Scy 381255332Scy if (outformat == FORMAT_ASN1) 382145522Sdarrenr i=(int)i2d_X509_CRL_bio(out,x); 383145522Sdarrenr else if (outformat == FORMAT_PEM) 384145522Sdarrenr i=PEM_write_bio_X509_CRL(out,x); 385145522Sdarrenr else 386330475Seadler { 387145522Sdarrenr BIO_printf(bio_err,"bad output format specified for outfile\n"); 388145522Sdarrenr goto end; 389145522Sdarrenr } 390145522Sdarrenr if (!i) { BIO_printf(bio_err,"unable to write CRL\n"); goto end; } 391255332Scy ret=0; 392145522Sdarrenrend: 393145522Sdarrenr BIO_free_all(out); 394145522Sdarrenr BIO_free_all(bio_out); 395369245Sgit2svn bio_out=NULL; 396369245Sgit2svn X509_CRL_free(x); 397369245Sgit2svn if(store) { 398369245Sgit2svn X509_STORE_CTX_cleanup(&ctx); 399369245Sgit2svn X509_STORE_free(store); 400369245Sgit2svn } 401369245Sgit2svn apps_shutdown(); 402369245Sgit2svn OPENSSL_EXIT(ret); 403369245Sgit2svn } 404369245Sgit2svn 405369245Sgit2svnstatic X509_CRL *load_crl(char *infile, int format) 406369245Sgit2svn { 407369245Sgit2svn X509_CRL *x=NULL; 408369245Sgit2svn BIO *in=NULL; 409145522Sdarrenr 410145522Sdarrenr in=BIO_new(BIO_s_file()); 411145522Sdarrenr if (in == NULL) 412255332Scy { 413145522Sdarrenr ERR_print_errors(bio_err); 414255332Scy goto end; 415255332Scy } 416145522Sdarrenr 417145522Sdarrenr if (infile == NULL) 418145522Sdarrenr BIO_set_fp(in,stdin,BIO_NOCLOSE); 419145522Sdarrenr else 420255332Scy { 421145522Sdarrenr if (BIO_read_filename(in,infile) <= 0) 422255332Scy { 423255332Scy perror(infile); 424255332Scy goto end; 425255332Scy } 42653642Sguido } 42753642Sguido if (format == FORMAT_ASN1) 428153876Sguido x=d2i_X509_CRL_bio(in,NULL); 429153876Sguido else if (format == FORMAT_PEM) 430145522Sdarrenr x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL); 43160850Sdarrenr else { 432145522Sdarrenr BIO_printf(bio_err,"bad input format specified for input crl\n"); 433145522Sdarrenr goto end; 434255332Scy } 435255332Scy if (x == NULL) 436145522Sdarrenr { 437145522Sdarrenr BIO_printf(bio_err,"unable to load CRL\n"); 438145522Sdarrenr ERR_print_errors(bio_err); 439145522Sdarrenr goto end; 440153876Sguido } 441153876Sguido 442153876Sguidoend: 443145522Sdarrenr BIO_free(in); 444255332Scy return(x); 445255332Scy } 446255332Scy 447145522Sdarrenr