crl.c revision 279264
1322249Sbapt/* apps/crl.c */ 2274880Sbapt/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3322249Sbapt * All rights reserved. 4274880Sbapt * 5274880Sbapt * This package is an SSL implementation written 6274880Sbapt * by Eric Young (eay@cryptsoft.com). 7274880Sbapt * The implementation was written so as to conform with Netscapes SSL. 8274880Sbapt * 9274880Sbapt * This library is free for commercial and non-commercial use as long as 10294113Sbapt * the following conditions are aheared to. The following conditions 11274880Sbapt * apply to all code found in this distribution, be it the RC4, RSA, 12294113Sbapt * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13274880Sbapt * included with this distribution is covered by the same copyright terms 14274880Sbapt * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15274880Sbapt * 16274880Sbapt * Copyright remains Eric Young's, and as such any Copyright notices in 17274880Sbapt * the code are not to be removed. 18274880Sbapt * If this package is used in a product, Eric Young should be given attribution 19274880Sbapt * as the author of the parts of the library used. 20275432Sbapt * This can be in the form of a textual message at program startup or 21275432Sbapt * in documentation (online or textual) provided with the package. 22275432Sbapt * 23274880Sbapt * Redistribution and use in source and binary forms, with or without 24294113Sbapt * modification, are permitted provided that the following conditions 25294113Sbapt * are met: 26294113Sbapt * 1. Redistributions of source code must retain the copyright 27274880Sbapt * notice, this list of conditions and the following disclaimer. 28274880Sbapt * 2. Redistributions in binary form must reproduce the above copyright 29274880Sbapt * notice, this list of conditions and the following disclaimer in the 30274880Sbapt * documentation and/or other materials provided with the distribution. 31274880Sbapt * 3. All advertising materials mentioning features or use of this software 32274880Sbapt * must display the following acknowledgement: 33294113Sbapt * "This product includes cryptographic software written by 34274880Sbapt * Eric Young (eay@cryptsoft.com)" 35294113Sbapt * The word 'cryptographic' can be left out if the rouines from the library 36275432Sbapt * being used are not cryptographic related :-). 37275432Sbapt * 4. If you include any Windows specific code (or a derivative thereof) from 38274880Sbapt * the apps directory (application code) you must include an acknowledgement: 39294113Sbapt * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40274880Sbapt * 41294113Sbapt * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42274880Sbapt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43274880Sbapt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44274880Sbapt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45274880Sbapt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46274880Sbapt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47294113Sbapt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48274880Sbapt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49274880Sbapt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50274880Sbapt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51294113Sbapt * SUCH DAMAGE. 52274880Sbapt * 53274880Sbapt * The licence and distribution terms for any publically available version or 54274880Sbapt * derivative of this code cannot be changed. i.e. this code cannot simply be 55274880Sbapt * copied and put under another distribution licence 56274880Sbapt * [including the GNU Public Licence.] 57274880Sbapt */ 58274880Sbapt 59274880Sbapt#include <stdio.h> 60274880Sbapt#include <stdlib.h> 61274880Sbapt#include <string.h> 62294113Sbapt#include "apps.h" 63274880Sbapt#include <openssl/bio.h> 64274880Sbapt#include <openssl/err.h> 65274880Sbapt#include <openssl/x509.h> 66274880Sbapt#include <openssl/x509v3.h> 67274880Sbapt#include <openssl/pem.h> 68294113Sbapt 69294113Sbapt#undef PROG 70274880Sbapt#define PROG crl_main 71274880Sbapt 72274880Sbapt#undef POSTFIX 73274880Sbapt#define POSTFIX ".rvk" 74274880Sbapt 75294113Sbaptstatic const char *crl_usage[]={ 76294113Sbapt"usage: crl args\n", 77274880Sbapt"\n", 78274880Sbapt" -inform arg - input format - default PEM (DER or PEM)\n", 79274880Sbapt" -outform arg - output format - default PEM\n", 80274880Sbapt" -text - print out a text format version\n", 81274880Sbapt" -in arg - input file - default stdin\n", 82274880Sbapt" -out arg - output file - default stdout\n", 83274880Sbapt" -hash - print hash value\n", 84294113Sbapt#ifndef OPENSSL_NO_MD5 85294113Sbapt" -hash_old - print old-style (MD5) hash value\n", 86294113Sbapt#endif 87274880Sbapt" -fingerprint - print the crl fingerprint\n", 88274880Sbapt" -issuer - print issuer DN\n", 89274880Sbapt" -lastupdate - lastUpdate field\n", 90274880Sbapt" -nextupdate - nextUpdate field\n", 91294113Sbapt" -crlnumber - print CRL number\n", 92274880Sbapt" -noout - no CRL output\n", 93274880Sbapt" -CAfile name - verify CRL using certificates in file \"name\"\n", 94322249Sbapt" -CApath dir - verify CRL using certificates in \"dir\"\n", 95322249Sbapt" -nameopt arg - various certificate name options\n", 96322249SbaptNULL 97322249Sbapt}; 98322249Sbapt 99322249Sbaptstatic X509_CRL *load_crl(char *file, int format); 100322249Sbaptstatic BIO *bio_out=NULL; 101274880Sbapt 102274880Sbaptint MAIN(int, char **); 103274880Sbapt 104274880Sbaptint MAIN(int argc, char **argv) 105275432Sbapt { 106274880Sbapt unsigned long nmflag = 0; 107274880Sbapt X509_CRL *x=NULL; 108274880Sbapt char *CAfile = NULL, *CApath = NULL; 109274880Sbapt int ret=1,i,num,badops=0; 110274880Sbapt BIO *out=NULL; 111274880Sbapt int informat,outformat; 112274880Sbapt char *infile=NULL,*outfile=NULL; 113275432Sbapt int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0; 114274880Sbapt#ifndef OPENSSL_NO_MD5 115274880Sbapt int hash_old=0; 116274880Sbapt#endif 117274880Sbapt int fingerprint = 0, crlnumber = 0; 118274880Sbapt const char **pp; 119274880Sbapt X509_STORE *store = NULL; 120274880Sbapt X509_STORE_CTX ctx; 121275432Sbapt X509_LOOKUP *lookup = NULL; 122274880Sbapt X509_OBJECT xobj; 123274880Sbapt EVP_PKEY *pkey; 124275432Sbapt int do_ver = 0; 125274880Sbapt const EVP_MD *md_alg,*digest=EVP_sha1(); 126274880Sbapt 127274880Sbapt apps_startup(); 128275432Sbapt 129294113Sbapt if (bio_err == NULL) 130294113Sbapt if ((bio_err=BIO_new(BIO_s_file())) != NULL) 131274880Sbapt BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); 132275432Sbapt 133274880Sbapt if (!load_config(bio_err, NULL)) 134274880Sbapt goto end; 135274880Sbapt 136274880Sbapt if (bio_out == NULL) 137274880Sbapt if ((bio_out=BIO_new(BIO_s_file())) != NULL) 138275432Sbapt { 139294113Sbapt BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); 140294113Sbapt#ifdef OPENSSL_SYS_VMS 141275432Sbapt { 142275432Sbapt BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 143275432Sbapt bio_out = BIO_push(tmpbio, bio_out); 144274880Sbapt } 145274880Sbapt#endif 146274880Sbapt } 147274880Sbapt 148274880Sbapt informat=FORMAT_PEM; 149274880Sbapt outformat=FORMAT_PEM; 150274880Sbapt 151294113Sbapt argc--; 152274880Sbapt argv++; 153274880Sbapt num=0; 154274880Sbapt while (argc >= 1) 155294113Sbapt { 156294113Sbapt#ifdef undef 157274880Sbapt if (strcmp(*argv,"-p") == 0) 158294113Sbapt { 159294113Sbapt if (--argc < 1) goto bad; 160294113Sbapt if (!args_from_file(++argv,Nargc,Nargv)) { goto end; }*/ 161294113Sbapt } 162294113Sbapt#endif 163274880Sbapt if (strcmp(*argv,"-inform") == 0) 164274880Sbapt { 165294113Sbapt if (--argc < 1) goto bad; 166294113Sbapt informat=str2fmt(*(++argv)); 167274880Sbapt } 168294113Sbapt else if (strcmp(*argv,"-outform") == 0) 169294113Sbapt { 170294113Sbapt if (--argc < 1) goto bad; 171274880Sbapt outformat=str2fmt(*(++argv)); 172294113Sbapt } 173294113Sbapt else if (strcmp(*argv,"-in") == 0) 174294113Sbapt { 175274880Sbapt if (--argc < 1) goto bad; 176294113Sbapt infile= *(++argv); 177294113Sbapt } 178274880Sbapt else if (strcmp(*argv,"-out") == 0) 179294113Sbapt { 180294113Sbapt if (--argc < 1) goto bad; 181274880Sbapt outfile= *(++argv); 182294113Sbapt } 183294113Sbapt else if (strcmp(*argv,"-CApath") == 0) 184307795Sbapt { 185307795Sbapt if (--argc < 1) goto bad; 186307795Sbapt CApath = *(++argv); 187294113Sbapt do_ver = 1; 188294113Sbapt } 189307795Sbapt else if (strcmp(*argv,"-CAfile") == 0) 190274880Sbapt { 191294113Sbapt if (--argc < 1) goto bad; 192294113Sbapt CAfile = *(++argv); 193294113Sbapt do_ver = 1; 194294113Sbapt } 195294113Sbapt else if (strcmp(*argv,"-verify") == 0) 196294113Sbapt do_ver = 1; 197294113Sbapt else if (strcmp(*argv,"-text") == 0) 198294113Sbapt text = 1; 199294113Sbapt else if (strcmp(*argv,"-hash") == 0) 200294113Sbapt hash= ++num; 201294113Sbapt#ifndef OPENSSL_NO_MD5 202294113Sbapt else if (strcmp(*argv,"-hash_old") == 0) 203294113Sbapt hash_old= ++num; 204294113Sbapt#endif 205294113Sbapt else if (strcmp(*argv,"-nameopt") == 0) 206294113Sbapt { 207294113Sbapt if (--argc < 1) goto bad; 208294113Sbapt if (!set_name_ex(&nmflag, *(++argv))) goto bad; 209294113Sbapt } 210294113Sbapt else if (strcmp(*argv,"-issuer") == 0) 211294113Sbapt issuer= ++num; 212294113Sbapt else if (strcmp(*argv,"-lastupdate") == 0) 213294113Sbapt lastupdate= ++num; 214294113Sbapt else if (strcmp(*argv,"-nextupdate") == 0) 215294113Sbapt nextupdate= ++num; 216294113Sbapt else if (strcmp(*argv,"-noout") == 0) 217322249Sbapt noout= ++num; 218294113Sbapt else if (strcmp(*argv,"-fingerprint") == 0) 219294113Sbapt fingerprint= ++num; 220294113Sbapt else if (strcmp(*argv,"-crlnumber") == 0) 221294113Sbapt crlnumber= ++num; 222274880Sbapt else if ((md_alg=EVP_get_digestbyname(*argv + 1))) 223294113Sbapt { 224294113Sbapt /* ok */ 225274880Sbapt digest=md_alg; 226294113Sbapt } 227294113Sbapt else 228294113Sbapt { 229274880Sbapt BIO_printf(bio_err,"unknown option %s\n",*argv); 230294113Sbapt badops=1; 231322249Sbapt break; 232322249Sbapt } 233294113Sbapt argc--; 234294113Sbapt argv++; 235294113Sbapt } 236322249Sbapt 237294113Sbapt if (badops) 238294113Sbapt { 239322249Sbaptbad: 240322249Sbapt for (pp=crl_usage; (*pp != NULL); pp++) 241322249Sbapt BIO_printf(bio_err,"%s",*pp); 242294113Sbapt goto end; 243294113Sbapt } 244294113Sbapt 245294113Sbapt ERR_load_crypto_strings(); 246294113Sbapt x=load_crl(infile,informat); 247294113Sbapt if (x == NULL) { goto end; } 248294113Sbapt 249294113Sbapt if(do_ver) { 250294113Sbapt store = X509_STORE_new(); 251294113Sbapt lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file()); 252294113Sbapt if (lookup == NULL) goto end; 253294113Sbapt if (!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) 254294113Sbapt X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT); 255294113Sbapt 256322249Sbapt lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir()); 257322249Sbapt if (lookup == NULL) goto end; 258322249Sbapt if (!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) 259322249Sbapt X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); 260322249Sbapt ERR_clear_error(); 261322249Sbapt 262322249Sbapt if(!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) { 263322249Sbapt BIO_printf(bio_err, 264294113Sbapt "Error initialising X509 store\n"); 265294113Sbapt goto end; 266294113Sbapt } 267322249Sbapt 268322249Sbapt i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, 269322249Sbapt X509_CRL_get_issuer(x), &xobj); 270322249Sbapt if(i <= 0) { 271322249Sbapt BIO_printf(bio_err, 272322249Sbapt "Error getting CRL issuer certificate\n"); 273294113Sbapt goto end; 274322249Sbapt } 275322249Sbapt pkey = X509_get_pubkey(xobj.data.x509); 276322249Sbapt X509_OBJECT_free_contents(&xobj); 277322249Sbapt if(!pkey) { 278322249Sbapt BIO_printf(bio_err, 279322249Sbapt "Error getting CRL issuer public key\n"); 280294113Sbapt goto end; 281322249Sbapt } 282322249Sbapt i = X509_CRL_verify(x, pkey); 283322249Sbapt EVP_PKEY_free(pkey); 284322249Sbapt if(i < 0) goto end; 285322249Sbapt if(i == 0) BIO_printf(bio_err, "verify failure\n"); 286322249Sbapt else BIO_printf(bio_err, "verify OK\n"); 287294113Sbapt } 288322249Sbapt 289322249Sbapt if (num) 290322249Sbapt { 291322249Sbapt for (i=1; i<=num; i++) 292322249Sbapt { 293322249Sbapt if (issuer == i) 294294113Sbapt { 295322249Sbapt print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); 296322249Sbapt } 297322249Sbapt if (crlnumber == i) 298322249Sbapt { 299322249Sbapt ASN1_INTEGER *crlnum; 300322249Sbapt crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, 301322249Sbapt NULL, NULL); 302322249Sbapt BIO_printf(bio_out,"crlNumber="); 303322249Sbapt if (crlnum) 304294113Sbapt { 305322249Sbapt i2a_ASN1_INTEGER(bio_out, crlnum); 306322249Sbapt ASN1_INTEGER_free(crlnum); 307322249Sbapt } 308322249Sbapt else 309322249Sbapt BIO_puts(bio_out, "<NONE>"); 310322249Sbapt BIO_printf(bio_out,"\n"); 311322249Sbapt } 312322249Sbapt if (hash == i) 313322249Sbapt { 314294113Sbapt BIO_printf(bio_out,"%08lx\n", 315294113Sbapt X509_NAME_hash(X509_CRL_get_issuer(x))); 316322249Sbapt } 317294113Sbapt#ifndef OPENSSL_NO_MD5 318294113Sbapt if (hash_old == i) 319322249Sbapt { 320322249Sbapt BIO_printf(bio_out,"%08lx\n", 321322249Sbapt X509_NAME_hash_old( 322322249Sbapt X509_CRL_get_issuer(x))); 323294113Sbapt } 324322249Sbapt#endif 325322249Sbapt if (lastupdate == i) 326322249Sbapt { 327294113Sbapt BIO_printf(bio_out,"lastUpdate="); 328322249Sbapt ASN1_TIME_print(bio_out, 329322249Sbapt X509_CRL_get_lastUpdate(x)); 330322249Sbapt BIO_printf(bio_out,"\n"); 331322249Sbapt } 332322249Sbapt if (nextupdate == i) 333294113Sbapt { 334 BIO_printf(bio_out,"nextUpdate="); 335 if (X509_CRL_get_nextUpdate(x)) 336 ASN1_TIME_print(bio_out, 337 X509_CRL_get_nextUpdate(x)); 338 else 339 BIO_printf(bio_out,"NONE"); 340 BIO_printf(bio_out,"\n"); 341 } 342 if (fingerprint == i) 343 { 344 int j; 345 unsigned int n; 346 unsigned char md[EVP_MAX_MD_SIZE]; 347 348 if (!X509_CRL_digest(x,digest,md,&n)) 349 { 350 BIO_printf(bio_err,"out of memory\n"); 351 goto end; 352 } 353 BIO_printf(bio_out,"%s Fingerprint=", 354 OBJ_nid2sn(EVP_MD_type(digest))); 355 for (j=0; j<(int)n; j++) 356 { 357 BIO_printf(bio_out,"%02X%c",md[j], 358 (j+1 == (int)n) 359 ?'\n':':'); 360 } 361 } 362 } 363 } 364 365 out=BIO_new(BIO_s_file()); 366 if (out == NULL) 367 { 368 ERR_print_errors(bio_err); 369 goto end; 370 } 371 372 if (outfile == NULL) 373 { 374 BIO_set_fp(out,stdout,BIO_NOCLOSE); 375#ifdef OPENSSL_SYS_VMS 376 { 377 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 378 out = BIO_push(tmpbio, out); 379 } 380#endif 381 } 382 else 383 { 384 if (BIO_write_filename(out,outfile) <= 0) 385 { 386 perror(outfile); 387 goto end; 388 } 389 } 390 391 if (text) X509_CRL_print(out, x); 392 393 if (noout) 394 { 395 ret = 0; 396 goto end; 397 } 398 399 if (outformat == FORMAT_ASN1) 400 i=(int)i2d_X509_CRL_bio(out,x); 401 else if (outformat == FORMAT_PEM) 402 i=PEM_write_bio_X509_CRL(out,x); 403 else 404 { 405 BIO_printf(bio_err,"bad output format specified for outfile\n"); 406 goto end; 407 } 408 if (!i) { BIO_printf(bio_err,"unable to write CRL\n"); goto end; } 409 ret=0; 410end: 411 BIO_free_all(out); 412 BIO_free_all(bio_out); 413 bio_out=NULL; 414 X509_CRL_free(x); 415 if(store) { 416 X509_STORE_CTX_cleanup(&ctx); 417 X509_STORE_free(store); 418 } 419 apps_shutdown(); 420 OPENSSL_EXIT(ret); 421 } 422 423static X509_CRL *load_crl(char *infile, int format) 424 { 425 X509_CRL *x=NULL; 426 BIO *in=NULL; 427 428 in=BIO_new(BIO_s_file()); 429 if (in == NULL) 430 { 431 ERR_print_errors(bio_err); 432 goto end; 433 } 434 435 if (infile == NULL) 436 BIO_set_fp(in,stdin,BIO_NOCLOSE); 437 else 438 { 439 if (BIO_read_filename(in,infile) <= 0) 440 { 441 perror(infile); 442 goto end; 443 } 444 } 445 if (format == FORMAT_ASN1) 446 x=d2i_X509_CRL_bio(in,NULL); 447 else if (format == FORMAT_PEM) 448 x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL); 449 else { 450 BIO_printf(bio_err,"bad input format specified for input crl\n"); 451 goto end; 452 } 453 if (x == NULL) 454 { 455 BIO_printf(bio_err,"unable to load CRL\n"); 456 ERR_print_errors(bio_err); 457 goto end; 458 } 459 460end: 461 BIO_free(in); 462 return(x); 463 } 464 465