]> git.ipfire.org Git - thirdparty/openssl.git/blame - apps/ocsp.c
Make it possible to have multiple active certificates with the same
[thirdparty/openssl.git] / apps / ocsp.c
CommitLineData
5782ceb2
DSH
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 */
85d686e7 58#ifndef OPENSSL_NO_OCSP
5782ceb2
DSH
59
60#include <stdio.h>
61#include <string.h>
7b63c0fa 62#include "apps.h"
5782ceb2
DSH
63#include <openssl/pem.h>
64#include <openssl/ocsp.h>
65#include <openssl/err.h>
cdc7b8cc 66#include <openssl/ssl.h>
5782ceb2 67
f1965221
DSH
68/* Maximum leeway in validity period: default 5 minutes */
69#define MAX_VALIDITY_PERIOD (5 * 60)
70
73758d43
DSH
71static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
72 STACK_OF(OCSP_CERTID) *ids);
73static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer,
74 STACK_OF(OCSP_CERTID) *ids);
75static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
f1965221
DSH
76 STACK *names, STACK_OF(OCSP_CERTID) *ids,
77 long nsec, long maxage);
5782ceb2 78
f85b68cd 79static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, CA_DB *db,
ee306a13
DSH
80 X509 *ca, X509 *rcert, EVP_PKEY *rkey,
81 STACK_OF(X509) *rother, unsigned long flags,
82 int nmin, int ndays);
83
f85b68cd 84static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser);
534a1ed0
DSH
85static BIO *init_responder(char *port);
86static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, char *port);
ee306a13
DSH
87static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp);
88
5782ceb2
DSH
89#undef PROG
90#define PROG ocsp_main
91
92int MAIN(int, char **);
93
94int MAIN(int argc, char **argv)
95 {
30b4c272 96 ENGINE *e = NULL;
5782ceb2 97 char **args;
67c18019 98 char *host = NULL, *port = NULL, *path = "/";
5782ceb2
DSH
99 char *reqin = NULL, *respin = NULL;
100 char *reqout = NULL, *respout = NULL;
101 char *signfile = NULL, *keyfile = NULL;
ee306a13 102 char *rsignfile = NULL, *rkeyfile = NULL;
5782ceb2 103 char *outfile = NULL;
67c18019 104 int add_nonce = 1, noverify = 0, use_ssl = -1;
5782ceb2
DSH
105 OCSP_REQUEST *req = NULL;
106 OCSP_RESPONSE *resp = NULL;
81f169e9 107 OCSP_BASICRESP *bs = NULL;
5782ceb2 108 X509 *issuer = NULL, *cert = NULL;
ee306a13
DSH
109 X509 *signer = NULL, *rsigner = NULL;
110 EVP_PKEY *key = NULL, *rkey = NULL;
534a1ed0
DSH
111 BIO *acbio = NULL, *cbio = NULL;
112 BIO *derbio = NULL;
5782ceb2
DSH
113 BIO *out = NULL;
114 int req_text = 0, resp_text = 0;
f1965221 115 long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
81f169e9
DSH
116 char *CAfile = NULL, *CApath = NULL;
117 X509_STORE *store = NULL;
cdc7b8cc 118 SSL_CTX *ctx = NULL;
ee306a13
DSH
119 STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL;
120 char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
121 unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
5782ceb2 122 int ret = 1;
534a1ed0 123 int accept_count = -1;
5782ceb2 124 int badarg = 0;
81f169e9 125 int i;
73758d43
DSH
126 STACK *reqnames = NULL;
127 STACK_OF(OCSP_CERTID) *ids = NULL;
ee306a13
DSH
128
129 X509 *rca_cert = NULL;
130 char *ridx_filename = NULL;
131 char *rca_filename = NULL;
f85b68cd 132 CA_DB *rdb = NULL;
ee306a13
DSH
133 int nmin = 0, ndays = -1;
134
5782ceb2 135 if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
3647bee2
DSH
136
137 if (!load_config(bio_err, NULL))
138 goto end;
cdc7b8cc 139 SSL_load_error_strings();
5782ceb2 140 args = argv + 1;
73758d43
DSH
141 reqnames = sk_new_null();
142 ids = sk_OCSP_CERTID_new_null();
5782ceb2
DSH
143 while (!badarg && *args && *args[0] == '-')
144 {
145 if (!strcmp(*args, "-out"))
146 {
147 if (args[1])
148 {
149 args++;
150 outfile = *args;
151 }
152 else badarg = 1;
153 }
67c18019
DSH
154 else if (!strcmp(*args, "-url"))
155 {
156 if (args[1])
157 {
158 args++;
159 if (!OCSP_parse_url(*args, &host, &port, &path, &use_ssl))
160 {
161 BIO_printf(bio_err, "Error parsing URL\n");
162 badarg = 1;
163 }
164 }
165 else badarg = 1;
166 }
5782ceb2
DSH
167 else if (!strcmp(*args, "-host"))
168 {
169 if (args[1])
170 {
171 args++;
172 host = *args;
173 }
174 else badarg = 1;
175 }
ee306a13
DSH
176 else if (!strcmp(*args, "-port"))
177 {
178 if (args[1])
179 {
180 args++;
181 port = *args;
182 }
183 else badarg = 1;
184 }
73758d43
DSH
185 else if (!strcmp(*args, "-noverify"))
186 noverify = 1;
5782ceb2
DSH
187 else if (!strcmp(*args, "-nonce"))
188 add_nonce = 2;
189 else if (!strcmp(*args, "-no_nonce"))
190 add_nonce = 0;
534a1ed0 191 else if (!strcmp(*args, "-resp_no_certs"))
ee306a13 192 rflags |= OCSP_NOCERTS;
534a1ed0 193 else if (!strcmp(*args, "-resp_key_id"))
ee306a13 194 rflags |= OCSP_RESPID_KEY;
8c950429
DSH
195 else if (!strcmp(*args, "-no_certs"))
196 sign_flags |= OCSP_NOCERTS;
197 else if (!strcmp(*args, "-no_signature_verify"))
198 verify_flags |= OCSP_NOSIGS;
199 else if (!strcmp(*args, "-no_cert_verify"))
200 verify_flags |= OCSP_NOVERIFY;
201 else if (!strcmp(*args, "-no_chain"))
202 verify_flags |= OCSP_NOCHAIN;
203 else if (!strcmp(*args, "-no_cert_checks"))
204 verify_flags |= OCSP_NOCHECKS;
205 else if (!strcmp(*args, "-no_explicit"))
206 verify_flags |= OCSP_NOEXPLICIT;
207 else if (!strcmp(*args, "-trust_other"))
208 verify_flags |= OCSP_TRUSTOTHER;
209 else if (!strcmp(*args, "-no_intern"))
210 verify_flags |= OCSP_NOINTERN;
5782ceb2
DSH
211 else if (!strcmp(*args, "-text"))
212 {
213 req_text = 1;
214 resp_text = 1;
215 }
216 else if (!strcmp(*args, "-req_text"))
217 req_text = 1;
218 else if (!strcmp(*args, "-resp_text"))
219 resp_text = 1;
220 else if (!strcmp(*args, "-reqin"))
221 {
222 if (args[1])
223 {
224 args++;
225 reqin = *args;
226 }
227 else badarg = 1;
228 }
229 else if (!strcmp(*args, "-respin"))
230 {
231 if (args[1])
232 {
233 args++;
234 respin = *args;
235 }
236 else badarg = 1;
237 }
238 else if (!strcmp(*args, "-signer"))
239 {
240 if (args[1])
241 {
242 args++;
243 signfile = *args;
244 }
245 else badarg = 1;
246 }
9235adbf
RL
247 else if (!strcmp (*args, "-VAfile"))
248 {
249 if (args[1])
250 {
251 args++;
8c950429
DSH
252 verify_certfile = *args;
253 verify_flags |= OCSP_TRUSTOTHER;
254 }
255 else badarg = 1;
256 }
257 else if (!strcmp(*args, "-sign_other"))
258 {
259 if (args[1])
260 {
261 args++;
262 sign_certfile = *args;
263 }
264 else badarg = 1;
265 }
266 else if (!strcmp(*args, "-verify_other"))
267 {
268 if (args[1])
269 {
270 args++;
271 verify_certfile = *args;
9235adbf
RL
272 }
273 else badarg = 1;
274 }
81f169e9
DSH
275 else if (!strcmp (*args, "-CAfile"))
276 {
277 if (args[1])
278 {
279 args++;
280 CAfile = *args;
281 }
282 else badarg = 1;
283 }
284 else if (!strcmp (*args, "-CApath"))
285 {
286 if (args[1])
287 {
288 args++;
289 CApath = *args;
290 }
291 else badarg = 1;
292 }
f1965221
DSH
293 else if (!strcmp (*args, "-validity_period"))
294 {
295 if (args[1])
296 {
297 args++;
298 nsec = atol(*args);
299 if (nsec < 0)
300 {
301 BIO_printf(bio_err,
302 "Illegal validity period %s\n",
303 *args);
304 badarg = 1;
305 }
306 }
307 else badarg = 1;
308 }
309 else if (!strcmp (*args, "-status_age"))
310 {
311 if (args[1])
312 {
313 args++;
314 maxage = atol(*args);
315 if (maxage < 0)
316 {
317 BIO_printf(bio_err,
318 "Illegal validity age %s\n",
319 *args);
320 badarg = 1;
321 }
322 }
323 else badarg = 1;
324 }
5782ceb2
DSH
325 else if (!strcmp(*args, "-signkey"))
326 {
327 if (args[1])
328 {
329 args++;
330 keyfile = *args;
331 }
332 else badarg = 1;
333 }
334 else if (!strcmp(*args, "-reqout"))
335 {
336 if (args[1])
337 {
338 args++;
339 reqout = *args;
340 }
341 else badarg = 1;
342 }
343 else if (!strcmp(*args, "-respout"))
344 {
345 if (args[1])
346 {
347 args++;
348 respout = *args;
349 }
350 else badarg = 1;
351 }
352 else if (!strcmp(*args, "-path"))
353 {
354 if (args[1])
355 {
356 args++;
357 path = *args;
358 }
359 else badarg = 1;
360 }
361 else if (!strcmp(*args, "-issuer"))
362 {
363 if (args[1])
364 {
365 args++;
366 X509_free(issuer);
30b4c272
RL
367 issuer = load_cert(bio_err, *args, FORMAT_PEM,
368 NULL, e, "issuer certificate");
5782ceb2
DSH
369 if(!issuer) goto end;
370 }
371 else badarg = 1;
372 }
373 else if (!strcmp (*args, "-cert"))
374 {
375 if (args[1])
376 {
377 args++;
378 X509_free(cert);
30b4c272
RL
379 cert = load_cert(bio_err, *args, FORMAT_PEM,
380 NULL, e, "certificate");
5782ceb2 381 if(!cert) goto end;
73758d43
DSH
382 if(!add_ocsp_cert(&req, cert, issuer, ids))
383 goto end;
384 if(!sk_push(reqnames, *args))
5782ceb2
DSH
385 goto end;
386 }
387 else badarg = 1;
388 }
389 else if (!strcmp(*args, "-serial"))
390 {
391 if (args[1])
392 {
393 args++;
73758d43
DSH
394 if(!add_ocsp_serial(&req, *args, issuer, ids))
395 goto end;
396 if(!sk_push(reqnames, *args))
5782ceb2
DSH
397 goto end;
398 }
399 else badarg = 1;
400 }
ee306a13
DSH
401 else if (!strcmp(*args, "-index"))
402 {
403 if (args[1])
404 {
405 args++;
406 ridx_filename = *args;
407 }
408 else badarg = 1;
409 }
410 else if (!strcmp(*args, "-CA"))
411 {
412 if (args[1])
413 {
414 args++;
415 rca_filename = *args;
416 }
417 else badarg = 1;
418 }
419 else if (!strcmp (*args, "-nmin"))
420 {
421 if (args[1])
422 {
423 args++;
424 nmin = atol(*args);
425 if (nmin < 0)
426 {
427 BIO_printf(bio_err,
428 "Illegal update period %s\n",
429 *args);
430 badarg = 1;
431 }
432 }
433 if (ndays == -1)
434 ndays = 0;
435 else badarg = 1;
436 }
534a1ed0
DSH
437 else if (!strcmp (*args, "-nrequest"))
438 {
439 if (args[1])
440 {
441 args++;
442 accept_count = atol(*args);
443 if (accept_count < 0)
444 {
445 BIO_printf(bio_err,
446 "Illegal accept count %s\n",
447 *args);
448 badarg = 1;
449 }
450 }
451 else badarg = 1;
452 }
ee306a13
DSH
453 else if (!strcmp (*args, "-ndays"))
454 {
455 if (args[1])
456 {
457 args++;
458 ndays = atol(*args);
459 if (ndays < 0)
460 {
461 BIO_printf(bio_err,
462 "Illegal update period %s\n",
463 *args);
464 badarg = 1;
465 }
466 }
467 else badarg = 1;
468 }
469 else if (!strcmp(*args, "-rsigner"))
470 {
471 if (args[1])
472 {
473 args++;
474 rsignfile = *args;
475 }
476 else badarg = 1;
477 }
478 else if (!strcmp(*args, "-rkey"))
479 {
480 if (args[1])
481 {
482 args++;
483 rkeyfile = *args;
484 }
485 else badarg = 1;
486 }
487 else if (!strcmp(*args, "-rother"))
488 {
489 if (args[1])
490 {
491 args++;
492 rcertfile = *args;
493 }
494 else badarg = 1;
495 }
5782ceb2
DSH
496 else badarg = 1;
497 args++;
498 }
499
500 /* Have we anything to do? */
ee306a13 501 if (!req && !reqin && !respin && !(port && ridx_filename)) badarg = 1;
5782ceb2
DSH
502
503 if (badarg)
504 {
505 BIO_printf (bio_err, "OCSP utility\n");
506 BIO_printf (bio_err, "Usage ocsp [options]\n");
507 BIO_printf (bio_err, "where options are\n");
8c950429
DSH
508 BIO_printf (bio_err, "-out file output filename\n");
509 BIO_printf (bio_err, "-issuer file issuer certificate\n");
510 BIO_printf (bio_err, "-cert file certificate to check\n");
511 BIO_printf (bio_err, "-serial n serial number to check\n");
512 BIO_printf (bio_err, "-signer file certificate to sign OCSP request with\n");
513 BIO_printf (bio_err, "-signkey file private key to sign OCSP request with\n");
e5b0508a 514 BIO_printf (bio_err, "-sign_other file additional certificates to include in signed request\n");
b3f2e399 515 BIO_printf (bio_err, "-no_certs don't include any certificates in signed request\n");
8c950429
DSH
516 BIO_printf (bio_err, "-req_text print text form of request\n");
517 BIO_printf (bio_err, "-resp_text print text form of response\n");
518 BIO_printf (bio_err, "-text print text form of request and response\n");
519 BIO_printf (bio_err, "-reqout file write DER encoded OCSP request to \"file\"\n");
520 BIO_printf (bio_err, "-respout file write DER encoded OCSP reponse to \"file\"\n");
521 BIO_printf (bio_err, "-reqin file read DER encoded OCSP request from \"file\"\n");
522 BIO_printf (bio_err, "-respin file read DER encoded OCSP reponse from \"file\"\n");
523 BIO_printf (bio_err, "-nonce add OCSP nonce to request\n");
524 BIO_printf (bio_err, "-no_nonce don't add OCSP nonce to request\n");
67c18019 525 BIO_printf (bio_err, "-url URL OCSP responder URL\n");
8c950429
DSH
526 BIO_printf (bio_err, "-host host:n send OCSP request to host on port n\n");
527 BIO_printf (bio_err, "-path path to use in OCSP request\n");
528 BIO_printf (bio_err, "-CApath dir trusted certificates directory\n");
529 BIO_printf (bio_err, "-CAfile file trusted certificates file\n");
530 BIO_printf (bio_err, "-VAfile file validator certificates file\n");
f1965221
DSH
531 BIO_printf (bio_err, "-validity_period n maximum validity discrepancy in seconds\n");
532 BIO_printf (bio_err, "-status_age n maximum status age in seconds\n");
8c950429 533 BIO_printf (bio_err, "-noverify don't verify response at all\n");
e5b0508a 534 BIO_printf (bio_err, "-verify_other file additional certificates to search for signer\n");
b3f2e399
DSH
535 BIO_printf (bio_err, "-trust_other don't verify additional certificates\n");
536 BIO_printf (bio_err, "-no_intern don't search certificates contained in response for signer\n");
e5b0508a 537 BIO_printf (bio_err, "-no_signature_verify don't check signature on response\n");
b3f2e399
DSH
538 BIO_printf (bio_err, "-no_cert_verify don't check signing certificate\n");
539 BIO_printf (bio_err, "-no_chain don't chain verify response\n");
540 BIO_printf (bio_err, "-no_cert_checks don't do additional checks on signing certificate\n");
b439a746 541 BIO_printf (bio_err, "-port num port to run responder on\n");
534a1ed0
DSH
542 BIO_printf (bio_err, "-index file certificate status index file\n");
543 BIO_printf (bio_err, "-CA file CA certificate\n");
99889b46
DSH
544 BIO_printf (bio_err, "-rsigner file responder certificate to sign responses with\n");
545 BIO_printf (bio_err, "-rkey file responder key to sign responses with\n");
534a1ed0
DSH
546 BIO_printf (bio_err, "-rother file other certificates to include in response\n");
547 BIO_printf (bio_err, "-resp_no_certs don't include any certificates in response\n");
548 BIO_printf (bio_err, "-nmin n number of minutes before next update\n");
549 BIO_printf (bio_err, "-ndays n number of days before next update\n");
550 BIO_printf (bio_err, "-resp_key_id identify reponse by signing certificate key ID\n");
551 BIO_printf (bio_err, "-nrequest n number of requests to accept (default unlimited)\n");
5782ceb2
DSH
552 goto end;
553 }
554
555 if(outfile) out = BIO_new_file(outfile, "w");
556 else out = BIO_new_fp(stdout, BIO_NOCLOSE);
557
558 if(!out)
559 {
560 BIO_printf(bio_err, "Error opening output file\n");
561 goto end;
562 }
563
564 if (!req && (add_nonce != 2)) add_nonce = 0;
565
566 if (!req && reqin)
567 {
568 derbio = BIO_new_file(reqin, "rb");
569 if (!derbio)
570 {
571 BIO_printf(bio_err, "Error Opening OCSP request file\n");
572 goto end;
573 }
574 req = d2i_OCSP_REQUEST_bio(derbio, NULL);
575 BIO_free(derbio);
576 if(!req)
577 {
578 BIO_printf(bio_err, "Error reading OCSP request\n");
579 goto end;
580 }
581 }
582
ee306a13
DSH
583 if (!req && port)
584 {
534a1ed0
DSH
585 acbio = init_responder(port);
586 if (!acbio)
ee306a13 587 goto end;
534a1ed0
DSH
588 }
589
b439a746
DSH
590 if (rsignfile && !rdb)
591 {
592 if (!rkeyfile) rkeyfile = rsignfile;
593 rsigner = load_cert(bio_err, rsignfile, FORMAT_PEM,
594 NULL, e, "responder certificate");
595 if (!rsigner)
596 {
597 BIO_printf(bio_err, "Error loading responder certificate\n");
598 goto end;
599 }
600 rca_cert = load_cert(bio_err, rca_filename, FORMAT_PEM,
601 NULL, e, "CA certificate");
602 if (rcertfile)
603 {
5575f781 604 rother = load_certs(bio_err, rcertfile, FORMAT_PEM,
b439a746 605 NULL, e, "responder other certificates");
5575f781 606 if (!rother) goto end;
b439a746 607 }
da9b9724 608 rkey = load_key(bio_err, rkeyfile, FORMAT_PEM, 0, NULL, NULL,
b439a746
DSH
609 "responder private key");
610 if (!rkey)
611 goto end;
612 }
613 if(acbio)
614 BIO_printf(bio_err, "Waiting for OCSP client connections...\n");
615
534a1ed0
DSH
616 redo_accept:
617
618 if (acbio)
619 {
620 if (!do_responder(&req, &cbio, acbio, port))
621 goto end;
622 if (!req)
ee306a13
DSH
623 {
624 resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL);
625 send_ocsp_response(cbio, resp);
626 goto done_resp;
627 }
628 }
629
630 if (!req && (signfile || reqout || host || add_nonce || ridx_filename))
5782ceb2
DSH
631 {
632 BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
633 goto end;
634 }
635
73758d43 636 if (req && add_nonce) OCSP_request_add1_nonce(req, NULL, -1);
5782ceb2
DSH
637
638 if (signfile)
639 {
640 if (!keyfile) keyfile = signfile;
30b4c272
RL
641 signer = load_cert(bio_err, signfile, FORMAT_PEM,
642 NULL, e, "signer certificate");
5782ceb2
DSH
643 if (!signer)
644 {
645 BIO_printf(bio_err, "Error loading signer certificate\n");
646 goto end;
647 }
8c950429
DSH
648 if (sign_certfile)
649 {
30b4c272
RL
650 sign_other = load_certs(bio_err, sign_certfile, FORMAT_PEM,
651 NULL, e, "signer certificates");
8c950429
DSH
652 if (!sign_other) goto end;
653 }
da9b9724 654 key = load_key(bio_err, keyfile, FORMAT_PEM, 0, NULL, NULL,
30b4c272 655 "signer private key");
5782ceb2 656 if (!key)
5782ceb2 657 goto end;
8c950429 658 if (!OCSP_request_sign(req, signer, key, EVP_sha1(), sign_other, sign_flags))
5782ceb2
DSH
659 {
660 BIO_printf(bio_err, "Error signing OCSP request\n");
661 goto end;
662 }
663 }
664
ee306a13
DSH
665 if (req_text && req) OCSP_REQUEST_print(out, req, 0);
666
99889b46
DSH
667 if (reqout)
668 {
669 derbio = BIO_new_file(reqout, "wb");
670 if(!derbio)
671 {
672 BIO_printf(bio_err, "Error opening file %s\n", reqout);
673 goto end;
674 }
675 i2d_OCSP_REQUEST_bio(derbio, req);
676 BIO_free(derbio);
677 }
678
ee306a13
DSH
679 if (ridx_filename && (!rkey || !rsigner || !rca_cert))
680 {
681 BIO_printf(bio_err, "Need a responder certificate, key and CA for this operation!\n");
682 goto end;
683 }
5782ceb2 684
534a1ed0 685 if (ridx_filename && !rdb)
ee306a13 686 {
f85b68cd
RL
687 rdb = load_index(ridx_filename, NULL);
688 if (!rdb) goto end;
689 if (!index_index(rdb)) goto end;
534a1ed0
DSH
690 }
691
692 if (rdb)
693 {
ee306a13
DSH
694 i = make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey, rother, rflags, nmin, ndays);
695 if (cbio)
696 send_ocsp_response(cbio, resp);
697 }
698 else if (host)
5782ceb2 699 {
85d686e7 700#ifndef OPENSSL_NO_SOCK
5782ceb2 701 cbio = BIO_new_connect(host);
85d686e7
RL
702#else
703 BIO_printf(bio_err, "Error creating connect BIO - sockets not supported.\n");
704 goto end;
705#endif
5782ceb2
DSH
706 if (!cbio)
707 {
708 BIO_printf(bio_err, "Error creating connect BIO\n");
709 goto end;
710 }
67c18019 711 if (port) BIO_set_conn_port(cbio, port);
cdc7b8cc
DSH
712 if (use_ssl == 1)
713 {
714 BIO *sbio;
e270cf9c 715#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
cdc7b8cc 716 ctx = SSL_CTX_new(SSLv23_client_method());
e270cf9c
RL
717#elif !defined(OPENSSL_NO_SSL3)
718 ctx = SSL_CTX_new(SSLv3_client_method());
719#elif !defined(OPENSSL_NO_SSL2)
720 ctx = SSL_CTX_new(SSLv2_client_method());
721#else
722 BIO_printf(bio_err, "SSL is disabled\n");
723 goto end;
724#endif
cdc7b8cc
DSH
725 SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
726 sbio = BIO_new_ssl(ctx, 1);
727 cbio = BIO_push(sbio, cbio);
728 }
5782ceb2
DSH
729 if (BIO_do_connect(cbio) <= 0)
730 {
731 BIO_printf(bio_err, "Error connecting BIO\n");
732 goto end;
733 }
734 resp = OCSP_sendreq_bio(cbio, path, req);
cdc7b8cc 735 BIO_free_all(cbio);
5782ceb2
DSH
736 cbio = NULL;
737 if (!resp)
738 {
739 BIO_printf(bio_err, "Error querying OCSP responsder\n");
740 goto end;
741 }
742 }
743 else if (respin)
744 {
745 derbio = BIO_new_file(respin, "rb");
746 if (!derbio)
747 {
748 BIO_printf(bio_err, "Error Opening OCSP response file\n");
749 goto end;
750 }
751 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
752 BIO_free(derbio);
753 if(!resp)
754 {
755 BIO_printf(bio_err, "Error reading OCSP response\n");
756 goto end;
757 }
758
759 }
760 else
761 {
762 ret = 0;
763 goto end;
764 }
765
ee306a13
DSH
766 done_resp:
767
5782ceb2
DSH
768 if (respout)
769 {
770 derbio = BIO_new_file(respout, "wb");
771 if(!derbio)
772 {
773 BIO_printf(bio_err, "Error opening file %s\n", respout);
774 goto end;
775 }
776 i2d_OCSP_RESPONSE_bio(derbio, resp);
777 BIO_free(derbio);
778 }
779
73758d43
DSH
780 i = OCSP_response_status(resp);
781
782 if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL)
783 {
784 BIO_printf(out, "Responder Error: %s (%ld)\n",
785 OCSP_response_status_str(i), i);
786 ret = 0;
787 goto end;
788 }
789
5782ceb2
DSH
790 if (resp_text) OCSP_RESPONSE_print(out, resp, 0);
791
ee306a13
DSH
792 /* If running as responder don't verify our own response */
793 if (cbio)
534a1ed0
DSH
794 {
795 if (accept_count > 0)
796 accept_count--;
797 /* Redo if more connections needed */
798 if (accept_count)
799 {
800 BIO_free_all(cbio);
801 cbio = NULL;
802 OCSP_REQUEST_free(req);
803 req = NULL;
804 OCSP_RESPONSE_free(resp);
805 resp = NULL;
806 goto redo_accept;
807 }
ee306a13 808 goto end;
534a1ed0 809 }
ee306a13 810
534a1ed0
DSH
811 if (!store)
812 store = setup_verify(bio_err, CAfile, CApath);
99889b46
DSH
813 if (!store)
814 goto end;
8c950429
DSH
815 if (verify_certfile)
816 {
30b4c272
RL
817 verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM,
818 NULL, e, "validator certificate");
8c950429
DSH
819 if (!verify_other) goto end;
820 }
9235adbf 821
81f169e9
DSH
822 bs = OCSP_response_get1_basic(resp);
823
73758d43
DSH
824 if (!bs)
825 {
826 BIO_printf(bio_err, "Error parsing response\n");
827 goto end;
828 }
81f169e9 829
73758d43 830 if (!noverify)
81f169e9 831 {
46a58ab9 832 if (req && ((i = OCSP_check_nonce(req, bs)) <= 0))
73758d43 833 {
46a58ab9
DSH
834 if (i == -1)
835 BIO_printf(bio_err, "WARNING: no nonce in response\n");
836 else
837 {
838 BIO_printf(bio_err, "Nonce Verify error\n");
839 goto end;
840 }
73758d43
DSH
841 }
842
8c950429 843 i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
9235adbf 844 if (i < 0) i = OCSP_basic_verify(bs, NULL, store, 0);
73758d43
DSH
845
846 if(i <= 0)
847 {
848 BIO_printf(bio_err, "Response Verify Failure\n", i);
849 ERR_print_errors(bio_err);
850 }
851 else
852 BIO_printf(bio_err, "Response verify OK\n");
853
81f169e9 854 }
73758d43 855
f1965221 856 if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage))
73758d43 857 goto end;
81f169e9 858
5782ceb2
DSH
859 ret = 0;
860
861end:
862 ERR_print_errors(bio_err);
863 X509_free(signer);
81f169e9 864 X509_STORE_free(store);
5782ceb2 865 EVP_PKEY_free(key);
ee306a13 866 EVP_PKEY_free(rkey);
5782ceb2
DSH
867 X509_free(issuer);
868 X509_free(cert);
ee306a13
DSH
869 X509_free(rsigner);
870 X509_free(rca_cert);
f85b68cd 871 free_index(rdb);
cdc7b8cc 872 BIO_free_all(cbio);
534a1ed0 873 BIO_free_all(acbio);
5782ceb2
DSH
874 BIO_free(out);
875 OCSP_REQUEST_free(req);
876 OCSP_RESPONSE_free(resp);
81f169e9 877 OCSP_BASICRESP_free(bs);
73758d43
DSH
878 sk_free(reqnames);
879 sk_OCSP_CERTID_free(ids);
8c950429
DSH
880 sk_X509_pop_free(sign_other, X509_free);
881 sk_X509_pop_free(verify_other, X509_free);
5782ceb2 882
67c18019
DSH
883 if (use_ssl != -1)
884 {
885 OPENSSL_free(host);
886 OPENSSL_free(port);
887 OPENSSL_free(path);
cdc7b8cc 888 SSL_CTX_free(ctx);
67c18019
DSH
889 }
890
1c3e4a36 891 OPENSSL_EXIT(ret);
5782ceb2
DSH
892}
893
73758d43
DSH
894static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
895 STACK_OF(OCSP_CERTID) *ids)
5782ceb2
DSH
896 {
897 OCSP_CERTID *id;
898 if(!issuer)
899 {
900 BIO_printf(bio_err, "No issuer certificate specified\n");
901 return 0;
902 }
903 if(!*req) *req = OCSP_REQUEST_new();
904 if(!*req) goto err;
905 id = OCSP_cert_to_id(NULL, cert, issuer);
73758d43 906 if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
5782ceb2
DSH
907 if(!OCSP_request_add0_id(*req, id)) goto err;
908 return 1;
909
910 err:
911 BIO_printf(bio_err, "Error Creating OCSP request\n");
912 return 0;
913 }
914
73758d43
DSH
915static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer,
916 STACK_OF(OCSP_CERTID) *ids)
5782ceb2
DSH
917 {
918 OCSP_CERTID *id;
919 X509_NAME *iname;
920 ASN1_BIT_STRING *ikey;
921 ASN1_INTEGER *sno;
922 if(!issuer)
923 {
924 BIO_printf(bio_err, "No issuer certificate specified\n");
925 return 0;
926 }
927 if(!*req) *req = OCSP_REQUEST_new();
928 if(!*req) goto err;
929 iname = X509_get_subject_name(issuer);
88ce56f8 930 ikey = X509_get0_pubkey_bitstr(issuer);
5782ceb2
DSH
931 sno = s2i_ASN1_INTEGER(NULL, serial);
932 if(!sno)
933 {
934 BIO_printf(bio_err, "Error converting serial number %s\n", serial);
935 return 0;
936 }
937 id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno);
938 ASN1_INTEGER_free(sno);
73758d43 939 if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
5782ceb2
DSH
940 if(!OCSP_request_add0_id(*req, id)) goto err;
941 return 1;
942
943 err:
944 BIO_printf(bio_err, "Error Creating OCSP request\n");
945 return 0;
946 }
73758d43
DSH
947
948static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
f1965221
DSH
949 STACK *names, STACK_OF(OCSP_CERTID) *ids,
950 long nsec, long maxage)
73758d43
DSH
951 {
952 OCSP_CERTID *id;
953 char *name;
954 int i;
955
956 int status, reason;
957
958 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
959
960 if (!bs || !req || !sk_num(names) || !sk_OCSP_CERTID_num(ids))
961 return 1;
962
963 for (i = 0; i < sk_OCSP_CERTID_num(ids); i++)
964 {
965 id = sk_OCSP_CERTID_value(ids, i);
966 name = sk_value(names, i);
967 BIO_printf(out, "%s: ", name);
968
969 if(!OCSP_resp_find_status(bs, id, &status, &reason,
970 &rev, &thisupd, &nextupd))
971 {
972 BIO_puts(out, "ERROR: No Status found.\n");
973 continue;
974 }
f1965221
DSH
975
976 /* Check validity: if invalid write to output BIO so we
977 * know which response this refers to.
978 */
979 if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage))
980 {
981 BIO_puts(out, "WARNING: Status times invalid.\n");
982 ERR_print_errors(out);
983 }
73758d43
DSH
984 BIO_printf(out, "%s\n", OCSP_cert_status_str(status));
985
986 BIO_puts(out, "\tThis Update: ");
987 ASN1_GENERALIZEDTIME_print(out, thisupd);
988 BIO_puts(out, "\n");
989
990 if(nextupd)
991 {
992 BIO_puts(out, "\tNext Update: ");
569afce4 993 ASN1_GENERALIZEDTIME_print(out, nextupd);
73758d43
DSH
994 BIO_puts(out, "\n");
995 }
996
997 if (status != V_OCSP_CERTSTATUS_REVOKED)
998 continue;
999
8e8972bb 1000 if (reason != -1)
73758d43
DSH
1001 BIO_printf(out, "\tReason: %s\n",
1002 OCSP_crl_reason_str(reason));
1003
1004 BIO_puts(out, "\tRevocation Time: ");
1005 ASN1_GENERALIZEDTIME_print(out, rev);
1006 BIO_puts(out, "\n");
1007 }
1008
1009 return 1;
1010 }
1011
ee306a13 1012
f85b68cd 1013static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, CA_DB *db,
ee306a13
DSH
1014 X509 *ca, X509 *rcert, EVP_PKEY *rkey,
1015 STACK_OF(X509) *rother, unsigned long flags,
1016 int nmin, int ndays)
1017 {
1018 ASN1_TIME *thisupd = NULL, *nextupd = NULL;
1019 OCSP_CERTID *cid, *ca_id = NULL;
1020 OCSP_BASICRESP *bs = NULL;
1021 int i, id_count, ret = 1;
1022
1023
1024 id_count = OCSP_request_onereq_count(req);
1025
1026 if (id_count <= 0)
1027 {
1028 *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL);
1029 goto end;
1030 }
1031
1032 ca_id = OCSP_cert_to_id(EVP_sha1(), NULL, ca);
1033
1034 bs = OCSP_BASICRESP_new();
1035 thisupd = X509_gmtime_adj(NULL, 0);
1036 if (ndays != -1)
1037 nextupd = X509_gmtime_adj(NULL, nmin * 60 + ndays * 3600 * 24 );
1038
1039 /* Examine each certificate id in the request */
1040 for (i = 0; i < id_count; i++)
1041 {
1042 OCSP_ONEREQ *one;
1043 ASN1_INTEGER *serial;
1044 char **inf;
1045 one = OCSP_request_onereq_get0(req, i);
1046 cid = OCSP_onereq_get0_id(one);
1047 /* Is this request about our CA? */
1048 if (OCSP_id_issuer_cmp(ca_id, cid))
1049 {
1050 OCSP_basic_add1_status(bs, cid,
1051 V_OCSP_CERTSTATUS_UNKNOWN,
1052 0, NULL,
1053 thisupd, nextupd);
1054 continue;
1055 }
1056 OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid);
1057 inf = lookup_serial(db, serial);
1058 if (!inf)
1059 OCSP_basic_add1_status(bs, cid,
1060 V_OCSP_CERTSTATUS_UNKNOWN,
1061 0, NULL,
1062 thisupd, nextupd);
1063 else if (inf[DB_type][0] == DB_TYPE_VAL)
1064 OCSP_basic_add1_status(bs, cid,
1065 V_OCSP_CERTSTATUS_GOOD,
1066 0, NULL,
1067 thisupd, nextupd);
1068 else if (inf[DB_type][0] == DB_TYPE_REV)
1069 {
1070 ASN1_OBJECT *inst = NULL;
1071 ASN1_TIME *revtm = NULL;
1072 ASN1_GENERALIZEDTIME *invtm = NULL;
1073 OCSP_SINGLERESP *single;
1074 int reason = -1;
1075 unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]);
1076 single = OCSP_basic_add1_status(bs, cid,
1077 V_OCSP_CERTSTATUS_REVOKED,
1078 reason, revtm,
1079 thisupd, nextupd);
1080 if (invtm)
1081 OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date, invtm, 0, 0);
1082 else if (inst)
1083 OCSP_SINGLERESP_add1_ext_i2d(single, NID_hold_instruction_code, inst, 0, 0);
1084 ASN1_OBJECT_free(inst);
1085 ASN1_TIME_free(revtm);
1086 ASN1_GENERALIZEDTIME_free(invtm);
1087 }
1088 }
1089
1090 OCSP_copy_nonce(bs, req);
1091
1092 OCSP_basic_sign(bs, rcert, rkey, EVP_sha1(), rother, flags);
1093
1094 *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs);
1095
1096 end:
1097 ASN1_TIME_free(thisupd);
1098 ASN1_TIME_free(nextupd);
1099 OCSP_CERTID_free(ca_id);
1100 OCSP_BASICRESP_free(bs);
1101 return ret;
1102
1103 }
1104
f85b68cd 1105static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
ee306a13
DSH
1106 {
1107 int i;
1108 BIGNUM *bn = NULL;
1109 char *itmp, *row[DB_NUMBER],**rrow;
1110 for (i = 0; i < DB_NUMBER; i++) row[i] = NULL;
1111 bn = ASN1_INTEGER_to_BN(ser,NULL);
2245cd87
RL
1112 if (BN_is_zero(bn))
1113 itmp = BUF_strdup("00");
1114 else
1115 itmp = BN_bn2hex(bn);
ee306a13
DSH
1116 row[DB_serial] = itmp;
1117 BN_free(bn);
f85b68cd 1118 rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
ee306a13
DSH
1119 OPENSSL_free(itmp);
1120 return rrow;
1121 }
1122
1123/* Quick and dirty OCSP server: read in and parse input request */
1124
534a1ed0 1125static BIO *init_responder(char *port)
ee306a13 1126 {
534a1ed0 1127 BIO *acbio = NULL, *bufbio = NULL;
ee306a13
DSH
1128 bufbio = BIO_new(BIO_f_buffer());
1129 if (!bufbio)
1130 goto err;
85d686e7 1131#ifndef OPENSSL_NO_SOCK
ee306a13 1132 acbio = BIO_new_accept(port);
85d686e7
RL
1133#else
1134 BIO_printf(bio_err, "Error setting up accept BIO - sockets not supported.\n");
1135#endif
ee306a13
DSH
1136 if (!acbio)
1137 goto err;
1138 BIO_set_accept_bios(acbio, bufbio);
1139 bufbio = NULL;
1140
1141 if (BIO_do_accept(acbio) <= 0)
1142 {
1143 BIO_printf(bio_err, "Error setting up accept BIO\n");
1144 ERR_print_errors(bio_err);
1145 goto err;
1146 }
534a1ed0
DSH
1147
1148 return acbio;
1149
1150 err:
1151 BIO_free_all(acbio);
1152 BIO_free(bufbio);
1153 return NULL;
1154 }
ee306a13 1155
534a1ed0
DSH
1156static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, char *port)
1157 {
1158 int have_post = 0, len;
1159 OCSP_REQUEST *req = NULL;
1160 char inbuf[1024];
1161 BIO *cbio = NULL;
ee306a13
DSH
1162
1163 if (BIO_do_accept(acbio) <= 0)
1164 {
1165 BIO_printf(bio_err, "Error accepting connection\n");
1166 ERR_print_errors(bio_err);
534a1ed0 1167 return 0;
ee306a13
DSH
1168 }
1169
ee306a13 1170 cbio = BIO_pop(acbio);
534a1ed0 1171 *pcbio = cbio;
ee306a13
DSH
1172
1173 for(;;)
1174 {
54a656ef 1175 len = BIO_gets(cbio, inbuf, sizeof inbuf);
534a1ed0
DSH
1176 if (len <= 0)
1177 return 1;
ee306a13
DSH
1178 /* Look for "POST" signalling start of query */
1179 if (!have_post)
1180 {
1181 if(strncmp(inbuf, "POST", 4))
1182 {
1183 BIO_printf(bio_err, "Invalid request\n");
534a1ed0 1184 return 1;
ee306a13
DSH
1185 }
1186 have_post = 1;
1187 }
1188 /* Look for end of headers */
1189 if ((inbuf[0] == '\r') || (inbuf[0] == '\n'))
1190 break;
1191 }
1192
1193 /* Try to read OCSP request */
1194
1195 req = d2i_OCSP_REQUEST_bio(cbio, NULL);
1196
ee306a13
DSH
1197 if (!req)
1198 {
1199 BIO_printf(bio_err, "Error parsing OCSP request\n");
1200 ERR_print_errors(bio_err);
1201 }
1202
534a1ed0
DSH
1203 *preq = req;
1204
1205 return 1;
ee306a13 1206
ee306a13
DSH
1207 }
1208
1209static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
1210 {
1211 char http_resp[] =
1212 "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n"
1213 "Content-Length: %d\r\n\r\n";
1214 if (!cbio)
1215 return 0;
1216 BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL));
1217 i2d_OCSP_RESPONSE_bio(cbio, resp);
1218 BIO_flush(cbio);
1219 return 1;
1220 }
1221
85d686e7 1222#endif