]> git.ipfire.org Git - thirdparty/openssl.git/blob - apps/ocsp.c
Initial OCSP certificate verify. Not complete,
[thirdparty/openssl.git] / apps / ocsp.c
1 /* ocsp.c */
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3 * project 2000.
4 */
5 /* ====================================================================
6 * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59 #include <stdio.h>
60 #include <string.h>
61 #include <openssl/pem.h>
62 #include <openssl/ocsp.h>
63 #include <openssl/err.h>
64 #include "apps.h"
65
66 static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer);
67 static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer);
68
69 #undef PROG
70 #define PROG ocsp_main
71
72 int MAIN(int, char **);
73
74 int MAIN(int argc, char **argv)
75 {
76 char **args;
77 char *host = NULL, *path = "/";
78 char *reqin = NULL, *respin = NULL;
79 char *reqout = NULL, *respout = NULL;
80 char *signfile = NULL, *keyfile = NULL;
81 char *outfile = NULL;
82 int add_nonce = 1;
83 OCSP_REQUEST *req = NULL;
84 OCSP_RESPONSE *resp = NULL;
85 OCSP_BASICRESP *bs = NULL;
86 X509 *issuer = NULL, *cert = NULL;
87 X509 *signer = NULL;
88 EVP_PKEY *key = NULL;
89 BIO *cbio = NULL, *derbio = NULL;
90 BIO *out = NULL;
91 int req_text = 0, resp_text = 0;
92 char *CAfile = NULL, *CApath = NULL;
93 X509_STORE *store = NULL;
94 int ret = 1;
95 int badarg = 0;
96 int i;
97 if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
98 ERR_load_crypto_strings();
99 args = argv + 1;
100 while (!badarg && *args && *args[0] == '-')
101 {
102 if (!strcmp(*args, "-out"))
103 {
104 if (args[1])
105 {
106 args++;
107 outfile = *args;
108 }
109 else badarg = 1;
110 }
111 else if (!strcmp(*args, "-host"))
112 {
113 if (args[1])
114 {
115 args++;
116 host = *args;
117 }
118 else badarg = 1;
119 }
120 else if (!strcmp(*args, "-nonce"))
121 add_nonce = 2;
122 else if (!strcmp(*args, "-no_nonce"))
123 add_nonce = 0;
124 else if (!strcmp(*args, "-text"))
125 {
126 req_text = 1;
127 resp_text = 1;
128 }
129 else if (!strcmp(*args, "-req_text"))
130 req_text = 1;
131 else if (!strcmp(*args, "-resp_text"))
132 resp_text = 1;
133 else if (!strcmp(*args, "-reqin"))
134 {
135 if (args[1])
136 {
137 args++;
138 reqin = *args;
139 }
140 else badarg = 1;
141 }
142 else if (!strcmp(*args, "-respin"))
143 {
144 if (args[1])
145 {
146 args++;
147 respin = *args;
148 }
149 else badarg = 1;
150 }
151 else if (!strcmp(*args, "-signer"))
152 {
153 if (args[1])
154 {
155 args++;
156 signfile = *args;
157 }
158 else badarg = 1;
159 }
160 else if (!strcmp (*args, "-CAfile"))
161 {
162 if (args[1])
163 {
164 args++;
165 CAfile = *args;
166 }
167 else badarg = 1;
168 }
169 else if (!strcmp (*args, "-CApath"))
170 {
171 if (args[1])
172 {
173 args++;
174 CApath = *args;
175 }
176 else badarg = 1;
177 }
178 else if (!strcmp(*args, "-signkey"))
179 {
180 if (args[1])
181 {
182 args++;
183 keyfile = *args;
184 }
185 else badarg = 1;
186 }
187 else if (!strcmp(*args, "-reqout"))
188 {
189 if (args[1])
190 {
191 args++;
192 reqout = *args;
193 }
194 else badarg = 1;
195 }
196 else if (!strcmp(*args, "-respout"))
197 {
198 if (args[1])
199 {
200 args++;
201 respout = *args;
202 }
203 else badarg = 1;
204 }
205 else if (!strcmp(*args, "-path"))
206 {
207 if (args[1])
208 {
209 args++;
210 path = *args;
211 }
212 else badarg = 1;
213 }
214 else if (!strcmp(*args, "-issuer"))
215 {
216 if (args[1])
217 {
218 args++;
219 X509_free(issuer);
220 issuer = load_cert(bio_err, *args, FORMAT_PEM);
221 if(!issuer) goto end;
222 }
223 else badarg = 1;
224 }
225 else if (!strcmp (*args, "-cert"))
226 {
227 if (args[1])
228 {
229 args++;
230 X509_free(cert);
231 cert = load_cert(bio_err, *args, FORMAT_PEM);
232 if(!cert) goto end;
233 if(!add_ocsp_cert(&req, cert, issuer))
234 goto end;
235 }
236 else badarg = 1;
237 }
238 else if (!strcmp(*args, "-serial"))
239 {
240 if (args[1])
241 {
242 args++;
243 if(!add_ocsp_serial(&req, *args, issuer))
244 goto end;
245 }
246 else badarg = 1;
247 }
248 else badarg = 1;
249 args++;
250 }
251
252 /* Have we anything to do? */
253 if (!req && !reqin && !respin) badarg = 1;
254
255 if (badarg)
256 {
257 BIO_printf (bio_err, "OCSP utility\n");
258 BIO_printf (bio_err, "Usage ocsp [options]\n");
259 BIO_printf (bio_err, "where options are\n");
260 BIO_printf (bio_err, "-out file output filename\n");
261 BIO_printf (bio_err, "-issuer file issuer certificate\n");
262 BIO_printf (bio_err, "-cert file certificate to check\n");
263 BIO_printf (bio_err, "-serial n serial number to check\n");
264 BIO_printf (bio_err, "-signer file certificate to sign OCSP request with\n");
265 BIO_printf (bio_err, "-signkey file private key to sign OCSP request with\n");
266 BIO_printf (bio_err, "-req_text print text form of request\n");
267 BIO_printf (bio_err, "-resp_text print text form of response\n");
268 BIO_printf (bio_err, "-text print text form of request and response\n");
269 BIO_printf (bio_err, "-reqout file write DER encoded OCSP request to \"file\"\n");
270 BIO_printf (bio_err, "-respout file write DER encoded OCSP reponse to \"file\"\n");
271 BIO_printf (bio_err, "-reqin file read DER encoded OCSP request from \"file\"\n");
272 BIO_printf (bio_err, "-respin file read DER encoded OCSP reponse from \"file\"\n");
273 BIO_printf (bio_err, "-nonce add OCSP nonce to request\n");
274 BIO_printf (bio_err, "-no_nonce don't add OCSP nonce to request\n");
275 BIO_printf (bio_err, "-host host:n send OCSP request to host on port n\n");
276 BIO_printf (bio_err, "-path path to use in OCSP request\n");
277 goto end;
278 }
279
280 if(outfile) out = BIO_new_file(outfile, "w");
281 else out = BIO_new_fp(stdout, BIO_NOCLOSE);
282
283 if(!out)
284 {
285 BIO_printf(bio_err, "Error opening output file\n");
286 goto end;
287 }
288
289 if (!req && (add_nonce != 2)) add_nonce = 0;
290
291 if (!req && reqin)
292 {
293 derbio = BIO_new_file(reqin, "rb");
294 if (!derbio)
295 {
296 BIO_printf(bio_err, "Error Opening OCSP request file\n");
297 goto end;
298 }
299 req = d2i_OCSP_REQUEST_bio(derbio, NULL);
300 BIO_free(derbio);
301 if(!req)
302 {
303 BIO_printf(bio_err, "Error reading OCSP request\n");
304 goto end;
305 }
306 }
307
308 if (!req && (signfile || reqout || host || add_nonce))
309 {
310 BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
311 goto end;
312 }
313
314 if (req) OCSP_request_add1_nonce(req, NULL, -1);
315
316 if (signfile)
317 {
318 if (!keyfile) keyfile = signfile;
319 signer = load_cert(bio_err, signfile, FORMAT_PEM);
320 if (!signer)
321 {
322 BIO_printf(bio_err, "Error loading signer certificate\n");
323 goto end;
324 }
325 key = load_key(bio_err, keyfile, FORMAT_PEM, NULL, NULL);
326 if (!key)
327 {
328 BIO_printf(bio_err, "Error loading signer private key\n");
329 goto end;
330 }
331 if (!OCSP_request_sign(req, signer, key, EVP_sha1(), NULL, 0))
332 {
333 BIO_printf(bio_err, "Error signing OCSP request\n");
334 goto end;
335 }
336 }
337
338 if (reqout)
339 {
340 derbio = BIO_new_file(reqout, "wb");
341 if (!derbio)
342 {
343 BIO_printf(bio_err, "Error opening file %s\n", reqout);
344 goto end;
345 }
346 i2d_OCSP_REQUEST_bio(derbio, req);
347 BIO_free(derbio);
348 }
349
350 if (req_text && req) OCSP_REQUEST_print(out, req, 0);
351
352 if (host)
353 {
354 cbio = BIO_new_connect(host);
355 if (!cbio)
356 {
357 BIO_printf(bio_err, "Error creating connect BIO\n");
358 goto end;
359 }
360 if (BIO_do_connect(cbio) <= 0)
361 {
362 BIO_printf(bio_err, "Error connecting BIO\n");
363 goto end;
364 }
365 resp = OCSP_sendreq_bio(cbio, path, req);
366 BIO_free(cbio);
367 cbio = NULL;
368 if (!resp)
369 {
370 BIO_printf(bio_err, "Error querying OCSP responsder\n");
371 goto end;
372 }
373 }
374 else if (respin)
375 {
376 derbio = BIO_new_file(respin, "rb");
377 if (!derbio)
378 {
379 BIO_printf(bio_err, "Error Opening OCSP response file\n");
380 goto end;
381 }
382 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
383 BIO_free(derbio);
384 if(!resp)
385 {
386 BIO_printf(bio_err, "Error reading OCSP response\n");
387 goto end;
388 }
389
390 }
391 else
392 {
393 ret = 0;
394 goto end;
395 }
396
397 if (respout)
398 {
399 derbio = BIO_new_file(respout, "wb");
400 if(!derbio)
401 {
402 BIO_printf(bio_err, "Error opening file %s\n", respout);
403 goto end;
404 }
405 i2d_OCSP_RESPONSE_bio(derbio, resp);
406 BIO_free(derbio);
407 }
408
409 if (resp_text) OCSP_RESPONSE_print(out, resp, 0);
410
411 store = setup_verify(bio_err, CAfile, CApath);
412 if(!store) goto end;
413
414 bs = OCSP_response_get1_basic(resp);
415
416 i = OCSP_basic_verify(bs, NULL, store, 0);
417
418 if(i <= 0)
419 {
420 BIO_printf(bio_err, "Response verify error (%d)\n", i);
421 ERR_print_errors(bio_err);
422 }
423
424 ret = 0;
425
426 end:
427 ERR_print_errors(bio_err);
428 X509_free(signer);
429 X509_STORE_free(store);
430 EVP_PKEY_free(key);
431 X509_free(issuer);
432 X509_free(cert);
433 BIO_free(cbio);
434 BIO_free(out);
435 OCSP_REQUEST_free(req);
436 OCSP_RESPONSE_free(resp);
437 OCSP_BASICRESP_free(bs);
438
439 EXIT(ret);
440 }
441
442 static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer)
443 {
444 OCSP_CERTID *id;
445 if(!issuer)
446 {
447 BIO_printf(bio_err, "No issuer certificate specified\n");
448 return 0;
449 }
450 if(!*req) *req = OCSP_REQUEST_new();
451 if(!*req) goto err;
452 id = OCSP_cert_to_id(NULL, cert, issuer);
453 if(!id) goto err;
454 if(!OCSP_request_add0_id(*req, id)) goto err;
455 return 1;
456
457 err:
458 BIO_printf(bio_err, "Error Creating OCSP request\n");
459 return 0;
460 }
461
462 static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer)
463 {
464 OCSP_CERTID *id;
465 X509_NAME *iname;
466 ASN1_BIT_STRING *ikey;
467 ASN1_INTEGER *sno;
468 if(!issuer)
469 {
470 BIO_printf(bio_err, "No issuer certificate specified\n");
471 return 0;
472 }
473 if(!*req) *req = OCSP_REQUEST_new();
474 if(!*req) goto err;
475 iname = X509_get_subject_name(issuer);
476 ikey = issuer->cert_info->key->public_key;
477 sno = s2i_ASN1_INTEGER(NULL, serial);
478 if(!sno)
479 {
480 BIO_printf(bio_err, "Error converting serial number %s\n", serial);
481 return 0;
482 }
483 id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno);
484 ASN1_INTEGER_free(sno);
485 if(!id) goto err;
486 if(!OCSP_request_add0_id(*req, id)) goto err;
487 return 1;
488
489 err:
490 BIO_printf(bio_err, "Error Creating OCSP request\n");
491 return 0;
492 }