]> git.ipfire.org Git - thirdparty/openssl.git/blame - apps/ocsp.c
Fix some Typos and indents
[thirdparty/openssl.git] / apps / ocsp.c
CommitLineData
0f113f3e 1/*
2234212c 2 * Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved.
5782ceb2 3 *
846e33c7
RS
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
5782ceb2
DSH
8 */
9
3e41ac35
MC
10#include <openssl/opensslconf.h>
11
12#ifdef OPENSSL_NO_OCSP
13NON_EMPTY_TRANSLATION_UNIT
14#else
0f113f3e
MC
15# ifdef OPENSSL_SYS_VMS
16# define _XOPEN_SOURCE_EXTENDED/* So fd_set and friends get properly defined
17 * on OpenVMS */
18# endif
19
20# define USE_SOCKETS
21
22# include <stdio.h>
23# include <stdlib.h>
24# include <string.h>
25# include <time.h>
98cd49db 26# include <ctype.h>
3e41ac35
MC
27
28/* Needs to be included before the openssl headers */
29# include "apps.h"
0f113f3e
MC
30# include <openssl/e_os2.h>
31# include <openssl/crypto.h>
32# include <openssl/err.h>
33# include <openssl/ssl.h>
34# include <openssl/evp.h>
35# include <openssl/bn.h>
36# include <openssl/x509v3.h>
37
38# if defined(NETWARE_CLIB)
eef0c1f3 39# ifdef NETWARE_BSDSOCK
0f113f3e
MC
40# include <sys/socket.h>
41# include <sys/bsdskt.h>
eef0c1f3 42# else
0f113f3e 43# include <novsock2.h>
eef0c1f3 44# endif
0f113f3e 45# elif defined(NETWARE_LIBC)
eef0c1f3 46# ifdef NETWARE_BSDSOCK
0f113f3e 47# include <sys/select.h>
eef0c1f3 48# else
0f113f3e 49# include <novsock2.h>
eef0c1f3 50# endif
0f113f3e 51# endif
f1965221 52
0f113f3e 53/* Maximum leeway in validity period: default 5 minutes */
7e1b7485 54# define MAX_VALIDITY_PERIOD (5 * 60)
0f113f3e
MC
55
56static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert,
57 const EVP_MD *cert_id_md, X509 *issuer,
58 STACK_OF(OCSP_CERTID) *ids);
59static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
60 const EVP_MD *cert_id_md, X509 *issuer,
61 STACK_OF(OCSP_CERTID) *ids);
7e1b7485 62static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
0f113f3e
MC
63 STACK_OF(OPENSSL_STRING) *names,
64 STACK_OF(OCSP_CERTID) *ids, long nsec,
65 long maxage);
7e1b7485 66static void make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req,
3bb0f989 67 CA_DB *db, STACK_OF(X509) *ca, X509 *rcert,
0f113f3e
MC
68 EVP_PKEY *rkey, const EVP_MD *md,
69 STACK_OF(X509) *rother, unsigned long flags,
70 int nmin, int ndays, int badsig);
ee306a13 71
f85b68cd 72static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser);
c45a48c1 73static BIO *init_responder(const char *port);
a773b52a 74static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio);
ee306a13 75static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp);
f9e55034
MC
76
77# ifndef OPENSSL_NO_SOCK
76e0cd12
DSH
78static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host,
79 const char *path,
0f113f3e
MC
80 const STACK_OF(CONF_VALUE) *headers,
81 OCSP_REQUEST *req, int req_timeout);
f9e55034 82# endif
ee306a13 83
7e1b7485
RS
84typedef enum OPTION_choice {
85 OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
86 OPT_OUTFILE, OPT_TIMEOUT, OPT_URL, OPT_HOST, OPT_PORT,
87 OPT_IGNORE_ERR, OPT_NOVERIFY, OPT_NONCE, OPT_NO_NONCE,
88 OPT_RESP_NO_CERTS, OPT_RESP_KEY_ID, OPT_NO_CERTS,
89 OPT_NO_SIGNATURE_VERIFY, OPT_NO_CERT_VERIFY, OPT_NO_CHAIN,
90 OPT_NO_CERT_CHECKS, OPT_NO_EXPLICIT, OPT_TRUST_OTHER,
91 OPT_NO_INTERN, OPT_BADSIG, OPT_TEXT, OPT_REQ_TEXT, OPT_RESP_TEXT,
92 OPT_REQIN, OPT_RESPIN, OPT_SIGNER, OPT_VAFILE, OPT_SIGN_OTHER,
2b6bcb70 93 OPT_VERIFY_OTHER, OPT_CAFILE, OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH,
7e1b7485 94 OPT_VALIDITY_PERIOD, OPT_STATUS_AGE, OPT_SIGNKEY, OPT_REQOUT,
c6724060 95 OPT_RESPOUT, OPT_PATH, OPT_ISSUER, OPT_CERT, OPT_SERIAL,
7e1b7485
RS
96 OPT_INDEX, OPT_CA, OPT_NMIN, OPT_REQUEST, OPT_NDAYS, OPT_RSIGNER,
97 OPT_RKEY, OPT_ROTHER, OPT_RMD, OPT_HEADER,
98 OPT_V_ENUM,
99 OPT_MD
100} OPTION_CHOICE;
101
44c83ebd 102const OPTIONS ocsp_options[] = {
7e1b7485
RS
103 {"help", OPT_HELP, '-', "Display this summary"},
104 {"out", OPT_OUTFILE, '>', "Output filename"},
9a13bb38
RS
105 {"timeout", OPT_TIMEOUT, 'p',
106 "Connection timeout (in seconds) to the OCSP responder"},
7e1b7485 107 {"url", OPT_URL, 's', "Responder URL"},
ceab33e2 108 {"host", OPT_HOST, 's', "TCP/IP hostname:port to connect to"},
7e1b7485 109 {"port", OPT_PORT, 'p', "Port to run responder on"},
12d56b29
F
110 {"ignore_err", OPT_IGNORE_ERR, '-',
111 "Ignore Error response from OCSP responder, and retry "},
7e1b7485
RS
112 {"noverify", OPT_NOVERIFY, '-', "Don't verify response at all"},
113 {"nonce", OPT_NONCE, '-', "Add OCSP nonce to request"},
114 {"no_nonce", OPT_NO_NONCE, '-', "Don't add OCSP nonce to request"},
115 {"resp_no_certs", OPT_RESP_NO_CERTS, '-',
116 "Don't include any certificates in response"},
117 {"resp_key_id", OPT_RESP_KEY_ID, '-',
ceab33e2 118 "Identify response by signing certificate key ID"},
7e1b7485
RS
119 {"no_certs", OPT_NO_CERTS, '-',
120 "Don't include any certificates in signed request"},
121 {"no_signature_verify", OPT_NO_SIGNATURE_VERIFY, '-',
122 "Don't check signature on response"},
123 {"no_cert_verify", OPT_NO_CERT_VERIFY, '-',
124 "Don't check signing certificate"},
125 {"no_chain", OPT_NO_CHAIN, '-', "Don't chain verify response"},
126 {"no_cert_checks", OPT_NO_CERT_CHECKS, '-',
127 "Don't do additional checks on signing certificate"},
12d56b29
F
128 {"no_explicit", OPT_NO_EXPLICIT, '-',
129 "Do not explicitly check the chain, just verify the root"},
7e1b7485
RS
130 {"trust_other", OPT_TRUST_OTHER, '-',
131 "Don't verify additional certificates"},
132 {"no_intern", OPT_NO_INTERN, '-',
133 "Don't search certificates contained in response for signer"},
16e1b281
F
134 {"badsig", OPT_BADSIG, '-',
135 "Corrupt last byte of loaded OSCP response signature (for test)"},
7e1b7485
RS
136 {"text", OPT_TEXT, '-', "Print text form of request and response"},
137 {"req_text", OPT_REQ_TEXT, '-', "Print text form of request"},
138 {"resp_text", OPT_RESP_TEXT, '-', "Print text form of response"},
139 {"reqin", OPT_REQIN, 's', "File with the DER-encoded request"},
140 {"respin", OPT_RESPIN, 's', "File with the DER-encoded response"},
141 {"signer", OPT_SIGNER, '<', "Certificate to sign OCSP request with"},
142 {"VAfile", OPT_VAFILE, '<', "Validator certificates file"},
143 {"sign_other", OPT_SIGN_OTHER, '<',
144 "Additional certificates to include in signed request"},
145 {"verify_other", OPT_VERIFY_OTHER, '<',
146 "Additional certificates to search for signer"},
147 {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
148 {"CApath", OPT_CAPATH, '<', "Trusted certificates directory"},
2b6bcb70
MC
149 {"no-CAfile", OPT_NOCAFILE, '-',
150 "Do not load the default certificates file"},
151 {"no-CApath", OPT_NOCAPATH, '-',
152 "Do not load certificates from the default certificates directory"},
7e1b7485
RS
153 {"validity_period", OPT_VALIDITY_PERIOD, 'u',
154 "Maximum validity discrepancy in seconds"},
155 {"status_age", OPT_STATUS_AGE, 'p', "Maximum status age in seconds"},
156 {"signkey", OPT_SIGNKEY, 's', "Private key to sign OCSP request with"},
157 {"reqout", OPT_REQOUT, 's', "Output file for the DER-encoded request"},
158 {"respout", OPT_RESPOUT, 's', "Output file for the DER-encoded response"},
159 {"path", OPT_PATH, 's', "Path to use in OCSP request"},
c6724060 160 {"issuer", OPT_ISSUER, '<', "Issuer certificate"},
7e1b7485 161 {"cert", OPT_CERT, '<', "Certificate to check"},
16e1b281 162 {"serial", OPT_SERIAL, 's', "Serial number to check"},
7e1b7485
RS
163 {"index", OPT_INDEX, '<', "Certificate status index file"},
164 {"CA", OPT_CA, '<', "CA certificate"},
165 {"nmin", OPT_NMIN, 'p', "Number of minutes before next update"},
166 {"nrequest", OPT_REQUEST, 'p',
167 "Number of requests to accept (default unlimited)"},
168 {"ndays", OPT_NDAYS, 'p', "Number of days before next update"},
169 {"rsigner", OPT_RSIGNER, '<',
0ad69cd6 170 "Responder certificate to sign responses with"},
7e1b7485
RS
171 {"rkey", OPT_RKEY, '<', "Responder key to sign responses with"},
172 {"rother", OPT_ROTHER, '<', "Other certificates to include in response"},
16e1b281 173 {"rmd", OPT_RMD, 's', "Digest Algorithm to use in signature of OCSP response"},
7e1b7485 174 {"header", OPT_HEADER, 's', "key=value header to add"},
16e1b281 175 {"", OPT_MD, '-', "Any supported digest algorithm (sha1,sha256, ... )"},
7e1b7485
RS
176 OPT_V_OPTIONS,
177 {NULL}
178};
179
180int ocsp_main(int argc, char **argv)
0f113f3e 181{
7e1b7485
RS
182 BIO *acbio = NULL, *cbio = NULL, *derbio = NULL, *out = NULL;
183 const EVP_MD *cert_id_md = NULL, *rsign_md = NULL;
6302bbd2 184 int trailing_md = 0;
7e1b7485
RS
185 CA_DB *rdb = NULL;
186 EVP_PKEY *key = NULL, *rkey = NULL;
187 OCSP_BASICRESP *bs = NULL;
0f113f3e
MC
188 OCSP_REQUEST *req = NULL;
189 OCSP_RESPONSE *resp = NULL;
7e1b7485
RS
190 STACK_OF(CONF_VALUE) *headers = NULL;
191 STACK_OF(OCSP_CERTID) *ids = NULL;
192 STACK_OF(OPENSSL_STRING) *reqnames = NULL;
193 STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL;
88806cfc 194 STACK_OF(X509) *issuers = NULL;
3bb0f989
TS
195 X509 *issuer = NULL, *cert = NULL;
196 STACK_OF(X509) *rca_cert = NULL;
0f113f3e 197 X509 *signer = NULL, *rsigner = NULL;
0f113f3e
MC
198 X509_STORE *store = NULL;
199 X509_VERIFY_PARAM *vpm = NULL;
cc696296
F
200 const char *CAfile = NULL, *CApath = NULL;
201 char *header, *value;
7e1b7485
RS
202 char *host = NULL, *port = NULL, *path = "/", *outfile = NULL;
203 char *rca_filename = NULL, *reqin = NULL, *respin = NULL;
204 char *reqout = NULL, *respout = NULL, *ridx_filename = NULL;
205 char *rsignfile = NULL, *rkeyfile = NULL;
0f113f3e 206 char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
7e1b7485
RS
207 char *signfile = NULL, *keyfile = NULL;
208 char *thost = NULL, *tport = NULL, *tpath = NULL;
2b6bcb70 209 int noCAfile = 0, noCApath = 0;
7e1b7485
RS
210 int accept_count = -1, add_nonce = 1, noverify = 0, use_ssl = -1;
211 int vpmtouched = 0, badsig = 0, i, ignore_err = 0, nmin = 0, ndays = -1;
f9e55034
MC
212 int req_text = 0, resp_text = 0, ret = 1;
213#ifndef OPENSSL_NO_SOCK
214 int req_timeout = -1;
215#endif
7e1b7485 216 long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
0f113f3e 217 unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
7e1b7485
RS
218 OPTION_CHOICE o;
219 char *prog;
0f113f3e 220
0f113f3e 221 reqnames = sk_OPENSSL_STRING_new_null();
2234212c 222 if (reqnames == NULL)
7e1b7485 223 goto end;
0f113f3e 224 ids = sk_OCSP_CERTID_new_null();
2234212c 225 if (ids == NULL)
7e1b7485
RS
226 goto end;
227 if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
228 return 1;
229
230 prog = opt_init(argc, argv, ocsp_options);
231 while ((o = opt_next()) != OPT_EOF) {
232 switch (o) {
233 case OPT_EOF:
234 case OPT_ERR:
235 opthelp:
236 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
237 goto end;
238 case OPT_HELP:
239 ret = 0;
240 opt_help(ocsp_options);
241 goto end;
242 case OPT_OUTFILE:
243 outfile = opt_arg();
244 break;
245 case OPT_TIMEOUT:
f9e55034 246#ifndef OPENSSL_NO_SOCK
7e1b7485 247 req_timeout = atoi(opt_arg());
f9e55034 248#endif
7e1b7485
RS
249 break;
250 case OPT_URL:
b548a1f1
RS
251 OPENSSL_free(thost);
252 OPENSSL_free(tport);
253 OPENSSL_free(tpath);
4b8d8e2a 254 thost = tport = tpath = NULL;
7e1b7485
RS
255 if (!OCSP_parse_url(opt_arg(), &host, &port, &path, &use_ssl)) {
256 BIO_printf(bio_err, "%s Error parsing URL\n", prog);
257 goto end;
258 }
259 thost = host;
260 tport = port;
261 tpath = path;
262 break;
263 case OPT_HOST:
264 host = opt_arg();
265 break;
266 case OPT_PORT:
267 port = opt_arg();
268 break;
269 case OPT_IGNORE_ERR:
0f113f3e 270 ignore_err = 1;
7e1b7485
RS
271 break;
272 case OPT_NOVERIFY:
0f113f3e 273 noverify = 1;
7e1b7485
RS
274 break;
275 case OPT_NONCE:
0f113f3e 276 add_nonce = 2;
7e1b7485
RS
277 break;
278 case OPT_NO_NONCE:
0f113f3e 279 add_nonce = 0;
7e1b7485
RS
280 break;
281 case OPT_RESP_NO_CERTS:
0f113f3e 282 rflags |= OCSP_NOCERTS;
7e1b7485
RS
283 break;
284 case OPT_RESP_KEY_ID:
0f113f3e 285 rflags |= OCSP_RESPID_KEY;
7e1b7485
RS
286 break;
287 case OPT_NO_CERTS:
0f113f3e 288 sign_flags |= OCSP_NOCERTS;
7e1b7485
RS
289 break;
290 case OPT_NO_SIGNATURE_VERIFY:
0f113f3e 291 verify_flags |= OCSP_NOSIGS;
7e1b7485
RS
292 break;
293 case OPT_NO_CERT_VERIFY:
0f113f3e 294 verify_flags |= OCSP_NOVERIFY;
7e1b7485
RS
295 break;
296 case OPT_NO_CHAIN:
0f113f3e 297 verify_flags |= OCSP_NOCHAIN;
7e1b7485
RS
298 break;
299 case OPT_NO_CERT_CHECKS:
0f113f3e 300 verify_flags |= OCSP_NOCHECKS;
7e1b7485
RS
301 break;
302 case OPT_NO_EXPLICIT:
0f113f3e 303 verify_flags |= OCSP_NOEXPLICIT;
7e1b7485
RS
304 break;
305 case OPT_TRUST_OTHER:
0f113f3e 306 verify_flags |= OCSP_TRUSTOTHER;
7e1b7485
RS
307 break;
308 case OPT_NO_INTERN:
0f113f3e 309 verify_flags |= OCSP_NOINTERN;
7e1b7485
RS
310 break;
311 case OPT_BADSIG:
0f113f3e 312 badsig = 1;
7e1b7485
RS
313 break;
314 case OPT_TEXT:
315 req_text = resp_text = 1;
316 break;
317 case OPT_REQ_TEXT:
0f113f3e 318 req_text = 1;
7e1b7485
RS
319 break;
320 case OPT_RESP_TEXT:
0f113f3e 321 resp_text = 1;
7e1b7485
RS
322 break;
323 case OPT_REQIN:
324 reqin = opt_arg();
325 break;
326 case OPT_RESPIN:
327 respin = opt_arg();
328 break;
329 case OPT_SIGNER:
330 signfile = opt_arg();
331 break;
332 case OPT_VAFILE:
333 verify_certfile = opt_arg();
334 verify_flags |= OCSP_TRUSTOTHER;
335 break;
336 case OPT_SIGN_OTHER:
337 sign_certfile = opt_arg();
338 break;
339 case OPT_VERIFY_OTHER:
340 verify_certfile = opt_arg();
341 break;
342 case OPT_CAFILE:
343 CAfile = opt_arg();
344 break;
345 case OPT_CAPATH:
346 CApath = opt_arg();
347 break;
2b6bcb70
MC
348 case OPT_NOCAFILE:
349 noCAfile = 1;
350 break;
351 case OPT_NOCAPATH:
352 noCApath = 1;
353 break;
7e1b7485
RS
354 case OPT_V_CASES:
355 if (!opt_verify(o, vpm))
0f113f3e 356 goto end;
7e1b7485
RS
357 vpmtouched++;
358 break;
359 case OPT_VALIDITY_PERIOD:
360 opt_long(opt_arg(), &nsec);
361 break;
362 case OPT_STATUS_AGE:
363 opt_long(opt_arg(), &maxage);
364 break;
365 case OPT_SIGNKEY:
366 keyfile = opt_arg();
367 break;
368 case OPT_REQOUT:
369 reqout = opt_arg();
370 break;
371 case OPT_RESPOUT:
372 respout = opt_arg();
373 break;
374 case OPT_PATH:
375 path = opt_arg();
376 break;
c6724060 377 case OPT_ISSUER:
a773b52a 378 issuer = load_cert(opt_arg(), FORMAT_PEM, "issuer certificate");
c6724060
RS
379 if (issuer == NULL)
380 goto end;
bb7fc98c
DSH
381 if (issuers == NULL) {
382 if ((issuers = sk_X509_new_null()) == NULL)
383 goto end;
384 }
c6724060
RS
385 sk_X509_push(issuers, issuer);
386 break;
7e1b7485
RS
387 case OPT_CERT:
388 X509_free(cert);
a773b52a 389 cert = load_cert(opt_arg(), FORMAT_PEM, "certificate");
7e1b7485
RS
390 if (cert == NULL)
391 goto end;
392 if (cert_id_md == NULL)
393 cert_id_md = EVP_sha1();
394 if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids))
395 goto end;
396 if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
397 goto end;
6302bbd2 398 trailing_md = 0;
7e1b7485
RS
399 break;
400 case OPT_SERIAL:
401 if (cert_id_md == NULL)
402 cert_id_md = EVP_sha1();
403 if (!add_ocsp_serial(&req, opt_arg(), cert_id_md, issuer, ids))
404 goto end;
405 if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
406 goto end;
6302bbd2 407 trailing_md = 0;
7e1b7485
RS
408 break;
409 case OPT_INDEX:
410 ridx_filename = opt_arg();
411 break;
412 case OPT_CA:
413 rca_filename = opt_arg();
414 break;
415 case OPT_NMIN:
416 opt_int(opt_arg(), &nmin);
0f113f3e
MC
417 if (ndays == -1)
418 ndays = 0;
7e1b7485
RS
419 break;
420 case OPT_REQUEST:
421 opt_int(opt_arg(), &accept_count);
422 break;
423 case OPT_NDAYS:
424 ndays = atoi(opt_arg());
425 break;
426 case OPT_RSIGNER:
427 rsignfile = opt_arg();
428 break;
429 case OPT_RKEY:
430 rkeyfile = opt_arg();
431 break;
432 case OPT_ROTHER:
433 rcertfile = opt_arg();
434 break;
16e1b281 435 case OPT_RMD: /* Response MessageDigest */
7e1b7485
RS
436 if (!opt_md(opt_arg(), &rsign_md))
437 goto end;
438 break;
439 case OPT_HEADER:
440 header = opt_arg();
441 value = strchr(header, '=');
442 if (value == NULL) {
443 BIO_printf(bio_err, "Missing = in header key=value\n");
444 goto opthelp;
445 }
446 *value++ = '\0';
447 if (!X509V3_add_value(header, value, &headers))
448 goto end;
449 break;
450 case OPT_MD:
6302bbd2 451 if (trailing_md) {
7e1b7485
RS
452 BIO_printf(bio_err,
453 "%s: Digest must be before -cert or -serial\n",
454 prog);
455 goto opthelp;
456 }
457 if (!opt_md(opt_unknown(), &cert_id_md))
458 goto opthelp;
6302bbd2 459 trailing_md = 1;
7e1b7485 460 break;
0f113f3e 461 }
0f113f3e 462 }
6302bbd2
DSH
463
464 if (trailing_md) {
465 BIO_printf(bio_err, "%s: Digest must be before -cert or -serial\n",
466 prog);
467 goto opthelp;
468 }
7e1b7485 469 argc = opt_num_rest();
03358517
KR
470 if (argc != 0)
471 goto opthelp;
0f113f3e
MC
472
473 /* Have we anything to do? */
2234212c
PY
474 if (req == NULL&& reqin == NULL
475 && respin == NULL && !(port != NULL && ridx_filename != NULL))
7e1b7485 476 goto opthelp;
0f113f3e 477
bdd58d98 478 out = bio_open_default(outfile, 'w', FORMAT_TEXT);
7e1b7485 479 if (out == NULL)
0f113f3e 480 goto end;
0f113f3e 481
2234212c 482 if (req == NULL && (add_nonce != 2))
0f113f3e
MC
483 add_nonce = 0;
484
2234212c 485 if (req == NULL && reqin != NULL) {
bdd58d98 486 derbio = bio_open_default(reqin, 'r', FORMAT_ASN1);
7e1b7485 487 if (derbio == NULL)
0f113f3e 488 goto end;
0f113f3e
MC
489 req = d2i_OCSP_REQUEST_bio(derbio, NULL);
490 BIO_free(derbio);
2234212c 491 if (req == NULL) {
0f113f3e
MC
492 BIO_printf(bio_err, "Error reading OCSP request\n");
493 goto end;
494 }
495 }
496
2234212c 497 if (req == NULL && port != NULL) {
0f113f3e 498 acbio = init_responder(port);
2234212c 499 if (acbio == NULL)
0f113f3e
MC
500 goto end;
501 }
502
2234212c
PY
503 if (rsignfile != NULL) {
504 if (rkeyfile == NULL)
0f113f3e 505 rkeyfile = rsignfile;
a773b52a 506 rsigner = load_cert(rsignfile, FORMAT_PEM, "responder certificate");
2234212c 507 if (rsigner == NULL) {
0f113f3e
MC
508 BIO_printf(bio_err, "Error loading responder certificate\n");
509 goto end;
510 }
3bb0f989
TS
511 if (!load_certs(rca_filename, &rca_cert, FORMAT_PEM,
512 NULL, "CA certificate"))
513 goto end;
2234212c 514 if (rcertfile != NULL) {
a773b52a 515 if (!load_certs(rcertfile, &rother, FORMAT_PEM, NULL,
0996dc54 516 "responder other certificates"))
0f113f3e
MC
517 goto end;
518 }
7e1b7485 519 rkey = load_key(rkeyfile, FORMAT_PEM, 0, NULL, NULL,
0f113f3e 520 "responder private key");
2234212c 521 if (rkey == NULL)
0f113f3e
MC
522 goto end;
523 }
2234212c 524 if (acbio != NULL)
0f113f3e
MC
525 BIO_printf(bio_err, "Waiting for OCSP client connections...\n");
526
2234212c 527redo_accept:
0f113f3e 528
2234212c 529 if (acbio != NULL) {
a773b52a 530 if (!do_responder(&req, &cbio, acbio))
0f113f3e 531 goto end;
2234212c 532 if (req == NULL) {
0f113f3e
MC
533 resp =
534 OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
535 NULL);
536 send_ocsp_response(cbio, resp);
537 goto done_resp;
538 }
539 }
540
2234212c
PY
541 if (req == NULL
542 && (signfile != NULL || reqout != NULL
543 || host != NULL || add_nonce || ridx_filename != NULL)) {
0f113f3e
MC
544 BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
545 goto end;
546 }
547
2234212c 548 if (req != NULL && add_nonce)
0f113f3e
MC
549 OCSP_request_add1_nonce(req, NULL, -1);
550
2234212c
PY
551 if (signfile != NULL) {
552 if (keyfile == NULL)
0f113f3e 553 keyfile = signfile;
a773b52a 554 signer = load_cert(signfile, FORMAT_PEM, "signer certificate");
2234212c 555 if (signer == NULL) {
0f113f3e
MC
556 BIO_printf(bio_err, "Error loading signer certificate\n");
557 goto end;
558 }
2234212c 559 if (sign_certfile != NULL) {
a773b52a 560 if (!load_certs(sign_certfile, &sign_other, FORMAT_PEM, NULL,
0996dc54 561 "signer certificates"))
0f113f3e
MC
562 goto end;
563 }
7e1b7485 564 key = load_key(keyfile, FORMAT_PEM, 0, NULL, NULL,
0f113f3e 565 "signer private key");
2234212c 566 if (key == NULL)
0f113f3e
MC
567 goto end;
568
569 if (!OCSP_request_sign
570 (req, signer, key, NULL, sign_other, sign_flags)) {
571 BIO_printf(bio_err, "Error signing OCSP request\n");
572 goto end;
573 }
574 }
575
2234212c 576 if (req_text && req != NULL)
0f113f3e
MC
577 OCSP_REQUEST_print(out, req, 0);
578
2234212c 579 if (reqout != NULL) {
bdd58d98 580 derbio = bio_open_default(reqout, 'w', FORMAT_ASN1);
7e1b7485 581 if (derbio == NULL)
0f113f3e 582 goto end;
0f113f3e
MC
583 i2d_OCSP_REQUEST_bio(derbio, req);
584 BIO_free(derbio);
585 }
586
2234212c
PY
587 if (ridx_filename != NULL
588 && (rkey == NULL || rsigner == NULL || rca_cert == NULL)) {
0f113f3e
MC
589 BIO_printf(bio_err,
590 "Need a responder certificate, key and CA for this operation!\n");
591 goto end;
592 }
593
2234212c 594 if (ridx_filename != NULL && rdb == NULL) {
0f113f3e 595 rdb = load_index(ridx_filename, NULL);
2234212c 596 if (rdb == NULL)
0f113f3e
MC
597 goto end;
598 if (!index_index(rdb))
599 goto end;
600 }
601
2234212c 602 if (rdb != NULL) {
7e1b7485 603 make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey,
0f113f3e 604 rsign_md, rother, rflags, nmin, ndays, badsig);
2234212c 605 if (cbio != NULL)
0f113f3e 606 send_ocsp_response(cbio, resp);
2234212c 607 } else if (host != NULL) {
0f113f3e 608# ifndef OPENSSL_NO_SOCK
7e1b7485 609 resp = process_responder(req, host, path,
0f113f3e 610 port, use_ssl, headers, req_timeout);
2234212c 611 if (resp == NULL)
0f113f3e
MC
612 goto end;
613# else
614 BIO_printf(bio_err,
615 "Error creating connect BIO - sockets not supported.\n");
616 goto end;
617# endif
2234212c 618 } else if (respin != NULL) {
bdd58d98 619 derbio = bio_open_default(respin, 'r', FORMAT_ASN1);
7e1b7485 620 if (derbio == NULL)
0f113f3e 621 goto end;
0f113f3e
MC
622 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
623 BIO_free(derbio);
2234212c 624 if (resp == NULL) {
0f113f3e
MC
625 BIO_printf(bio_err, "Error reading OCSP response\n");
626 goto end;
627 }
0f113f3e
MC
628 } else {
629 ret = 0;
630 goto end;
631 }
632
633 done_resp:
634
2234212c 635 if (respout != NULL) {
bdd58d98 636 derbio = bio_open_default(respout, 'w', FORMAT_ASN1);
7e1b7485 637 if (derbio == NULL)
0f113f3e 638 goto end;
0f113f3e
MC
639 i2d_OCSP_RESPONSE_bio(derbio, resp);
640 BIO_free(derbio);
641 }
642
643 i = OCSP_response_status(resp);
0f113f3e
MC
644 if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
645 BIO_printf(out, "Responder Error: %s (%d)\n",
646 OCSP_response_status_str(i), i);
647 if (ignore_err)
648 goto redo_accept;
649 ret = 0;
650 goto end;
651 }
652
653 if (resp_text)
654 OCSP_RESPONSE_print(out, resp, 0);
655
656 /* If running as responder don't verify our own response */
2234212c 657 if (cbio != NULL) {
e46bcca2
AE
658 /* If not unlimited, see if we took all we should. */
659 if (accept_count != -1 && --accept_count <= 0) {
7e1b7485
RS
660 ret = 0;
661 goto end;
0f113f3e 662 }
7e1b7485
RS
663 BIO_free_all(cbio);
664 cbio = NULL;
665 OCSP_REQUEST_free(req);
666 req = NULL;
667 OCSP_RESPONSE_free(resp);
668 resp = NULL;
669 goto redo_accept;
670 }
2234212c 671 if (ridx_filename != NULL) {
0f113f3e
MC
672 ret = 0;
673 goto end;
674 }
675
2234212c 676 if (store == NULL) {
2b6bcb70 677 store = setup_verify(CAfile, CApath, noCAfile, noCApath);
7e1b7485
RS
678 if (!store)
679 goto end;
680 }
681 if (vpmtouched)
0f113f3e 682 X509_STORE_set1_param(store, vpm);
2234212c 683 if (verify_certfile != NULL) {
a773b52a 684 if (!load_certs(verify_certfile, &verify_other, FORMAT_PEM, NULL,
0996dc54 685 "validator certificate"))
0f113f3e
MC
686 goto end;
687 }
688
689 bs = OCSP_response_get1_basic(resp);
2234212c 690 if (bs == NULL) {
0f113f3e
MC
691 BIO_printf(bio_err, "Error parsing response\n");
692 goto end;
693 }
694
695 ret = 0;
696
697 if (!noverify) {
2234212c 698 if (req != NULL && ((i = OCSP_check_nonce(req, bs)) <= 0)) {
0f113f3e
MC
699 if (i == -1)
700 BIO_printf(bio_err, "WARNING: no nonce in response\n");
701 else {
702 BIO_printf(bio_err, "Nonce Verify error\n");
703 ret = 1;
704 goto end;
705 }
706 }
707
708 i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
c6724060
RS
709 if (i <= 0 && issuers) {
710 i = OCSP_basic_verify(bs, issuers, store, OCSP_TRUSTOTHER);
711 if (i > 0)
712 ERR_clear_error();
713 }
0f113f3e
MC
714 if (i <= 0) {
715 BIO_printf(bio_err, "Response Verify Failure\n");
716 ERR_print_errors(bio_err);
717 ret = 1;
2234212c 718 } else {
0f113f3e 719 BIO_printf(bio_err, "Response verify OK\n");
2234212c 720 }
0f113f3e
MC
721 }
722
7e1b7485 723 print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage);
0f113f3e
MC
724
725 end:
726 ERR_print_errors(bio_err);
727 X509_free(signer);
728 X509_STORE_free(store);
222561fe 729 X509_VERIFY_PARAM_free(vpm);
0f113f3e
MC
730 EVP_PKEY_free(key);
731 EVP_PKEY_free(rkey);
0f113f3e 732 X509_free(cert);
bb7fc98c 733 sk_X509_pop_free(issuers, X509_free);
0f113f3e 734 X509_free(rsigner);
3bb0f989 735 sk_X509_pop_free(rca_cert, X509_free);
0f113f3e
MC
736 free_index(rdb);
737 BIO_free_all(cbio);
738 BIO_free_all(acbio);
739 BIO_free(out);
740 OCSP_REQUEST_free(req);
741 OCSP_RESPONSE_free(resp);
742 OCSP_BASICRESP_free(bs);
743 sk_OPENSSL_STRING_free(reqnames);
744 sk_OCSP_CERTID_free(ids);
745 sk_X509_pop_free(sign_other, X509_free);
746 sk_X509_pop_free(verify_other, X509_free);
747 sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);
b548a1f1
RS
748 OPENSSL_free(thost);
749 OPENSSL_free(tport);
750 OPENSSL_free(tpath);
0f113f3e 751
7e1b7485 752 return (ret);
5782ceb2
DSH
753}
754
0f113f3e
MC
755static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert,
756 const EVP_MD *cert_id_md, X509 *issuer,
757 STACK_OF(OCSP_CERTID) *ids)
758{
759 OCSP_CERTID *id;
2234212c
PY
760
761 if (issuer == NULL) {
0f113f3e
MC
762 BIO_printf(bio_err, "No issuer certificate specified\n");
763 return 0;
764 }
96487cdd 765 if (*req == NULL)
0f113f3e 766 *req = OCSP_REQUEST_new();
96487cdd 767 if (*req == NULL)
0f113f3e
MC
768 goto err;
769 id = OCSP_cert_to_id(cert_id_md, cert, issuer);
2234212c 770 if (id == NULL || !sk_OCSP_CERTID_push(ids, id))
0f113f3e
MC
771 goto err;
772 if (!OCSP_request_add0_id(*req, id))
773 goto err;
774 return 1;
775
776 err:
777 BIO_printf(bio_err, "Error Creating OCSP request\n");
778 return 0;
779}
780
781static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
782 const EVP_MD *cert_id_md, X509 *issuer,
783 STACK_OF(OCSP_CERTID) *ids)
784{
785 OCSP_CERTID *id;
786 X509_NAME *iname;
787 ASN1_BIT_STRING *ikey;
788 ASN1_INTEGER *sno;
2234212c
PY
789
790 if (issuer == NULL) {
0f113f3e
MC
791 BIO_printf(bio_err, "No issuer certificate specified\n");
792 return 0;
793 }
96487cdd 794 if (*req == NULL)
0f113f3e 795 *req = OCSP_REQUEST_new();
96487cdd 796 if (*req == NULL)
0f113f3e
MC
797 goto err;
798 iname = X509_get_subject_name(issuer);
799 ikey = X509_get0_pubkey_bitstr(issuer);
800 sno = s2i_ASN1_INTEGER(NULL, serial);
2234212c 801 if (sno == NULL) {
0f113f3e
MC
802 BIO_printf(bio_err, "Error converting serial number %s\n", serial);
803 return 0;
804 }
805 id = OCSP_cert_id_new(cert_id_md, iname, ikey, sno);
806 ASN1_INTEGER_free(sno);
96487cdd 807 if (id == NULL || !sk_OCSP_CERTID_push(ids, id))
0f113f3e
MC
808 goto err;
809 if (!OCSP_request_add0_id(*req, id))
810 goto err;
811 return 1;
812
813 err:
814 BIO_printf(bio_err, "Error Creating OCSP request\n");
815 return 0;
816}
73758d43 817
7e1b7485 818static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
0f113f3e
MC
819 STACK_OF(OPENSSL_STRING) *names,
820 STACK_OF(OCSP_CERTID) *ids, long nsec,
821 long maxage)
822{
823 OCSP_CERTID *id;
cc696296 824 const char *name;
7e1b7485 825 int i, status, reason;
0f113f3e
MC
826 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
827
2234212c 828 if (bs == NULL || req == NULL || !sk_OPENSSL_STRING_num(names)
0f113f3e 829 || !sk_OCSP_CERTID_num(ids))
7e1b7485 830 return;
0f113f3e
MC
831
832 for (i = 0; i < sk_OCSP_CERTID_num(ids); i++) {
833 id = sk_OCSP_CERTID_value(ids, i);
834 name = sk_OPENSSL_STRING_value(names, i);
835 BIO_printf(out, "%s: ", name);
836
837 if (!OCSP_resp_find_status(bs, id, &status, &reason,
838 &rev, &thisupd, &nextupd)) {
839 BIO_puts(out, "ERROR: No Status found.\n");
840 continue;
841 }
842
843 /*
844 * Check validity: if invalid write to output BIO so we know which
845 * response this refers to.
846 */
847 if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) {
848 BIO_puts(out, "WARNING: Status times invalid.\n");
849 ERR_print_errors(out);
850 }
851 BIO_printf(out, "%s\n", OCSP_cert_status_str(status));
852
853 BIO_puts(out, "\tThis Update: ");
854 ASN1_GENERALIZEDTIME_print(out, thisupd);
855 BIO_puts(out, "\n");
856
857 if (nextupd) {
858 BIO_puts(out, "\tNext Update: ");
859 ASN1_GENERALIZEDTIME_print(out, nextupd);
860 BIO_puts(out, "\n");
861 }
862
863 if (status != V_OCSP_CERTSTATUS_REVOKED)
864 continue;
865
866 if (reason != -1)
867 BIO_printf(out, "\tReason: %s\n", OCSP_crl_reason_str(reason));
868
869 BIO_puts(out, "\tRevocation Time: ");
870 ASN1_GENERALIZEDTIME_print(out, rev);
871 BIO_puts(out, "\n");
872 }
0f113f3e
MC
873}
874
7e1b7485 875static void make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req,
3bb0f989 876 CA_DB *db, STACK_OF(X509) *ca, X509 *rcert,
0f113f3e
MC
877 EVP_PKEY *rkey, const EVP_MD *rmd,
878 STACK_OF(X509) *rother, unsigned long flags,
879 int nmin, int ndays, int badsig)
880{
881 ASN1_TIME *thisupd = NULL, *nextupd = NULL;
3bb0f989 882 OCSP_CERTID *cid;
0f113f3e 883 OCSP_BASICRESP *bs = NULL;
7e1b7485 884 int i, id_count;
0f113f3e
MC
885
886 id_count = OCSP_request_onereq_count(req);
887
888 if (id_count <= 0) {
889 *resp =
890 OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL);
891 goto end;
892 }
893
894 bs = OCSP_BASICRESP_new();
895 thisupd = X509_gmtime_adj(NULL, 0);
896 if (ndays != -1)
9aa00b18 897 nextupd = X509_time_adj_ex(NULL, ndays, nmin * 60, NULL);
0f113f3e
MC
898
899 /* Examine each certificate id in the request */
900 for (i = 0; i < id_count; i++) {
901 OCSP_ONEREQ *one;
902 ASN1_INTEGER *serial;
903 char **inf;
3bb0f989
TS
904 int jj;
905 int found = 0;
0f113f3e
MC
906 ASN1_OBJECT *cert_id_md_oid;
907 const EVP_MD *cert_id_md;
908 one = OCSP_request_onereq_get0(req, i);
909 cid = OCSP_onereq_get0_id(one);
910
911 OCSP_id_get0_info(NULL, &cert_id_md_oid, NULL, NULL, cid);
912
913 cert_id_md = EVP_get_digestbyobj(cert_id_md_oid);
2234212c 914 if (cert_id_md == NULL) {
0f113f3e
MC
915 *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR,
916 NULL);
917 goto end;
918 }
3bb0f989
TS
919 for (jj = 0; jj < sk_X509_num(ca) && !found; jj++) {
920 X509 *ca_cert = sk_X509_value(ca, jj);
921 OCSP_CERTID *ca_id = OCSP_cert_to_id(cert_id_md, NULL, ca_cert);
922
923 if (OCSP_id_issuer_cmp(ca_id, cid) == 0)
924 found = 1;
925
926 OCSP_CERTID_free(ca_id);
927 }
0f113f3e 928
3bb0f989 929 if (!found) {
0f113f3e
MC
930 OCSP_basic_add1_status(bs, cid,
931 V_OCSP_CERTSTATUS_UNKNOWN,
932 0, NULL, thisupd, nextupd);
933 continue;
934 }
935 OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid);
936 inf = lookup_serial(db, serial);
2234212c 937 if (inf == NULL) {
0f113f3e
MC
938 OCSP_basic_add1_status(bs, cid,
939 V_OCSP_CERTSTATUS_UNKNOWN,
940 0, NULL, thisupd, nextupd);
2234212c 941 } else if (inf[DB_type][0] == DB_TYPE_VAL) {
0f113f3e
MC
942 OCSP_basic_add1_status(bs, cid,
943 V_OCSP_CERTSTATUS_GOOD,
944 0, NULL, thisupd, nextupd);
2234212c 945 } else if (inf[DB_type][0] == DB_TYPE_REV) {
0f113f3e
MC
946 ASN1_OBJECT *inst = NULL;
947 ASN1_TIME *revtm = NULL;
948 ASN1_GENERALIZEDTIME *invtm = NULL;
949 OCSP_SINGLERESP *single;
950 int reason = -1;
951 unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]);
952 single = OCSP_basic_add1_status(bs, cid,
953 V_OCSP_CERTSTATUS_REVOKED,
954 reason, revtm, thisupd, nextupd);
2234212c 955 if (invtm != NULL)
0f113f3e
MC
956 OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date,
957 invtm, 0, 0);
2234212c 958 else if (inst != NULL)
0f113f3e
MC
959 OCSP_SINGLERESP_add1_ext_i2d(single,
960 NID_hold_instruction_code, inst,
961 0, 0);
962 ASN1_OBJECT_free(inst);
963 ASN1_TIME_free(revtm);
964 ASN1_GENERALIZEDTIME_free(invtm);
965 }
966 }
967
968 OCSP_copy_nonce(bs, req);
969
970 OCSP_basic_sign(bs, rcert, rkey, rmd, rother, flags);
971
6ef869d7 972 if (badsig) {
a0754084
DSH
973 const ASN1_OCTET_STRING *sig = OCSP_resp_get0_signature(bs);
974 corrupt_signature(sig);
6ef869d7 975 }
0f113f3e
MC
976
977 *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs);
978
979 end:
980 ASN1_TIME_free(thisupd);
981 ASN1_TIME_free(nextupd);
0f113f3e 982 OCSP_BASICRESP_free(bs);
0f113f3e 983}
ee306a13 984
f85b68cd 985static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
0f113f3e
MC
986{
987 int i;
988 BIGNUM *bn = NULL;
989 char *itmp, *row[DB_NUMBER], **rrow;
990 for (i = 0; i < DB_NUMBER; i++)
991 row[i] = NULL;
992 bn = ASN1_INTEGER_to_BN(ser, NULL);
993 OPENSSL_assert(bn); /* FIXME: should report an error at this
994 * point and abort */
995 if (BN_is_zero(bn))
7644a9ae 996 itmp = OPENSSL_strdup("00");
0f113f3e
MC
997 else
998 itmp = BN_bn2hex(bn);
999 row[DB_serial] = itmp;
1000 BN_free(bn);
1001 rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
1002 OPENSSL_free(itmp);
1003 return rrow;
1004}
ee306a13
DSH
1005
1006/* Quick and dirty OCSP server: read in and parse input request */
1007
c45a48c1 1008static BIO *init_responder(const char *port)
0f113f3e 1009{
366e2a60 1010# ifdef OPENSSL_NO_SOCK
0f113f3e
MC
1011 BIO_printf(bio_err,
1012 "Error setting up accept BIO - sockets not supported.\n");
366e2a60 1013 return NULL;
f863ad0c
MC
1014# else
1015 BIO *acbio = NULL, *bufbio = NULL;
1016
366e2a60 1017 bufbio = BIO_new(BIO_f_buffer());
96487cdd 1018 if (bufbio == NULL)
0f113f3e 1019 goto err;
366e2a60
RS
1020 acbio = BIO_new(BIO_s_accept());
1021 if (acbio == NULL
1022 || BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR) < 0
1023 || BIO_set_accept_port(acbio, port) < 0) {
1024 BIO_printf(bio_err, "Error setting up accept BIO\n");
1025 ERR_print_errors(bio_err);
1026 goto err;
1027 }
1028
0f113f3e
MC
1029 BIO_set_accept_bios(acbio, bufbio);
1030 bufbio = NULL;
0f113f3e 1031 if (BIO_do_accept(acbio) <= 0) {
366e2a60 1032 BIO_printf(bio_err, "Error starting accept\n");
0f113f3e
MC
1033 ERR_print_errors(bio_err);
1034 goto err;
1035 }
1036
1037 return acbio;
1038
1039 err:
1040 BIO_free_all(acbio);
1041 BIO_free(bufbio);
1042 return NULL;
f863ad0c 1043# endif
0f113f3e 1044}
ee306a13 1045
f863ad0c 1046# ifndef OPENSSL_NO_SOCK
fc3cec53
RS
1047/*
1048 * Decode %xx URL-decoding in-place. Ignores mal-formed sequences.
1049 */
1050static int urldecode(char *p)
995101d6
RS
1051{
1052 unsigned char *out = (unsigned char *)p;
fc3cec53 1053 unsigned char *save = out;
995101d6
RS
1054
1055 for (; *p; p++) {
1056 if (*p != '%')
1057 *out++ = *p;
18295f0c 1058 else if (isxdigit(_UC(p[1])) && isxdigit(_UC(p[2]))) {
14f051a0
RS
1059 /* Don't check, can't fail because of ixdigit() call. */
1060 *out++ = (OPENSSL_hexchar2int(p[1]) << 4)
1061 | OPENSSL_hexchar2int(p[2]);
995101d6
RS
1062 p += 2;
1063 }
fc3cec53
RS
1064 else
1065 return -1;
995101d6 1066 }
fc3cec53
RS
1067 *out = '\0';
1068 return (int)(out - save);
995101d6 1069}
f863ad0c 1070# endif
995101d6 1071
a773b52a 1072static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio)
0f113f3e 1073{
f863ad0c
MC
1074# ifdef OPENSSL_NO_SOCK
1075 return 0;
1076# else
7e1b7485 1077 int len;
0f113f3e 1078 OCSP_REQUEST *req = NULL;
fc3cec53 1079 char inbuf[2048], reqbuf[2048];
995101d6
RS
1080 char *p, *q;
1081 BIO *cbio = NULL, *getbio = NULL, *b64 = NULL;
0f113f3e
MC
1082
1083 if (BIO_do_accept(acbio) <= 0) {
1084 BIO_printf(bio_err, "Error accepting connection\n");
1085 ERR_print_errors(bio_err);
1086 return 0;
1087 }
1088
1089 cbio = BIO_pop(acbio);
1090 *pcbio = cbio;
1091
7e1b7485 1092 /* Read the request line. */
fc3cec53 1093 len = BIO_gets(cbio, reqbuf, sizeof reqbuf);
7e1b7485
RS
1094 if (len <= 0)
1095 return 1;
fc3cec53 1096 if (strncmp(reqbuf, "GET ", 4) == 0) {
995101d6 1097 /* Expecting GET {sp} /URL {sp} HTTP/1.x */
fc3cec53 1098 for (p = reqbuf + 4; *p == ' '; ++p)
995101d6 1099 continue;
fc3cec53
RS
1100 if (*p != '/') {
1101 BIO_printf(bio_err, "Invalid request -- bad URL\n");
1102 return 1;
995101d6 1103 }
fc3cec53
RS
1104 p++;
1105
995101d6
RS
1106 /* Splice off the HTTP version identifier. */
1107 for (q = p; *q; q++)
fc3cec53 1108 if (*q == ' ')
995101d6 1109 break;
fc3cec53
RS
1110 if (strncmp(q, " HTTP/1.", 8) != 0) {
1111 BIO_printf(bio_err, "Invalid request -- bad HTTP vesion\n");
995101d6
RS
1112 return 1;
1113 }
1114 *q = '\0';
fc3cec53
RS
1115 len = urldecode(p);
1116 if (len <= 0) {
1117 BIO_printf(bio_err, "Invalid request -- bad URL encoding\n");
1118 return 1;
1119 }
1120 if ((getbio = BIO_new_mem_buf(p, len)) == NULL
1121 || (b64 = BIO_new(BIO_f_base64())) == NULL) {
1122 BIO_printf(bio_err, "Could not allocate memory\n");
1123 ERR_print_errors(bio_err);
1124 return 1;
1125 }
995101d6
RS
1126 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1127 getbio = BIO_push(b64, getbio);
fc3cec53
RS
1128 } else if (strncmp(reqbuf, "POST ", 5) != 0) {
1129 BIO_printf(bio_err, "Invalid request -- bad HTTP verb\n");
7e1b7485
RS
1130 return 1;
1131 }
fc3cec53
RS
1132
1133 /* Read and skip past the headers. */
0f113f3e
MC
1134 for (;;) {
1135 len = BIO_gets(cbio, inbuf, sizeof inbuf);
1136 if (len <= 0)
1137 return 1;
0f113f3e
MC
1138 if ((inbuf[0] == '\r') || (inbuf[0] == '\n'))
1139 break;
1140 }
1141
1142 /* Try to read OCSP request */
2234212c 1143 if (getbio != NULL) {
995101d6
RS
1144 req = d2i_OCSP_REQUEST_bio(getbio, NULL);
1145 BIO_free_all(getbio);
2234212c 1146 } else {
995101d6 1147 req = d2i_OCSP_REQUEST_bio(cbio, NULL);
2234212c 1148 }
0f113f3e 1149
2234212c 1150 if (req == NULL) {
0f113f3e
MC
1151 BIO_printf(bio_err, "Error parsing OCSP request\n");
1152 ERR_print_errors(bio_err);
1153 }
1154
1155 *preq = req;
1156
1157 return 1;
f863ad0c 1158# endif
0f113f3e 1159}
ee306a13
DSH
1160
1161static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
0f113f3e
MC
1162{
1163 char http_resp[] =
1164 "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n"
1165 "Content-Length: %d\r\n\r\n";
2234212c 1166 if (cbio == NULL)
0f113f3e
MC
1167 return 0;
1168 BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL));
1169 i2d_OCSP_RESPONSE_bio(cbio, resp);
1170 (void)BIO_flush(cbio);
1171 return 1;
1172}
ee306a13 1173
f9e55034 1174# ifndef OPENSSL_NO_SOCK
76e0cd12
DSH
1175static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host,
1176 const char *path,
0f113f3e
MC
1177 const STACK_OF(CONF_VALUE) *headers,
1178 OCSP_REQUEST *req, int req_timeout)
1179{
1180 int fd;
1181 int rv;
1182 int i;
76e0cd12 1183 int add_host = 1;
0f113f3e
MC
1184 OCSP_REQ_CTX *ctx = NULL;
1185 OCSP_RESPONSE *rsp = NULL;
1186 fd_set confds;
1187 struct timeval tv;
1188
1189 if (req_timeout != -1)
1190 BIO_set_nbio(cbio, 1);
1191
1192 rv = BIO_do_connect(cbio);
1193
1194 if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) {
7e1b7485 1195 BIO_puts(bio_err, "Error connecting BIO\n");
0f113f3e
MC
1196 return NULL;
1197 }
1198
4428c7db 1199 if (BIO_get_fd(cbio, &fd) < 0) {
7e1b7485 1200 BIO_puts(bio_err, "Can't get connection fd\n");
0f113f3e
MC
1201 goto err;
1202 }
1203
1204 if (req_timeout != -1 && rv <= 0) {
1205 FD_ZERO(&confds);
1206 openssl_fdset(fd, &confds);
1207 tv.tv_usec = 0;
1208 tv.tv_sec = req_timeout;
1209 rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
1210 if (rv == 0) {
7e1b7485 1211 BIO_puts(bio_err, "Timeout on connect\n");
0f113f3e
MC
1212 return NULL;
1213 }
1214 }
1215
1216 ctx = OCSP_sendreq_new(cbio, path, NULL, -1);
96487cdd 1217 if (ctx == NULL)
0f113f3e
MC
1218 return NULL;
1219
1220 for (i = 0; i < sk_CONF_VALUE_num(headers); i++) {
1221 CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i);
76e0cd12
DSH
1222 if (add_host == 1 && strcasecmp("host", hdr->name) == 0)
1223 add_host = 0;
0f113f3e
MC
1224 if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value))
1225 goto err;
1226 }
1227
76e0cd12
DSH
1228 if (add_host == 1 && OCSP_REQ_CTX_add1_header(ctx, "Host", host) == 0)
1229 goto err;
1230
0f113f3e
MC
1231 if (!OCSP_REQ_CTX_set1_req(ctx, req))
1232 goto err;
1233
1234 for (;;) {
1235 rv = OCSP_sendreq_nbio(&rsp, ctx);
1236 if (rv != -1)
1237 break;
1238 if (req_timeout == -1)
1239 continue;
1240 FD_ZERO(&confds);
1241 openssl_fdset(fd, &confds);
1242 tv.tv_usec = 0;
1243 tv.tv_sec = req_timeout;
2234212c 1244 if (BIO_should_read(cbio)) {
0f113f3e 1245 rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv);
2234212c 1246 } else if (BIO_should_write(cbio)) {
0f113f3e 1247 rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
2234212c 1248 } else {
7e1b7485 1249 BIO_puts(bio_err, "Unexpected retry condition\n");
0f113f3e
MC
1250 goto err;
1251 }
1252 if (rv == 0) {
7e1b7485 1253 BIO_puts(bio_err, "Timeout on request\n");
0f113f3e
MC
1254 break;
1255 }
1256 if (rv == -1) {
7e1b7485 1257 BIO_puts(bio_err, "Select error\n");
0f113f3e
MC
1258 break;
1259 }
1260
1261 }
1262 err:
895cba19 1263 OCSP_REQ_CTX_free(ctx);
0f113f3e
MC
1264
1265 return rsp;
1266}
454dbbc5 1267
7e1b7485 1268OCSP_RESPONSE *process_responder(OCSP_REQUEST *req,
0f113f3e
MC
1269 const char *host, const char *path,
1270 const char *port, int use_ssl,
82c49427 1271 STACK_OF(CONF_VALUE) *headers,
0f113f3e
MC
1272 int req_timeout)
1273{
1274 BIO *cbio = NULL;
1275 SSL_CTX *ctx = NULL;
1276 OCSP_RESPONSE *resp = NULL;
ff4a9394 1277
0f113f3e 1278 cbio = BIO_new_connect(host);
2234212c 1279 if (cbio == NULL) {
7e1b7485 1280 BIO_printf(bio_err, "Error creating connect BIO\n");
0f113f3e
MC
1281 goto end;
1282 }
2234212c 1283 if (port != NULL)
0f113f3e
MC
1284 BIO_set_conn_port(cbio, port);
1285 if (use_ssl == 1) {
1286 BIO *sbio;
13c9bb3e 1287 ctx = SSL_CTX_new(TLS_client_method());
0f113f3e 1288 if (ctx == NULL) {
7e1b7485 1289 BIO_printf(bio_err, "Error creating SSL context.\n");
0f113f3e
MC
1290 goto end;
1291 }
1292 SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
1293 sbio = BIO_new_ssl(ctx, 1);
1294 cbio = BIO_push(sbio, cbio);
1295 }
ff4a9394 1296
76e0cd12 1297 resp = query_responder(cbio, host, path, headers, req, req_timeout);
2234212c 1298 if (resp == NULL)
0f113f3e
MC
1299 BIO_printf(bio_err, "Error querying OCSP responder\n");
1300 end:
ca3a82c3 1301 BIO_free_all(cbio);
62adbcee 1302 SSL_CTX_free(ctx);
0f113f3e
MC
1303 return resp;
1304}
f9e55034 1305# endif
67c8e7f4 1306
85d686e7 1307#endif