crl.c revision 225736
1113578Srwatson/* apps/crl.c */ 2196123Srwatson/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3101242Srwatson * All rights reserved. 4107603Sru * 5101242Srwatson * This package is an SSL implementation written 6106430Srwatson * by Eric Young (eay@cryptsoft.com). 7106430Srwatson * The implementation was written so as to conform with Netscapes SSL. 8106430Srwatson * 9106430Srwatson * This library is free for commercial and non-commercial use as long as 10107603Sru * the following conditions are aheared to. The following conditions 11101242Srwatson * apply to all code found in this distribution, be it the RC4, RSA, 12101242Srwatson * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13101242Srwatson * included with this distribution is covered by the same copyright terms 14101242Srwatson * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15101242Srwatson * 16101242Srwatson * Copyright remains Eric Young's, and as such any Copyright notices in 17101242Srwatson * the code are not to be removed. 18101242Srwatson * If this package is used in a product, Eric Young should be given attribution 19107603Sru * as the author of the parts of the library used. 20101242Srwatson * This can be in the form of a textual message at program startup or 21101242Srwatson * in documentation (online or textual) provided with the package. 22101242Srwatson * 23101242Srwatson * Redistribution and use in source and binary forms, with or without 24101242Srwatson * modification, are permitted provided that the following conditions 25101242Srwatson * are met: 26101242Srwatson * 1. Redistributions of source code must retain the copyright 27101242Srwatson * notice, this list of conditions and the following disclaimer. 28101242Srwatson * 2. Redistributions in binary form must reproduce the above copyright 29101242Srwatson * notice, this list of conditions and the following disclaimer in the 30101242Srwatson * documentation and/or other materials provided with the distribution. 31107603Sru * 3. All advertising materials mentioning features or use of this software 32101242Srwatson * must display the following acknowledgement: 33107603Sru * "This product includes cryptographic software written by 34196123Srwatson * Eric Young (eay@cryptsoft.com)" 35101242Srwatson * The word 'cryptographic' can be left out if the rouines from the library 36107744Sru * being used are not cryptographic related :-). 37101242Srwatson * 4. If you include any Windows specific code (or a derivative thereof) from 38101242Srwatson * the apps directory (application code) you must include an acknowledgement: 39115225Sru * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40101242Srwatson * 41101242Srwatson * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42101242Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43101242Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44101242Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45101242Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46101242Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47101242Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48196123Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49196123Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50196123Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51196123Srwatson * SUCH DAMAGE. 52196123Srwatson * 53196123Srwatson * The licence and distribution terms for any publically available version or 54196123Srwatson * derivative of this code cannot be changed. i.e. this code cannot simply be 55101242Srwatson * copied and put under another distribution licence 56196123Srwatson * [including the GNU Public Licence.] 57196123Srwatson */ 58196123Srwatson 59196123Srwatson#include <stdio.h> 60196123Srwatson#include <stdlib.h> 61196123Srwatson#include <string.h> 62196123Srwatson#include "apps.h" 63196123Srwatson#include <openssl/bio.h> 64196123Srwatson#include <openssl/err.h> 65101242Srwatson#include <openssl/x509.h> 66196123Srwatson#include <openssl/x509v3.h> 67196123Srwatson#include <openssl/pem.h> 68196123Srwatson 69196123Srwatson#undef PROG 70196123Srwatson#define PROG crl_main 71196123Srwatson 72196123Srwatson#undef POSTFIX 73196123Srwatson#define POSTFIX ".rvk" 74196123Srwatson 75196123Srwatsonstatic const char *crl_usage[]={ 76196123Srwatson"usage: crl args\n", 77210772Sjoel"\n", 78196123Srwatson" -inform arg - input format - default PEM (DER or PEM)\n", 79196123Srwatson" -outform arg - output format - default PEM\n", 80196123Srwatson" -text - print out a text format version\n", 81196123Srwatson" -in arg - input file - default stdin\n", 82196123Srwatson" -out arg - output file - default stdout\n", 83196123Srwatson" -hash - print hash value\n", 84196123Srwatson" -fingerprint - print the crl fingerprint\n", 85196123Srwatson" -issuer - print issuer DN\n", 86196123Srwatson" -lastupdate - lastUpdate field\n", 87196123Srwatson" -nextupdate - nextUpdate field\n", 88101242Srwatson" -crlnumber - print CRL number\n", 89196123Srwatson" -noout - no CRL output\n", 90196123Srwatson" -CAfile name - verify CRL using certificates in file \"name\"\n", 91196123Srwatson" -CApath dir - verify CRL using certificates in \"dir\"\n", 92196123Srwatson" -nameopt arg - various certificate name options\n", 93196123SrwatsonNULL 94196123Srwatson}; 95196123Srwatson 96101242Srwatsonstatic X509_CRL *load_crl(char *file, int format); 97196123Srwatsonstatic BIO *bio_out=NULL; 98196123Srwatson 99196123Srwatsonint MAIN(int, char **); 100196123Srwatson 101101242Srwatsonint MAIN(int argc, char **argv) 102196123Srwatson { 103196123Srwatson unsigned long nmflag = 0; 104196123Srwatson X509_CRL *x=NULL; 105101242Srwatson char *CAfile = NULL, *CApath = NULL; 106196123Srwatson int ret=1,i,num,badops=0; 107101242Srwatson BIO *out=NULL; 108196123Srwatson int informat,outformat; 109101242Srwatson char *infile=NULL,*outfile=NULL; 110196123Srwatson int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0; 111101242Srwatson int fingerprint = 0, crlnumber = 0; 112210772Sjoel const char **pp; 113101242Srwatson X509_STORE *store = NULL; 114196123Srwatson X509_STORE_CTX ctx; 115101242Srwatson X509_LOOKUP *lookup = NULL; 116196123Srwatson X509_OBJECT xobj; 117101242Srwatson EVP_PKEY *pkey; 118196123Srwatson int do_ver = 0; 119101242Srwatson const EVP_MD *md_alg,*digest=EVP_sha1(); 120196123Srwatson 121196123Srwatson apps_startup(); 122113732Srwatson 123196123Srwatson if (bio_err == NULL) 124113732Srwatson if ((bio_err=BIO_new(BIO_s_file())) != NULL) 125113732Srwatson BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); 126113732Srwatson 127113732Srwatson if (!load_config(bio_err, NULL)) 128101242Srwatson goto end; 129101242Srwatson 130101242Srwatson if (bio_out == NULL) 131101242Srwatson if ((bio_out=BIO_new(BIO_s_file())) != NULL) 132101242Srwatson { 133101242Srwatson BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); 134101242Srwatson#ifdef OPENSSL_SYS_VMS 135113741Srwatson { 136113741Srwatson BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 137113741Srwatson bio_out = BIO_push(tmpbio, bio_out); 138113741Srwatson } 139113741Srwatson#endif 140113741Srwatson } 141113741Srwatson 142113741Srwatson informat=FORMAT_PEM; 143101242Srwatson outformat=FORMAT_PEM; 144101242Srwatson 145101242Srwatson argc--; 146196123Srwatson argv++; 147109263Schris num=0; 148101242Srwatson while (argc >= 1) 149105671Srwatson { 150196123Srwatson#ifdef undef 151109273Schris if (strcmp(*argv,"-p") == 0) 152113741Srwatson { 153105671Srwatson if (--argc < 1) goto bad; 154101242Srwatson if (!args_from_file(++argv,Nargc,Nargv)) { goto end; }*/ 155196123Srwatson } 156196123Srwatson#endif 157210772Sjoel if (strcmp(*argv,"-inform") == 0) 158203787Strhodes { 159196123Srwatson if (--argc < 1) goto bad; 160106430Srwatson informat=str2fmt(*(++argv)); 161106430Srwatson } 162106430Srwatson else if (strcmp(*argv,"-outform") == 0) 163107603Sru { 164107603Sru if (--argc < 1) goto bad; 165107603Sru outformat=str2fmt(*(++argv)); 166106429Srwatson } 167107603Sru else if (strcmp(*argv,"-in") == 0) 168107603Sru { 169107603Sru if (--argc < 1) goto bad; 170106429Srwatson infile= *(++argv); 171106429Srwatson } 172106429Srwatson else if (strcmp(*argv,"-out") == 0) 173106429Srwatson { 174106429Srwatson if (--argc < 1) goto bad; 175106429Srwatson outfile= *(++argv); 176106429Srwatson } 177 else if (strcmp(*argv,"-CApath") == 0) 178 { 179 if (--argc < 1) goto bad; 180 CApath = *(++argv); 181 do_ver = 1; 182 } 183 else if (strcmp(*argv,"-CAfile") == 0) 184 { 185 if (--argc < 1) goto bad; 186 CAfile = *(++argv); 187 do_ver = 1; 188 } 189 else if (strcmp(*argv,"-verify") == 0) 190 do_ver = 1; 191 else if (strcmp(*argv,"-text") == 0) 192 text = 1; 193 else if (strcmp(*argv,"-hash") == 0) 194 hash= ++num; 195 else if (strcmp(*argv,"-nameopt") == 0) 196 { 197 if (--argc < 1) goto bad; 198 if (!set_name_ex(&nmflag, *(++argv))) goto bad; 199 } 200 else if (strcmp(*argv,"-issuer") == 0) 201 issuer= ++num; 202 else if (strcmp(*argv,"-lastupdate") == 0) 203 lastupdate= ++num; 204 else if (strcmp(*argv,"-nextupdate") == 0) 205 nextupdate= ++num; 206 else if (strcmp(*argv,"-noout") == 0) 207 noout= ++num; 208 else if (strcmp(*argv,"-fingerprint") == 0) 209 fingerprint= ++num; 210 else if (strcmp(*argv,"-crlnumber") == 0) 211 crlnumber= ++num; 212 else if ((md_alg=EVP_get_digestbyname(*argv + 1))) 213 { 214 /* ok */ 215 digest=md_alg; 216 } 217 else 218 { 219 BIO_printf(bio_err,"unknown option %s\n",*argv); 220 badops=1; 221 break; 222 } 223 argc--; 224 argv++; 225 } 226 227 if (badops) 228 { 229bad: 230 for (pp=crl_usage; (*pp != NULL); pp++) 231 BIO_printf(bio_err,"%s",*pp); 232 goto end; 233 } 234 235 ERR_load_crypto_strings(); 236 x=load_crl(infile,informat); 237 if (x == NULL) { goto end; } 238 239 if(do_ver) { 240 store = X509_STORE_new(); 241 lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file()); 242 if (lookup == NULL) goto end; 243 if (!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) 244 X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT); 245 246 lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir()); 247 if (lookup == NULL) goto end; 248 if (!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) 249 X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); 250 ERR_clear_error(); 251 252 if(!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) { 253 BIO_printf(bio_err, 254 "Error initialising X509 store\n"); 255 goto end; 256 } 257 258 i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, 259 X509_CRL_get_issuer(x), &xobj); 260 if(i <= 0) { 261 BIO_printf(bio_err, 262 "Error getting CRL issuer certificate\n"); 263 goto end; 264 } 265 pkey = X509_get_pubkey(xobj.data.x509); 266 X509_OBJECT_free_contents(&xobj); 267 if(!pkey) { 268 BIO_printf(bio_err, 269 "Error getting CRL issuer public key\n"); 270 goto end; 271 } 272 i = X509_CRL_verify(x, pkey); 273 EVP_PKEY_free(pkey); 274 if(i < 0) goto end; 275 if(i == 0) BIO_printf(bio_err, "verify failure\n"); 276 else BIO_printf(bio_err, "verify OK\n"); 277 } 278 279 if (num) 280 { 281 for (i=1; i<=num; i++) 282 { 283 if (issuer == i) 284 { 285 print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); 286 } 287 if (crlnumber == i) 288 { 289 ASN1_INTEGER *crlnum; 290 crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, 291 NULL, NULL); 292 BIO_printf(bio_out,"crlNumber="); 293 if (crlnum) 294 { 295 i2a_ASN1_INTEGER(bio_out, crlnum); 296 ASN1_INTEGER_free(crlnum); 297 } 298 else 299 BIO_puts(bio_out, "<NONE>"); 300 BIO_printf(bio_out,"\n"); 301 } 302 if (hash == i) 303 { 304 BIO_printf(bio_out,"%08lx\n", 305 X509_NAME_hash(X509_CRL_get_issuer(x))); 306 } 307 if (lastupdate == i) 308 { 309 BIO_printf(bio_out,"lastUpdate="); 310 ASN1_TIME_print(bio_out, 311 X509_CRL_get_lastUpdate(x)); 312 BIO_printf(bio_out,"\n"); 313 } 314 if (nextupdate == i) 315 { 316 BIO_printf(bio_out,"nextUpdate="); 317 if (X509_CRL_get_nextUpdate(x)) 318 ASN1_TIME_print(bio_out, 319 X509_CRL_get_nextUpdate(x)); 320 else 321 BIO_printf(bio_out,"NONE"); 322 BIO_printf(bio_out,"\n"); 323 } 324 if (fingerprint == i) 325 { 326 int j; 327 unsigned int n; 328 unsigned char md[EVP_MAX_MD_SIZE]; 329 330 if (!X509_CRL_digest(x,digest,md,&n)) 331 { 332 BIO_printf(bio_err,"out of memory\n"); 333 goto end; 334 } 335 BIO_printf(bio_out,"%s Fingerprint=", 336 OBJ_nid2sn(EVP_MD_type(digest))); 337 for (j=0; j<(int)n; j++) 338 { 339 BIO_printf(bio_out,"%02X%c",md[j], 340 (j+1 == (int)n) 341 ?'\n':':'); 342 } 343 } 344 } 345 } 346 347 out=BIO_new(BIO_s_file()); 348 if (out == NULL) 349 { 350 ERR_print_errors(bio_err); 351 goto end; 352 } 353 354 if (outfile == NULL) 355 { 356 BIO_set_fp(out,stdout,BIO_NOCLOSE); 357#ifdef OPENSSL_SYS_VMS 358 { 359 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 360 out = BIO_push(tmpbio, out); 361 } 362#endif 363 } 364 else 365 { 366 if (BIO_write_filename(out,outfile) <= 0) 367 { 368 perror(outfile); 369 goto end; 370 } 371 } 372 373 if (text) X509_CRL_print(out, x); 374 375 if (noout) 376 { 377 ret = 0; 378 goto end; 379 } 380 381 if (outformat == FORMAT_ASN1) 382 i=(int)i2d_X509_CRL_bio(out,x); 383 else if (outformat == FORMAT_PEM) 384 i=PEM_write_bio_X509_CRL(out,x); 385 else 386 { 387 BIO_printf(bio_err,"bad output format specified for outfile\n"); 388 goto end; 389 } 390 if (!i) { BIO_printf(bio_err,"unable to write CRL\n"); goto end; } 391 ret=0; 392end: 393 BIO_free_all(out); 394 BIO_free_all(bio_out); 395 bio_out=NULL; 396 X509_CRL_free(x); 397 if(store) { 398 X509_STORE_CTX_cleanup(&ctx); 399 X509_STORE_free(store); 400 } 401 apps_shutdown(); 402 OPENSSL_EXIT(ret); 403 } 404 405static X509_CRL *load_crl(char *infile, int format) 406 { 407 X509_CRL *x=NULL; 408 BIO *in=NULL; 409 410 in=BIO_new(BIO_s_file()); 411 if (in == NULL) 412 { 413 ERR_print_errors(bio_err); 414 goto end; 415 } 416 417 if (infile == NULL) 418 BIO_set_fp(in,stdin,BIO_NOCLOSE); 419 else 420 { 421 if (BIO_read_filename(in,infile) <= 0) 422 { 423 perror(infile); 424 goto end; 425 } 426 } 427 if (format == FORMAT_ASN1) 428 x=d2i_X509_CRL_bio(in,NULL); 429 else if (format == FORMAT_PEM) 430 x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL); 431 else { 432 BIO_printf(bio_err,"bad input format specified for input crl\n"); 433 goto end; 434 } 435 if (x == NULL) 436 { 437 BIO_printf(bio_err,"unable to load CRL\n"); 438 ERR_print_errors(bio_err); 439 goto end; 440 } 441 442end: 443 BIO_free(in); 444 return(x); 445 } 446 447