]>
Commit | Line | Data |
---|---|---|
d02b48c6 | 1 | /* apps/crl.c */ |
58964a49 | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
d02b48c6 RE |
3 | * All rights reserved. |
4 | * | |
5 | * This package is an SSL implementation written | |
6 | * by Eric Young (eay@cryptsoft.com). | |
7 | * The implementation was written so as to conform with Netscapes SSL. | |
10621efd | 8 | * |
d02b48c6 RE |
9 | * This library is free for commercial and non-commercial use as long as |
10 | * the following conditions are aheared to. The following conditions | |
11 | * apply to all code found in this distribution, be it the RC4, RSA, | |
12 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation | |
13 | * included with this distribution is covered by the same copyright terms | |
14 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). | |
10621efd | 15 | * |
d02b48c6 RE |
16 | * Copyright remains Eric Young's, and as such any Copyright notices in |
17 | * the code are not to be removed. | |
18 | * If this package is used in a product, Eric Young should be given attribution | |
19 | * as the author of the parts of the library used. | |
20 | * This can be in the form of a textual message at program startup or | |
21 | * in documentation (online or textual) provided with the package. | |
10621efd | 22 | * |
d02b48c6 RE |
23 | * Redistribution and use in source and binary forms, with or without |
24 | * modification, are permitted provided that the following conditions | |
25 | * are met: | |
26 | * 1. Redistributions of source code must retain the copyright | |
27 | * notice, this list of conditions and the following disclaimer. | |
28 | * 2. Redistributions in binary form must reproduce the above copyright | |
29 | * notice, this list of conditions and the following disclaimer in the | |
30 | * documentation and/or other materials provided with the distribution. | |
31 | * 3. All advertising materials mentioning features or use of this software | |
32 | * must display the following acknowledgement: | |
33 | * "This product includes cryptographic software written by | |
34 | * Eric Young (eay@cryptsoft.com)" | |
35 | * The word 'cryptographic' can be left out if the rouines from the library | |
36 | * being used are not cryptographic related :-). | |
10621efd | 37 | * 4. If you include any Windows specific code (or a derivative thereof) from |
d02b48c6 RE |
38 | * the apps directory (application code) you must include an acknowledgement: |
39 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | |
10621efd | 40 | * |
d02b48c6 RE |
41 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
42 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
43 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
44 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
45 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
46 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
47 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
49 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
50 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
51 | * SUCH DAMAGE. | |
10621efd | 52 | * |
d02b48c6 RE |
53 | * The licence and distribution terms for any publically available version or |
54 | * derivative of this code cannot be changed. i.e. this code cannot simply be | |
55 | * copied and put under another distribution licence | |
56 | * [including the GNU Public Licence.] | |
57 | */ | |
58 | ||
59 | #include <stdio.h> | |
60 | #include <stdlib.h> | |
61 | #include <string.h> | |
62 | #include "apps.h" | |
ec577822 BM |
63 | #include <openssl/bio.h> |
64 | #include <openssl/err.h> | |
65 | #include <openssl/x509.h> | |
66 | #include <openssl/x509v3.h> | |
67 | #include <openssl/pem.h> | |
d02b48c6 RE |
68 | |
69 | #undef PROG | |
10621efd | 70 | #define PROG crl_main |
d02b48c6 RE |
71 | |
72 | #undef POSTFIX | |
10621efd | 73 | #define POSTFIX ".rvk" |
d02b48c6 | 74 | |
10621efd MC |
75 | static const char *crl_usage[] = { |
76 | "usage: crl args\n", | |
77 | "\n", | |
78 | " -inform arg - input format - default PEM (DER or PEM)\n", | |
79 | " -outform arg - output format - default PEM\n", | |
80 | " -text - print out a text format version\n", | |
81 | " -in arg - input file - default stdin\n", | |
82 | " -out arg - output file - default stdout\n", | |
83 | " -hash - print hash value\n", | |
50522642 | 84 | #ifndef OPENSSL_NO_MD5 |
10621efd | 85 | " -hash_old - print old-style (MD5) hash value\n", |
50522642 | 86 | #endif |
10621efd MC |
87 | " -fingerprint - print the crl fingerprint\n", |
88 | " -issuer - print issuer DN\n", | |
89 | " -lastupdate - lastUpdate field\n", | |
90 | " -nextupdate - nextUpdate field\n", | |
91 | " -crlnumber - print CRL number\n", | |
92 | " -noout - no CRL output\n", | |
93 | " -CAfile name - verify CRL using certificates in file \"name\"\n", | |
94 | " -CApath dir - verify CRL using certificates in \"dir\"\n", | |
95 | " -nameopt arg - various certificate name options\n", | |
96 | NULL | |
d02b48c6 RE |
97 | }; |
98 | ||
d02b48c6 | 99 | static X509_CRL *load_crl(char *file, int format); |
10621efd | 100 | static BIO *bio_out = NULL; |
d02b48c6 | 101 | |
667ac4ec RE |
102 | int MAIN(int, char **); |
103 | ||
6b691a5c | 104 | int MAIN(int argc, char **argv) |
10621efd MC |
105 | { |
106 | unsigned long nmflag = 0; | |
107 | X509_CRL *x = NULL; | |
108 | char *CAfile = NULL, *CApath = NULL; | |
109 | int ret = 1, i, num, badops = 0; | |
110 | BIO *out = NULL; | |
111 | int informat, outformat; | |
112 | char *infile = NULL, *outfile = NULL; | |
113 | int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = | |
114 | 0, text = 0; | |
50522642 | 115 | #ifndef OPENSSL_NO_MD5 |
10621efd | 116 | int hash_old = 0; |
50522642 | 117 | #endif |
10621efd MC |
118 | int fingerprint = 0, crlnumber = 0; |
119 | const char **pp; | |
120 | X509_STORE *store = NULL; | |
121 | X509_STORE_CTX ctx; | |
122 | X509_LOOKUP *lookup = NULL; | |
123 | X509_OBJECT xobj; | |
124 | EVP_PKEY *pkey; | |
125 | int do_ver = 0; | |
126 | const EVP_MD *md_alg, *digest = EVP_sha1(); | |
d02b48c6 | 127 | |
10621efd | 128 | apps_startup(); |
d02b48c6 | 129 | |
10621efd MC |
130 | if (bio_err == NULL) |
131 | if ((bio_err = BIO_new(BIO_s_file())) != NULL) | |
132 | BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); | |
d02b48c6 | 133 | |
10621efd MC |
134 | if (!load_config(bio_err, NULL)) |
135 | goto end; | |
3647bee2 | 136 | |
10621efd MC |
137 | if (bio_out == NULL) |
138 | if ((bio_out = BIO_new(BIO_s_file())) != NULL) { | |
139 | BIO_set_fp(bio_out, stdout, BIO_NOCLOSE); | |
bc36ee62 | 140 | #ifdef OPENSSL_SYS_VMS |
10621efd MC |
141 | { |
142 | BIO *tmpbio = BIO_new(BIO_f_linebuffer()); | |
143 | bio_out = BIO_push(tmpbio, bio_out); | |
144 | } | |
645749ef | 145 | #endif |
10621efd | 146 | } |
d02b48c6 | 147 | |
10621efd MC |
148 | informat = FORMAT_PEM; |
149 | outformat = FORMAT_PEM; | |
d02b48c6 | 150 | |
10621efd MC |
151 | argc--; |
152 | argv++; | |
153 | num = 0; | |
154 | while (argc >= 1) { | |
d02b48c6 | 155 | #ifdef undef |
10621efd MC |
156 | if (strcmp(*argv, "-p") == 0) { |
157 | if (--argc < 1) | |
158 | goto bad; | |
159 | if (!args_from_file(++argv, Nargc, Nargv)) { | |
160 | goto end; | |
161 | } | |
162 | */} | |
d02b48c6 | 163 | #endif |
10621efd MC |
164 | if (strcmp(*argv, "-inform") == 0) { |
165 | if (--argc < 1) | |
166 | goto bad; | |
167 | informat = str2fmt(*(++argv)); | |
168 | } else if (strcmp(*argv, "-outform") == 0) { | |
169 | if (--argc < 1) | |
170 | goto bad; | |
171 | outformat = str2fmt(*(++argv)); | |
172 | } else if (strcmp(*argv, "-in") == 0) { | |
173 | if (--argc < 1) | |
174 | goto bad; | |
175 | infile = *(++argv); | |
176 | } else if (strcmp(*argv, "-out") == 0) { | |
177 | if (--argc < 1) | |
178 | goto bad; | |
179 | outfile = *(++argv); | |
180 | } else if (strcmp(*argv, "-CApath") == 0) { | |
181 | if (--argc < 1) | |
182 | goto bad; | |
183 | CApath = *(++argv); | |
184 | do_ver = 1; | |
185 | } else if (strcmp(*argv, "-CAfile") == 0) { | |
186 | if (--argc < 1) | |
187 | goto bad; | |
188 | CAfile = *(++argv); | |
189 | do_ver = 1; | |
190 | } else if (strcmp(*argv, "-verify") == 0) | |
191 | do_ver = 1; | |
192 | else if (strcmp(*argv, "-text") == 0) | |
193 | text = 1; | |
194 | else if (strcmp(*argv, "-hash") == 0) | |
195 | hash = ++num; | |
50522642 | 196 | #ifndef OPENSSL_NO_MD5 |
10621efd MC |
197 | else if (strcmp(*argv, "-hash_old") == 0) |
198 | hash_old = ++num; | |
50522642 | 199 | #endif |
10621efd MC |
200 | else if (strcmp(*argv, "-nameopt") == 0) { |
201 | if (--argc < 1) | |
202 | goto bad; | |
203 | if (!set_name_ex(&nmflag, *(++argv))) | |
204 | goto bad; | |
205 | } else if (strcmp(*argv, "-issuer") == 0) | |
206 | issuer = ++num; | |
207 | else if (strcmp(*argv, "-lastupdate") == 0) | |
208 | lastupdate = ++num; | |
209 | else if (strcmp(*argv, "-nextupdate") == 0) | |
210 | nextupdate = ++num; | |
211 | else if (strcmp(*argv, "-noout") == 0) | |
212 | noout = ++num; | |
213 | else if (strcmp(*argv, "-fingerprint") == 0) | |
214 | fingerprint = ++num; | |
215 | else if (strcmp(*argv, "-crlnumber") == 0) | |
216 | crlnumber = ++num; | |
217 | else if ((md_alg = EVP_get_digestbyname(*argv + 1))) { | |
218 | /* ok */ | |
219 | digest = md_alg; | |
220 | } else { | |
221 | BIO_printf(bio_err, "unknown option %s\n", *argv); | |
222 | badops = 1; | |
223 | break; | |
224 | } | |
225 | argc--; | |
226 | argv++; | |
227 | } | |
228 | ||
229 | if (badops) { | |
230 | bad: | |
231 | for (pp = crl_usage; (*pp != NULL); pp++) | |
232 | BIO_printf(bio_err, "%s", *pp); | |
233 | goto end; | |
234 | } | |
d02b48c6 | 235 | |
10621efd MC |
236 | ERR_load_crypto_strings(); |
237 | x = load_crl(infile, informat); | |
238 | if (x == NULL) { | |
239 | goto end; | |
240 | } | |
d02b48c6 | 241 | |
10621efd MC |
242 | if (do_ver) { |
243 | store = X509_STORE_new(); | |
244 | lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); | |
245 | if (lookup == NULL) | |
246 | goto end; | |
247 | if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) | |
248 | X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); | |
d02b48c6 | 249 | |
10621efd MC |
250 | lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); |
251 | if (lookup == NULL) | |
252 | goto end; | |
253 | if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) | |
254 | X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); | |
255 | ERR_clear_error(); | |
090d848e | 256 | |
10621efd MC |
257 | if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) { |
258 | BIO_printf(bio_err, "Error initialising X509 store\n"); | |
259 | goto end; | |
260 | } | |
090d848e | 261 | |
10621efd MC |
262 | i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, |
263 | X509_CRL_get_issuer(x), &xobj); | |
264 | if (i <= 0) { | |
265 | BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); | |
266 | goto end; | |
267 | } | |
268 | pkey = X509_get_pubkey(xobj.data.x509); | |
269 | X509_OBJECT_free_contents(&xobj); | |
270 | if (!pkey) { | |
271 | BIO_printf(bio_err, "Error getting CRL issuer public key\n"); | |
272 | goto end; | |
273 | } | |
274 | i = X509_CRL_verify(x, pkey); | |
275 | EVP_PKEY_free(pkey); | |
276 | if (i < 0) | |
277 | goto end; | |
278 | if (i == 0) | |
279 | BIO_printf(bio_err, "verify failure\n"); | |
280 | else | |
281 | BIO_printf(bio_err, "verify OK\n"); | |
282 | } | |
090d848e | 283 | |
10621efd MC |
284 | if (num) { |
285 | for (i = 1; i <= num; i++) { | |
286 | if (issuer == i) { | |
287 | print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), | |
288 | nmflag); | |
289 | } | |
290 | if (crlnumber == i) { | |
291 | ASN1_INTEGER *crlnum; | |
292 | crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL); | |
293 | BIO_printf(bio_out, "crlNumber="); | |
294 | if (crlnum) { | |
295 | i2a_ASN1_INTEGER(bio_out, crlnum); | |
296 | ASN1_INTEGER_free(crlnum); | |
297 | } else | |
298 | BIO_puts(bio_out, "<NONE>"); | |
299 | BIO_printf(bio_out, "\n"); | |
300 | } | |
301 | if (hash == i) { | |
302 | BIO_printf(bio_out, "%08lx\n", | |
303 | X509_NAME_hash(X509_CRL_get_issuer(x))); | |
304 | } | |
50522642 | 305 | #ifndef OPENSSL_NO_MD5 |
10621efd MC |
306 | if (hash_old == i) { |
307 | BIO_printf(bio_out, "%08lx\n", | |
308 | X509_NAME_hash_old(X509_CRL_get_issuer(x))); | |
309 | } | |
50522642 | 310 | #endif |
10621efd MC |
311 | if (lastupdate == i) { |
312 | BIO_printf(bio_out, "lastUpdate="); | |
313 | ASN1_TIME_print(bio_out, X509_CRL_get_lastUpdate(x)); | |
314 | BIO_printf(bio_out, "\n"); | |
315 | } | |
316 | if (nextupdate == i) { | |
317 | BIO_printf(bio_out, "nextUpdate="); | |
318 | if (X509_CRL_get_nextUpdate(x)) | |
319 | ASN1_TIME_print(bio_out, 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 | int j; | |
326 | unsigned int n; | |
327 | unsigned char md[EVP_MAX_MD_SIZE]; | |
439df508 | 328 | |
10621efd MC |
329 | if (!X509_CRL_digest(x, digest, md, &n)) { |
330 | BIO_printf(bio_err, "out of memory\n"); | |
331 | goto end; | |
332 | } | |
333 | BIO_printf(bio_out, "%s Fingerprint=", | |
334 | OBJ_nid2sn(EVP_MD_type(digest))); | |
335 | for (j = 0; j < (int)n; j++) { | |
336 | BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n) | |
337 | ? '\n' : ':'); | |
338 | } | |
339 | } | |
340 | } | |
341 | } | |
d02b48c6 | 342 | |
10621efd MC |
343 | out = BIO_new(BIO_s_file()); |
344 | if (out == NULL) { | |
345 | ERR_print_errors(bio_err); | |
346 | goto end; | |
347 | } | |
d02b48c6 | 348 | |
10621efd MC |
349 | if (outfile == NULL) { |
350 | BIO_set_fp(out, stdout, BIO_NOCLOSE); | |
bc36ee62 | 351 | #ifdef OPENSSL_SYS_VMS |
10621efd MC |
352 | { |
353 | BIO *tmpbio = BIO_new(BIO_f_linebuffer()); | |
354 | out = BIO_push(tmpbio, out); | |
355 | } | |
645749ef | 356 | #endif |
10621efd MC |
357 | } else { |
358 | if (BIO_write_filename(out, outfile) <= 0) { | |
359 | perror(outfile); | |
360 | goto end; | |
361 | } | |
362 | } | |
d02b48c6 | 363 | |
10621efd MC |
364 | if (text) |
365 | X509_CRL_print(out, x); | |
2f0cd195 | 366 | |
10621efd MC |
367 | if (noout) { |
368 | ret = 0; | |
369 | goto end; | |
370 | } | |
2f0cd195 | 371 | |
10621efd MC |
372 | if (outformat == FORMAT_ASN1) |
373 | i = (int)i2d_X509_CRL_bio(out, x); | |
374 | else if (outformat == FORMAT_PEM) | |
375 | i = PEM_write_bio_X509_CRL(out, x); | |
376 | else { | |
377 | BIO_printf(bio_err, "bad output format specified for outfile\n"); | |
378 | goto end; | |
379 | } | |
380 | if (!i) { | |
381 | BIO_printf(bio_err, "unable to write CRL\n"); | |
382 | goto end; | |
383 | } | |
384 | ret = 0; | |
385 | end: | |
386 | BIO_free_all(out); | |
387 | BIO_free_all(bio_out); | |
388 | bio_out = NULL; | |
389 | X509_CRL_free(x); | |
390 | if (store) { | |
391 | X509_STORE_CTX_cleanup(&ctx); | |
392 | X509_STORE_free(store); | |
393 | } | |
394 | apps_shutdown(); | |
395 | OPENSSL_EXIT(ret); | |
396 | } | |
d02b48c6 | 397 | |
6b691a5c | 398 | static X509_CRL *load_crl(char *infile, int format) |
10621efd MC |
399 | { |
400 | X509_CRL *x = NULL; | |
401 | BIO *in = NULL; | |
d02b48c6 | 402 | |
10621efd MC |
403 | in = BIO_new(BIO_s_file()); |
404 | if (in == NULL) { | |
405 | ERR_print_errors(bio_err); | |
406 | goto end; | |
407 | } | |
d02b48c6 | 408 | |
10621efd MC |
409 | if (infile == NULL) |
410 | BIO_set_fp(in, stdin, BIO_NOCLOSE); | |
411 | else { | |
412 | if (BIO_read_filename(in, infile) <= 0) { | |
413 | perror(infile); | |
414 | goto end; | |
415 | } | |
416 | } | |
417 | if (format == FORMAT_ASN1) | |
418 | x = d2i_X509_CRL_bio(in, NULL); | |
419 | else if (format == FORMAT_PEM) | |
420 | x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); | |
421 | else { | |
422 | BIO_printf(bio_err, "bad input format specified for input crl\n"); | |
423 | goto end; | |
424 | } | |
425 | if (x == NULL) { | |
426 | BIO_printf(bio_err, "unable to load CRL\n"); | |
427 | ERR_print_errors(bio_err); | |
428 | goto end; | |
429 | } | |
d02b48c6 | 430 | |
10621efd MC |
431 | end: |
432 | BIO_free(in); | |
433 | return (x); | |
434 | } |