155714Skris/* apps/crl.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 8280304Sjkim * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15280304Sjkim * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 22280304Sjkim * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 37280304Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40280304Sjkim * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 52280304Sjkim * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 6055714Skris#include <stdlib.h> 6155714Skris#include <string.h> 6255714Skris#include "apps.h" 6355714Skris#include <openssl/bio.h> 6455714Skris#include <openssl/err.h> 6555714Skris#include <openssl/x509.h> 6655714Skris#include <openssl/x509v3.h> 6755714Skris#include <openssl/pem.h> 6855714Skris 6955714Skris#undef PROG 70280304Sjkim#define PROG crl_main 7155714Skris 7255714Skris#undef POSTFIX 73280304Sjkim#define POSTFIX ".rvk" 7455714Skris 75280304Sjkimstatic const char *crl_usage[] = { 76280304Sjkim "usage: crl args\n", 77280304Sjkim "\n", 78280304Sjkim " -inform arg - input format - default PEM (DER or PEM)\n", 79280304Sjkim " -outform arg - output format - default PEM\n", 80280304Sjkim " -text - print out a text format version\n", 81280304Sjkim " -in arg - input file - default stdin\n", 82280304Sjkim " -out arg - output file - default stdout\n", 83280304Sjkim " -hash - print hash value\n", 84264331Sjkim#ifndef OPENSSL_NO_MD5 85280304Sjkim " -hash_old - print old-style (MD5) hash value\n", 86264331Sjkim#endif 87280304Sjkim " -fingerprint - print the crl fingerprint\n", 88280304Sjkim " -issuer - print issuer DN\n", 89280304Sjkim " -lastupdate - lastUpdate field\n", 90280304Sjkim " -nextupdate - nextUpdate field\n", 91280304Sjkim " -crlnumber - print CRL number\n", 92280304Sjkim " -noout - no CRL output\n", 93280304Sjkim " -CAfile name - verify CRL using certificates in file \"name\"\n", 94280304Sjkim " -CApath dir - verify CRL using certificates in \"dir\"\n", 95280304Sjkim " -nameopt arg - various certificate name options\n", 96280304Sjkim NULL 9755714Skris}; 9855714Skris 9955714Skrisstatic X509_CRL *load_crl(char *file, int format); 100280304Sjkimstatic BIO *bio_out = NULL; 10155714Skris 10259191Skrisint MAIN(int, char **); 10359191Skris 10455714Skrisint MAIN(int argc, char **argv) 105280304Sjkim{ 106280304Sjkim unsigned long nmflag = 0; 107280304Sjkim X509_CRL *x = NULL; 108280304Sjkim char *CAfile = NULL, *CApath = NULL; 109280304Sjkim int ret = 1, i, num, badops = 0; 110280304Sjkim BIO *out = NULL; 111280304Sjkim int informat, outformat; 112280304Sjkim char *infile = NULL, *outfile = NULL; 113280304Sjkim int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = 114280304Sjkim 0, text = 0; 115264331Sjkim#ifndef OPENSSL_NO_MD5 116280304Sjkim int hash_old = 0; 117264331Sjkim#endif 118280304Sjkim int fingerprint = 0, crlnumber = 0; 119280304Sjkim const char **pp; 120280304Sjkim X509_STORE *store = NULL; 121280304Sjkim X509_STORE_CTX ctx; 122280304Sjkim X509_LOOKUP *lookup = NULL; 123280304Sjkim X509_OBJECT xobj; 124280304Sjkim EVP_PKEY *pkey; 125280304Sjkim int do_ver = 0; 126280304Sjkim const EVP_MD *md_alg, *digest = EVP_sha1(); 12755714Skris 128280304Sjkim apps_startup(); 12955714Skris 130280304Sjkim if (bio_err == NULL) 131280304Sjkim if ((bio_err = BIO_new(BIO_s_file())) != NULL) 132280304Sjkim BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 13355714Skris 134280304Sjkim if (!load_config(bio_err, NULL)) 135280304Sjkim goto end; 136109998Smarkm 137280304Sjkim if (bio_out == NULL) 138280304Sjkim if ((bio_out = BIO_new(BIO_s_file())) != NULL) { 139280304Sjkim BIO_set_fp(bio_out, stdout, BIO_NOCLOSE); 140109998Smarkm#ifdef OPENSSL_SYS_VMS 141280304Sjkim { 142280304Sjkim BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 143280304Sjkim bio_out = BIO_push(tmpbio, bio_out); 144280304Sjkim } 14568651Skris#endif 146280304Sjkim } 14755714Skris 148280304Sjkim informat = FORMAT_PEM; 149280304Sjkim outformat = FORMAT_PEM; 15055714Skris 151280304Sjkim argc--; 152280304Sjkim argv++; 153280304Sjkim num = 0; 154280304Sjkim while (argc >= 1) { 15555714Skris#ifdef undef 156280304Sjkim if (strcmp(*argv, "-p") == 0) { 157280304Sjkim if (--argc < 1) 158280304Sjkim goto bad; 159280304Sjkim if (!args_from_file(++argv, Nargc, Nargv)) { 160280304Sjkim goto end; 161280304Sjkim } 162280304Sjkim */} 16355714Skris#endif 164280304Sjkim if (strcmp(*argv, "-inform") == 0) { 165280304Sjkim if (--argc < 1) 166280304Sjkim goto bad; 167280304Sjkim informat = str2fmt(*(++argv)); 168280304Sjkim } else if (strcmp(*argv, "-outform") == 0) { 169280304Sjkim if (--argc < 1) 170280304Sjkim goto bad; 171280304Sjkim outformat = str2fmt(*(++argv)); 172280304Sjkim } else if (strcmp(*argv, "-in") == 0) { 173280304Sjkim if (--argc < 1) 174280304Sjkim goto bad; 175280304Sjkim infile = *(++argv); 176280304Sjkim } else if (strcmp(*argv, "-out") == 0) { 177280304Sjkim if (--argc < 1) 178280304Sjkim goto bad; 179280304Sjkim outfile = *(++argv); 180280304Sjkim } else if (strcmp(*argv, "-CApath") == 0) { 181280304Sjkim if (--argc < 1) 182280304Sjkim goto bad; 183280304Sjkim CApath = *(++argv); 184280304Sjkim do_ver = 1; 185280304Sjkim } else if (strcmp(*argv, "-CAfile") == 0) { 186280304Sjkim if (--argc < 1) 187280304Sjkim goto bad; 188280304Sjkim CAfile = *(++argv); 189280304Sjkim do_ver = 1; 190280304Sjkim } else if (strcmp(*argv, "-verify") == 0) 191280304Sjkim do_ver = 1; 192280304Sjkim else if (strcmp(*argv, "-text") == 0) 193280304Sjkim text = 1; 194280304Sjkim else if (strcmp(*argv, "-hash") == 0) 195280304Sjkim hash = ++num; 196264331Sjkim#ifndef OPENSSL_NO_MD5 197280304Sjkim else if (strcmp(*argv, "-hash_old") == 0) 198280304Sjkim hash_old = ++num; 199264331Sjkim#endif 200280304Sjkim else if (strcmp(*argv, "-nameopt") == 0) { 201280304Sjkim if (--argc < 1) 202280304Sjkim goto bad; 203280304Sjkim if (!set_name_ex(&nmflag, *(++argv))) 204280304Sjkim goto bad; 205280304Sjkim } else if (strcmp(*argv, "-issuer") == 0) 206280304Sjkim issuer = ++num; 207280304Sjkim else if (strcmp(*argv, "-lastupdate") == 0) 208280304Sjkim lastupdate = ++num; 209280304Sjkim else if (strcmp(*argv, "-nextupdate") == 0) 210280304Sjkim nextupdate = ++num; 211280304Sjkim else if (strcmp(*argv, "-noout") == 0) 212280304Sjkim noout = ++num; 213280304Sjkim else if (strcmp(*argv, "-fingerprint") == 0) 214280304Sjkim fingerprint = ++num; 215280304Sjkim else if (strcmp(*argv, "-crlnumber") == 0) 216280304Sjkim crlnumber = ++num; 217280304Sjkim else if ((md_alg = EVP_get_digestbyname(*argv + 1))) { 218280304Sjkim /* ok */ 219280304Sjkim digest = md_alg; 220280304Sjkim } else { 221280304Sjkim BIO_printf(bio_err, "unknown option %s\n", *argv); 222280304Sjkim badops = 1; 223280304Sjkim break; 224280304Sjkim } 225280304Sjkim argc--; 226280304Sjkim argv++; 227280304Sjkim } 22855714Skris 229280304Sjkim if (badops) { 230280304Sjkim bad: 231280304Sjkim for (pp = crl_usage; (*pp != NULL); pp++) 232280304Sjkim BIO_printf(bio_err, "%s", *pp); 233280304Sjkim goto end; 234280304Sjkim } 23555714Skris 236280304Sjkim ERR_load_crypto_strings(); 237280304Sjkim x = load_crl(infile, informat); 238280304Sjkim if (x == NULL) { 239280304Sjkim goto end; 240280304Sjkim } 24155714Skris 242280304Sjkim if (do_ver) { 243280304Sjkim store = X509_STORE_new(); 244280304Sjkim lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); 245280304Sjkim if (lookup == NULL) 246280304Sjkim goto end; 247280304Sjkim if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) 248280304Sjkim X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); 24959191Skris 250280304Sjkim lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); 251280304Sjkim if (lookup == NULL) 252280304Sjkim goto end; 253280304Sjkim if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) 254280304Sjkim X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); 255280304Sjkim ERR_clear_error(); 25659191Skris 257280304Sjkim if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) { 258280304Sjkim BIO_printf(bio_err, "Error initialising X509 store\n"); 259280304Sjkim goto end; 260280304Sjkim } 26159191Skris 262280304Sjkim i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, 263280304Sjkim X509_CRL_get_issuer(x), &xobj); 264280304Sjkim if (i <= 0) { 265280304Sjkim BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); 266280304Sjkim goto end; 267280304Sjkim } 268280304Sjkim pkey = X509_get_pubkey(xobj.data.x509); 269280304Sjkim X509_OBJECT_free_contents(&xobj); 270280304Sjkim if (!pkey) { 271280304Sjkim BIO_printf(bio_err, "Error getting CRL issuer public key\n"); 272280304Sjkim goto end; 273280304Sjkim } 274280304Sjkim i = X509_CRL_verify(x, pkey); 275280304Sjkim EVP_PKEY_free(pkey); 276280304Sjkim if (i < 0) 277280304Sjkim goto end; 278280304Sjkim if (i == 0) 279280304Sjkim BIO_printf(bio_err, "verify failure\n"); 280280304Sjkim else 281280304Sjkim BIO_printf(bio_err, "verify OK\n"); 282280304Sjkim } 283280304Sjkim 284280304Sjkim if (num) { 285280304Sjkim for (i = 1; i <= num; i++) { 286280304Sjkim if (issuer == i) { 287280304Sjkim print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), 288280304Sjkim nmflag); 289280304Sjkim } 290280304Sjkim if (crlnumber == i) { 291280304Sjkim ASN1_INTEGER *crlnum; 292280304Sjkim crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL); 293280304Sjkim BIO_printf(bio_out, "crlNumber="); 294280304Sjkim if (crlnum) { 295280304Sjkim i2a_ASN1_INTEGER(bio_out, crlnum); 296280304Sjkim ASN1_INTEGER_free(crlnum); 297280304Sjkim } else 298280304Sjkim BIO_puts(bio_out, "<NONE>"); 299280304Sjkim BIO_printf(bio_out, "\n"); 300280304Sjkim } 301280304Sjkim if (hash == i) { 302280304Sjkim BIO_printf(bio_out, "%08lx\n", 303280304Sjkim X509_NAME_hash(X509_CRL_get_issuer(x))); 304280304Sjkim } 305264331Sjkim#ifndef OPENSSL_NO_MD5 306280304Sjkim if (hash_old == i) { 307280304Sjkim BIO_printf(bio_out, "%08lx\n", 308280304Sjkim X509_NAME_hash_old(X509_CRL_get_issuer(x))); 309280304Sjkim } 310264331Sjkim#endif 311280304Sjkim if (lastupdate == i) { 312280304Sjkim BIO_printf(bio_out, "lastUpdate="); 313280304Sjkim ASN1_TIME_print(bio_out, X509_CRL_get_lastUpdate(x)); 314280304Sjkim BIO_printf(bio_out, "\n"); 315280304Sjkim } 316280304Sjkim if (nextupdate == i) { 317280304Sjkim BIO_printf(bio_out, "nextUpdate="); 318280304Sjkim if (X509_CRL_get_nextUpdate(x)) 319280304Sjkim ASN1_TIME_print(bio_out, X509_CRL_get_nextUpdate(x)); 320280304Sjkim else 321280304Sjkim BIO_printf(bio_out, "NONE"); 322280304Sjkim BIO_printf(bio_out, "\n"); 323280304Sjkim } 324280304Sjkim if (fingerprint == i) { 325280304Sjkim int j; 326280304Sjkim unsigned int n; 327280304Sjkim unsigned char md[EVP_MAX_MD_SIZE]; 32868651Skris 329280304Sjkim if (!X509_CRL_digest(x, digest, md, &n)) { 330280304Sjkim BIO_printf(bio_err, "out of memory\n"); 331280304Sjkim goto end; 332280304Sjkim } 333280304Sjkim BIO_printf(bio_out, "%s Fingerprint=", 334280304Sjkim OBJ_nid2sn(EVP_MD_type(digest))); 335280304Sjkim for (j = 0; j < (int)n; j++) { 336280304Sjkim BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n) 337280304Sjkim ? '\n' : ':'); 338280304Sjkim } 339280304Sjkim } 340280304Sjkim } 341280304Sjkim } 34255714Skris 343280304Sjkim out = BIO_new(BIO_s_file()); 344280304Sjkim if (out == NULL) { 345280304Sjkim ERR_print_errors(bio_err); 346280304Sjkim goto end; 347280304Sjkim } 34855714Skris 349280304Sjkim if (outfile == NULL) { 350280304Sjkim BIO_set_fp(out, stdout, BIO_NOCLOSE); 351109998Smarkm#ifdef OPENSSL_SYS_VMS 352280304Sjkim { 353280304Sjkim BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 354280304Sjkim out = BIO_push(tmpbio, out); 355280304Sjkim } 35668651Skris#endif 357280304Sjkim } else { 358280304Sjkim if (BIO_write_filename(out, outfile) <= 0) { 359280304Sjkim perror(outfile); 360280304Sjkim goto end; 361280304Sjkim } 362280304Sjkim } 36355714Skris 364280304Sjkim if (text) 365280304Sjkim X509_CRL_print(out, x); 36655714Skris 367280304Sjkim if (noout) { 368280304Sjkim ret = 0; 369280304Sjkim goto end; 370280304Sjkim } 37155714Skris 372280304Sjkim if (outformat == FORMAT_ASN1) 373280304Sjkim i = (int)i2d_X509_CRL_bio(out, x); 374280304Sjkim else if (outformat == FORMAT_PEM) 375280304Sjkim i = PEM_write_bio_X509_CRL(out, x); 376280304Sjkim else { 377280304Sjkim BIO_printf(bio_err, "bad output format specified for outfile\n"); 378280304Sjkim goto end; 379280304Sjkim } 380280304Sjkim if (!i) { 381280304Sjkim BIO_printf(bio_err, "unable to write CRL\n"); 382280304Sjkim goto end; 383280304Sjkim } 384280304Sjkim ret = 0; 385280304Sjkim end: 386280304Sjkim BIO_free_all(out); 387280304Sjkim BIO_free_all(bio_out); 388280304Sjkim bio_out = NULL; 389280304Sjkim X509_CRL_free(x); 390280304Sjkim if (store) { 391280304Sjkim X509_STORE_CTX_cleanup(&ctx); 392280304Sjkim X509_STORE_free(store); 393280304Sjkim } 394280304Sjkim apps_shutdown(); 395280304Sjkim OPENSSL_EXIT(ret); 396280304Sjkim} 39755714Skris 39855714Skrisstatic X509_CRL *load_crl(char *infile, int format) 399280304Sjkim{ 400280304Sjkim X509_CRL *x = NULL; 401280304Sjkim BIO *in = NULL; 40255714Skris 403280304Sjkim in = BIO_new(BIO_s_file()); 404280304Sjkim if (in == NULL) { 405280304Sjkim ERR_print_errors(bio_err); 406280304Sjkim goto end; 407280304Sjkim } 40855714Skris 409280304Sjkim if (infile == NULL) 410280304Sjkim BIO_set_fp(in, stdin, BIO_NOCLOSE); 411280304Sjkim else { 412280304Sjkim if (BIO_read_filename(in, infile) <= 0) { 413280304Sjkim perror(infile); 414280304Sjkim goto end; 415280304Sjkim } 416280304Sjkim } 417280304Sjkim if (format == FORMAT_ASN1) 418280304Sjkim x = d2i_X509_CRL_bio(in, NULL); 419280304Sjkim else if (format == FORMAT_PEM) 420280304Sjkim x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); 421280304Sjkim else { 422280304Sjkim BIO_printf(bio_err, "bad input format specified for input crl\n"); 423280304Sjkim goto end; 424280304Sjkim } 425280304Sjkim if (x == NULL) { 426280304Sjkim BIO_printf(bio_err, "unable to load CRL\n"); 427280304Sjkim ERR_print_errors(bio_err); 428280304Sjkim goto end; 429280304Sjkim } 43055714Skris 431280304Sjkim end: 432280304Sjkim BIO_free(in); 433280304Sjkim return (x); 434280304Sjkim} 435