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