xref: /freebsd/crypto/openssl/apps/ocsp.c (revision db522d3ae42d8f706499b4b4bc97836292ab180b)
15c87c606SMark Murray /* ocsp.c */
2db522d3aSSimon L. B. Nielsen /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
35c87c606SMark Murray  * project 2000.
45c87c606SMark Murray  */
55c87c606SMark Murray /* ====================================================================
65c87c606SMark Murray  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
75c87c606SMark Murray  *
85c87c606SMark Murray  * Redistribution and use in source and binary forms, with or without
95c87c606SMark Murray  * modification, are permitted provided that the following conditions
105c87c606SMark Murray  * are met:
115c87c606SMark Murray  *
125c87c606SMark Murray  * 1. Redistributions of source code must retain the above copyright
135c87c606SMark Murray  *    notice, this list of conditions and the following disclaimer.
145c87c606SMark Murray  *
155c87c606SMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
165c87c606SMark Murray  *    notice, this list of conditions and the following disclaimer in
175c87c606SMark Murray  *    the documentation and/or other materials provided with the
185c87c606SMark Murray  *    distribution.
195c87c606SMark Murray  *
205c87c606SMark Murray  * 3. All advertising materials mentioning features or use of this
215c87c606SMark Murray  *    software must display the following acknowledgment:
225c87c606SMark Murray  *    "This product includes software developed by the OpenSSL Project
235c87c606SMark Murray  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
245c87c606SMark Murray  *
255c87c606SMark Murray  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
265c87c606SMark Murray  *    endorse or promote products derived from this software without
275c87c606SMark Murray  *    prior written permission. For written permission, please contact
285c87c606SMark Murray  *    licensing@OpenSSL.org.
295c87c606SMark Murray  *
305c87c606SMark Murray  * 5. Products derived from this software may not be called "OpenSSL"
315c87c606SMark Murray  *    nor may "OpenSSL" appear in their names without prior written
325c87c606SMark Murray  *    permission of the OpenSSL Project.
335c87c606SMark Murray  *
345c87c606SMark Murray  * 6. Redistributions of any form whatsoever must retain the following
355c87c606SMark Murray  *    acknowledgment:
365c87c606SMark Murray  *    "This product includes software developed by the OpenSSL Project
375c87c606SMark Murray  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
385c87c606SMark Murray  *
395c87c606SMark Murray  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
405c87c606SMark Murray  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
415c87c606SMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
425c87c606SMark Murray  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
435c87c606SMark Murray  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
445c87c606SMark Murray  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
455c87c606SMark Murray  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
465c87c606SMark Murray  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
475c87c606SMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
485c87c606SMark Murray  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
495c87c606SMark Murray  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
505c87c606SMark Murray  * OF THE POSSIBILITY OF SUCH DAMAGE.
515c87c606SMark Murray  * ====================================================================
525c87c606SMark Murray  *
535c87c606SMark Murray  * This product includes cryptographic software written by Eric Young
545c87c606SMark Murray  * (eay@cryptsoft.com).  This product includes software written by Tim
555c87c606SMark Murray  * Hudson (tjh@cryptsoft.com).
565c87c606SMark Murray  *
575c87c606SMark Murray  */
58fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_OCSP
59db522d3aSSimon L. B. Nielsen #define USE_SOCKETS
605c87c606SMark Murray #include <stdio.h>
61db522d3aSSimon L. B. Nielsen #include <stdlib.h>
625c87c606SMark Murray #include <string.h>
63db522d3aSSimon L. B. Nielsen #include "apps.h" /* needs to be included before the openssl headers! */
64db522d3aSSimon L. B. Nielsen #include <openssl/e_os2.h>
655c87c606SMark Murray #include <openssl/ssl.h>
66db522d3aSSimon L. B. Nielsen #include <openssl/err.h>
675c87c606SMark Murray 
685c87c606SMark Murray /* Maximum leeway in validity period: default 5 minutes */
695c87c606SMark Murray #define MAX_VALIDITY_PERIOD	(5 * 60)
705c87c606SMark Murray 
715c87c606SMark Murray static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
725c87c606SMark Murray 				STACK_OF(OCSP_CERTID) *ids);
735c87c606SMark Murray static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer,
745c87c606SMark Murray 				STACK_OF(OCSP_CERTID) *ids);
755c87c606SMark Murray static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
765c87c606SMark Murray 				STACK *names, STACK_OF(OCSP_CERTID) *ids,
775c87c606SMark Murray 				long nsec, long maxage);
785c87c606SMark Murray 
79ced566fdSJacques Vidrine static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, CA_DB *db,
805c87c606SMark Murray 			X509 *ca, X509 *rcert, EVP_PKEY *rkey,
815c87c606SMark Murray 			STACK_OF(X509) *rother, unsigned long flags,
825c87c606SMark Murray 			int nmin, int ndays);
835c87c606SMark Murray 
84ced566fdSJacques Vidrine static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser);
855c87c606SMark Murray static BIO *init_responder(char *port);
865c87c606SMark Murray static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, char *port);
875c87c606SMark Murray static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp);
88db522d3aSSimon L. B. Nielsen static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path,
89db522d3aSSimon L. B. Nielsen 				OCSP_REQUEST *req, int req_timeout);
905c87c606SMark Murray 
915c87c606SMark Murray #undef PROG
925c87c606SMark Murray #define PROG ocsp_main
935c87c606SMark Murray 
945c87c606SMark Murray int MAIN(int, char **);
955c87c606SMark Murray 
965c87c606SMark Murray int MAIN(int argc, char **argv)
975c87c606SMark Murray 	{
985c87c606SMark Murray 	ENGINE *e = NULL;
995c87c606SMark Murray 	char **args;
1005c87c606SMark Murray 	char *host = NULL, *port = NULL, *path = "/";
1015c87c606SMark Murray 	char *reqin = NULL, *respin = NULL;
1025c87c606SMark Murray 	char *reqout = NULL, *respout = NULL;
1035c87c606SMark Murray 	char *signfile = NULL, *keyfile = NULL;
1045c87c606SMark Murray 	char *rsignfile = NULL, *rkeyfile = NULL;
1055c87c606SMark Murray 	char *outfile = NULL;
1065c87c606SMark Murray 	int add_nonce = 1, noverify = 0, use_ssl = -1;
1075c87c606SMark Murray 	OCSP_REQUEST *req = NULL;
1085c87c606SMark Murray 	OCSP_RESPONSE *resp = NULL;
1095c87c606SMark Murray 	OCSP_BASICRESP *bs = NULL;
1105c87c606SMark Murray 	X509 *issuer = NULL, *cert = NULL;
1115c87c606SMark Murray 	X509 *signer = NULL, *rsigner = NULL;
1125c87c606SMark Murray 	EVP_PKEY *key = NULL, *rkey = NULL;
1135c87c606SMark Murray 	BIO *acbio = NULL, *cbio = NULL;
1145c87c606SMark Murray 	BIO *derbio = NULL;
1155c87c606SMark Murray 	BIO *out = NULL;
116db522d3aSSimon L. B. Nielsen 	int req_timeout = -1;
1175c87c606SMark Murray 	int req_text = 0, resp_text = 0;
1185c87c606SMark Murray 	long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
1195c87c606SMark Murray 	char *CAfile = NULL, *CApath = NULL;
1205c87c606SMark Murray 	X509_STORE *store = NULL;
1215c87c606SMark Murray 	STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL;
1225c87c606SMark Murray 	char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
1235c87c606SMark Murray 	unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
1245c87c606SMark Murray 	int ret = 1;
1255c87c606SMark Murray 	int accept_count = -1;
1265c87c606SMark Murray 	int badarg = 0;
1275c87c606SMark Murray 	int i;
12850ef0093SJacques Vidrine 	int ignore_err = 0;
1295c87c606SMark Murray 	STACK *reqnames = NULL;
1305c87c606SMark Murray 	STACK_OF(OCSP_CERTID) *ids = NULL;
1315c87c606SMark Murray 
1325c87c606SMark Murray 	X509 *rca_cert = NULL;
1335c87c606SMark Murray 	char *ridx_filename = NULL;
1345c87c606SMark Murray 	char *rca_filename = NULL;
135ced566fdSJacques Vidrine 	CA_DB *rdb = NULL;
1365c87c606SMark Murray 	int nmin = 0, ndays = -1;
1375c87c606SMark Murray 
1385c87c606SMark Murray 	if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
1395c87c606SMark Murray 
1405c87c606SMark Murray 	if (!load_config(bio_err, NULL))
1415c87c606SMark Murray 		goto end;
1425c87c606SMark Murray 	SSL_load_error_strings();
1435471f83eSSimon L. B. Nielsen 	OpenSSL_add_ssl_algorithms();
1445c87c606SMark Murray 	args = argv + 1;
1455c87c606SMark Murray 	reqnames = sk_new_null();
1465c87c606SMark Murray 	ids = sk_OCSP_CERTID_new_null();
1475c87c606SMark Murray 	while (!badarg && *args && *args[0] == '-')
1485c87c606SMark Murray 		{
1495c87c606SMark Murray 		if (!strcmp(*args, "-out"))
1505c87c606SMark Murray 			{
1515c87c606SMark Murray 			if (args[1])
1525c87c606SMark Murray 				{
1535c87c606SMark Murray 				args++;
1545c87c606SMark Murray 				outfile = *args;
1555c87c606SMark Murray 				}
1565c87c606SMark Murray 			else badarg = 1;
1575c87c606SMark Murray 			}
158db522d3aSSimon L. B. Nielsen 		else if (!strcmp(*args, "-timeout"))
159db522d3aSSimon L. B. Nielsen 			{
160db522d3aSSimon L. B. Nielsen 			if (args[1])
161db522d3aSSimon L. B. Nielsen 				{
162db522d3aSSimon L. B. Nielsen 				args++;
163db522d3aSSimon L. B. Nielsen 				req_timeout = atol(*args);
164db522d3aSSimon L. B. Nielsen 				if (req_timeout < 0)
165db522d3aSSimon L. B. Nielsen 					{
166db522d3aSSimon L. B. Nielsen 					BIO_printf(bio_err,
167db522d3aSSimon L. B. Nielsen 						"Illegal timeout value %s\n",
168db522d3aSSimon L. B. Nielsen 						*args);
169db522d3aSSimon L. B. Nielsen 					badarg = 1;
170db522d3aSSimon L. B. Nielsen 					}
171db522d3aSSimon L. B. Nielsen 				}
172db522d3aSSimon L. B. Nielsen 			else badarg = 1;
173db522d3aSSimon L. B. Nielsen 			}
1745c87c606SMark Murray 		else if (!strcmp(*args, "-url"))
1755c87c606SMark Murray 			{
1765c87c606SMark Murray 			if (args[1])
1775c87c606SMark Murray 				{
1785c87c606SMark Murray 				args++;
1795c87c606SMark Murray 				if (!OCSP_parse_url(*args, &host, &port, &path, &use_ssl))
1805c87c606SMark Murray 					{
1815c87c606SMark Murray 					BIO_printf(bio_err, "Error parsing URL\n");
1825c87c606SMark Murray 					badarg = 1;
1835c87c606SMark Murray 					}
1845c87c606SMark Murray 				}
1855c87c606SMark Murray 			else badarg = 1;
1865c87c606SMark Murray 			}
1875c87c606SMark Murray 		else if (!strcmp(*args, "-host"))
1885c87c606SMark Murray 			{
1895c87c606SMark Murray 			if (args[1])
1905c87c606SMark Murray 				{
1915c87c606SMark Murray 				args++;
1925c87c606SMark Murray 				host = *args;
1935c87c606SMark Murray 				}
1945c87c606SMark Murray 			else badarg = 1;
1955c87c606SMark Murray 			}
1965c87c606SMark Murray 		else if (!strcmp(*args, "-port"))
1975c87c606SMark Murray 			{
1985c87c606SMark Murray 			if (args[1])
1995c87c606SMark Murray 				{
2005c87c606SMark Murray 				args++;
2015c87c606SMark Murray 				port = *args;
2025c87c606SMark Murray 				}
2035c87c606SMark Murray 			else badarg = 1;
2045c87c606SMark Murray 			}
20550ef0093SJacques Vidrine 		else if (!strcmp(*args, "-ignore_err"))
20650ef0093SJacques Vidrine 			ignore_err = 1;
2075c87c606SMark Murray 		else if (!strcmp(*args, "-noverify"))
2085c87c606SMark Murray 			noverify = 1;
2095c87c606SMark Murray 		else if (!strcmp(*args, "-nonce"))
2105c87c606SMark Murray 			add_nonce = 2;
2115c87c606SMark Murray 		else if (!strcmp(*args, "-no_nonce"))
2125c87c606SMark Murray 			add_nonce = 0;
2135c87c606SMark Murray 		else if (!strcmp(*args, "-resp_no_certs"))
2145c87c606SMark Murray 			rflags |= OCSP_NOCERTS;
2155c87c606SMark Murray 		else if (!strcmp(*args, "-resp_key_id"))
2165c87c606SMark Murray 			rflags |= OCSP_RESPID_KEY;
2175c87c606SMark Murray 		else if (!strcmp(*args, "-no_certs"))
2185c87c606SMark Murray 			sign_flags |= OCSP_NOCERTS;
2195c87c606SMark Murray 		else if (!strcmp(*args, "-no_signature_verify"))
2205c87c606SMark Murray 			verify_flags |= OCSP_NOSIGS;
2215c87c606SMark Murray 		else if (!strcmp(*args, "-no_cert_verify"))
2225c87c606SMark Murray 			verify_flags |= OCSP_NOVERIFY;
2235c87c606SMark Murray 		else if (!strcmp(*args, "-no_chain"))
2245c87c606SMark Murray 			verify_flags |= OCSP_NOCHAIN;
2255c87c606SMark Murray 		else if (!strcmp(*args, "-no_cert_checks"))
2265c87c606SMark Murray 			verify_flags |= OCSP_NOCHECKS;
2275c87c606SMark Murray 		else if (!strcmp(*args, "-no_explicit"))
2285c87c606SMark Murray 			verify_flags |= OCSP_NOEXPLICIT;
2295c87c606SMark Murray 		else if (!strcmp(*args, "-trust_other"))
2305c87c606SMark Murray 			verify_flags |= OCSP_TRUSTOTHER;
2315c87c606SMark Murray 		else if (!strcmp(*args, "-no_intern"))
2325c87c606SMark Murray 			verify_flags |= OCSP_NOINTERN;
2335c87c606SMark Murray 		else if (!strcmp(*args, "-text"))
2345c87c606SMark Murray 			{
2355c87c606SMark Murray 			req_text = 1;
2365c87c606SMark Murray 			resp_text = 1;
2375c87c606SMark Murray 			}
2385c87c606SMark Murray 		else if (!strcmp(*args, "-req_text"))
2395c87c606SMark Murray 			req_text = 1;
2405c87c606SMark Murray 		else if (!strcmp(*args, "-resp_text"))
2415c87c606SMark Murray 			resp_text = 1;
2425c87c606SMark Murray 		else if (!strcmp(*args, "-reqin"))
2435c87c606SMark Murray 			{
2445c87c606SMark Murray 			if (args[1])
2455c87c606SMark Murray 				{
2465c87c606SMark Murray 				args++;
2475c87c606SMark Murray 				reqin = *args;
2485c87c606SMark Murray 				}
2495c87c606SMark Murray 			else badarg = 1;
2505c87c606SMark Murray 			}
2515c87c606SMark Murray 		else if (!strcmp(*args, "-respin"))
2525c87c606SMark Murray 			{
2535c87c606SMark Murray 			if (args[1])
2545c87c606SMark Murray 				{
2555c87c606SMark Murray 				args++;
2565c87c606SMark Murray 				respin = *args;
2575c87c606SMark Murray 				}
2585c87c606SMark Murray 			else badarg = 1;
2595c87c606SMark Murray 			}
2605c87c606SMark Murray 		else if (!strcmp(*args, "-signer"))
2615c87c606SMark Murray 			{
2625c87c606SMark Murray 			if (args[1])
2635c87c606SMark Murray 				{
2645c87c606SMark Murray 				args++;
2655c87c606SMark Murray 				signfile = *args;
2665c87c606SMark Murray 				}
2675c87c606SMark Murray 			else badarg = 1;
2685c87c606SMark Murray 			}
2695c87c606SMark Murray 		else if (!strcmp (*args, "-VAfile"))
2705c87c606SMark Murray 			{
2715c87c606SMark Murray 			if (args[1])
2725c87c606SMark Murray 				{
2735c87c606SMark Murray 				args++;
2745c87c606SMark Murray 				verify_certfile = *args;
2755c87c606SMark Murray 				verify_flags |= OCSP_TRUSTOTHER;
2765c87c606SMark Murray 				}
2775c87c606SMark Murray 			else badarg = 1;
2785c87c606SMark Murray 			}
2795c87c606SMark Murray 		else if (!strcmp(*args, "-sign_other"))
2805c87c606SMark Murray 			{
2815c87c606SMark Murray 			if (args[1])
2825c87c606SMark Murray 				{
2835c87c606SMark Murray 				args++;
2845c87c606SMark Murray 				sign_certfile = *args;
2855c87c606SMark Murray 				}
2865c87c606SMark Murray 			else badarg = 1;
2875c87c606SMark Murray 			}
2885c87c606SMark Murray 		else if (!strcmp(*args, "-verify_other"))
2895c87c606SMark Murray 			{
2905c87c606SMark Murray 			if (args[1])
2915c87c606SMark Murray 				{
2925c87c606SMark Murray 				args++;
2935c87c606SMark Murray 				verify_certfile = *args;
2945c87c606SMark Murray 				}
2955c87c606SMark Murray 			else badarg = 1;
2965c87c606SMark Murray 			}
2975c87c606SMark Murray 		else if (!strcmp (*args, "-CAfile"))
2985c87c606SMark Murray 			{
2995c87c606SMark Murray 			if (args[1])
3005c87c606SMark Murray 				{
3015c87c606SMark Murray 				args++;
3025c87c606SMark Murray 				CAfile = *args;
3035c87c606SMark Murray 				}
3045c87c606SMark Murray 			else badarg = 1;
3055c87c606SMark Murray 			}
3065c87c606SMark Murray 		else if (!strcmp (*args, "-CApath"))
3075c87c606SMark Murray 			{
3085c87c606SMark Murray 			if (args[1])
3095c87c606SMark Murray 				{
3105c87c606SMark Murray 				args++;
3115c87c606SMark Murray 				CApath = *args;
3125c87c606SMark Murray 				}
3135c87c606SMark Murray 			else badarg = 1;
3145c87c606SMark Murray 			}
3155c87c606SMark Murray 		else if (!strcmp (*args, "-validity_period"))
3165c87c606SMark Murray 			{
3175c87c606SMark Murray 			if (args[1])
3185c87c606SMark Murray 				{
3195c87c606SMark Murray 				args++;
3205c87c606SMark Murray 				nsec = atol(*args);
3215c87c606SMark Murray 				if (nsec < 0)
3225c87c606SMark Murray 					{
3235c87c606SMark Murray 					BIO_printf(bio_err,
3245c87c606SMark Murray 						"Illegal validity period %s\n",
3255c87c606SMark Murray 						*args);
3265c87c606SMark Murray 					badarg = 1;
3275c87c606SMark Murray 					}
3285c87c606SMark Murray 				}
3295c87c606SMark Murray 			else badarg = 1;
3305c87c606SMark Murray 			}
3315c87c606SMark Murray 		else if (!strcmp (*args, "-status_age"))
3325c87c606SMark Murray 			{
3335c87c606SMark Murray 			if (args[1])
3345c87c606SMark Murray 				{
3355c87c606SMark Murray 				args++;
3365c87c606SMark Murray 				maxage = atol(*args);
3375c87c606SMark Murray 				if (maxage < 0)
3385c87c606SMark Murray 					{
3395c87c606SMark Murray 					BIO_printf(bio_err,
3405c87c606SMark Murray 						"Illegal validity age %s\n",
3415c87c606SMark Murray 						*args);
3425c87c606SMark Murray 					badarg = 1;
3435c87c606SMark Murray 					}
3445c87c606SMark Murray 				}
3455c87c606SMark Murray 			else badarg = 1;
3465c87c606SMark Murray 			}
3475c87c606SMark Murray 		 else if (!strcmp(*args, "-signkey"))
3485c87c606SMark Murray 			{
3495c87c606SMark Murray 			if (args[1])
3505c87c606SMark Murray 				{
3515c87c606SMark Murray 				args++;
3525c87c606SMark Murray 				keyfile = *args;
3535c87c606SMark Murray 				}
3545c87c606SMark Murray 			else badarg = 1;
3555c87c606SMark Murray 			}
3565c87c606SMark Murray 		else if (!strcmp(*args, "-reqout"))
3575c87c606SMark Murray 			{
3585c87c606SMark Murray 			if (args[1])
3595c87c606SMark Murray 				{
3605c87c606SMark Murray 				args++;
3615c87c606SMark Murray 				reqout = *args;
3625c87c606SMark Murray 				}
3635c87c606SMark Murray 			else badarg = 1;
3645c87c606SMark Murray 			}
3655c87c606SMark Murray 		else if (!strcmp(*args, "-respout"))
3665c87c606SMark Murray 			{
3675c87c606SMark Murray 			if (args[1])
3685c87c606SMark Murray 				{
3695c87c606SMark Murray 				args++;
3705c87c606SMark Murray 				respout = *args;
3715c87c606SMark Murray 				}
3725c87c606SMark Murray 			else badarg = 1;
3735c87c606SMark Murray 			}
3745c87c606SMark Murray 		 else if (!strcmp(*args, "-path"))
3755c87c606SMark Murray 			{
3765c87c606SMark Murray 			if (args[1])
3775c87c606SMark Murray 				{
3785c87c606SMark Murray 				args++;
3795c87c606SMark Murray 				path = *args;
3805c87c606SMark Murray 				}
3815c87c606SMark Murray 			else badarg = 1;
3825c87c606SMark Murray 			}
3835c87c606SMark Murray 		else if (!strcmp(*args, "-issuer"))
3845c87c606SMark Murray 			{
3855c87c606SMark Murray 			if (args[1])
3865c87c606SMark Murray 				{
3875c87c606SMark Murray 				args++;
3885c87c606SMark Murray 				X509_free(issuer);
3895c87c606SMark Murray 				issuer = load_cert(bio_err, *args, FORMAT_PEM,
3905c87c606SMark Murray 					NULL, e, "issuer certificate");
3915c87c606SMark Murray 				if(!issuer) goto end;
3925c87c606SMark Murray 				}
3935c87c606SMark Murray 			else badarg = 1;
3945c87c606SMark Murray 			}
3955c87c606SMark Murray 		else if (!strcmp (*args, "-cert"))
3965c87c606SMark Murray 			{
3975c87c606SMark Murray 			if (args[1])
3985c87c606SMark Murray 				{
3995c87c606SMark Murray 				args++;
4005c87c606SMark Murray 				X509_free(cert);
4015c87c606SMark Murray 				cert = load_cert(bio_err, *args, FORMAT_PEM,
4025c87c606SMark Murray 					NULL, e, "certificate");
4035c87c606SMark Murray 				if(!cert) goto end;
4045c87c606SMark Murray 				if(!add_ocsp_cert(&req, cert, issuer, ids))
4055c87c606SMark Murray 					goto end;
4065c87c606SMark Murray 				if(!sk_push(reqnames, *args))
4075c87c606SMark Murray 					goto end;
4085c87c606SMark Murray 				}
4095c87c606SMark Murray 			else badarg = 1;
4105c87c606SMark Murray 			}
4115c87c606SMark Murray 		else if (!strcmp(*args, "-serial"))
4125c87c606SMark Murray 			{
4135c87c606SMark Murray 			if (args[1])
4145c87c606SMark Murray 				{
4155c87c606SMark Murray 				args++;
4165c87c606SMark Murray 				if(!add_ocsp_serial(&req, *args, issuer, ids))
4175c87c606SMark Murray 					goto end;
4185c87c606SMark Murray 				if(!sk_push(reqnames, *args))
4195c87c606SMark Murray 					goto end;
4205c87c606SMark Murray 				}
4215c87c606SMark Murray 			else badarg = 1;
4225c87c606SMark Murray 			}
4235c87c606SMark Murray 		else if (!strcmp(*args, "-index"))
4245c87c606SMark Murray 			{
4255c87c606SMark Murray 			if (args[1])
4265c87c606SMark Murray 				{
4275c87c606SMark Murray 				args++;
4285c87c606SMark Murray 				ridx_filename = *args;
4295c87c606SMark Murray 				}
4305c87c606SMark Murray 			else badarg = 1;
4315c87c606SMark Murray 			}
4325c87c606SMark Murray 		else if (!strcmp(*args, "-CA"))
4335c87c606SMark Murray 			{
4345c87c606SMark Murray 			if (args[1])
4355c87c606SMark Murray 				{
4365c87c606SMark Murray 				args++;
4375c87c606SMark Murray 				rca_filename = *args;
4385c87c606SMark Murray 				}
4395c87c606SMark Murray 			else badarg = 1;
4405c87c606SMark Murray 			}
4415c87c606SMark Murray 		else if (!strcmp (*args, "-nmin"))
4425c87c606SMark Murray 			{
4435c87c606SMark Murray 			if (args[1])
4445c87c606SMark Murray 				{
4455c87c606SMark Murray 				args++;
4465c87c606SMark Murray 				nmin = atol(*args);
4475c87c606SMark Murray 				if (nmin < 0)
4485c87c606SMark Murray 					{
4495c87c606SMark Murray 					BIO_printf(bio_err,
4505c87c606SMark Murray 						"Illegal update period %s\n",
4515c87c606SMark Murray 						*args);
4525c87c606SMark Murray 					badarg = 1;
4535c87c606SMark Murray 					}
4545c87c606SMark Murray 				}
4555c87c606SMark Murray 				if (ndays == -1)
4565c87c606SMark Murray 					ndays = 0;
4575c87c606SMark Murray 			else badarg = 1;
4585c87c606SMark Murray 			}
4595c87c606SMark Murray 		else if (!strcmp (*args, "-nrequest"))
4605c87c606SMark Murray 			{
4615c87c606SMark Murray 			if (args[1])
4625c87c606SMark Murray 				{
4635c87c606SMark Murray 				args++;
4645c87c606SMark Murray 				accept_count = atol(*args);
4655c87c606SMark Murray 				if (accept_count < 0)
4665c87c606SMark Murray 					{
4675c87c606SMark Murray 					BIO_printf(bio_err,
4685c87c606SMark Murray 						"Illegal accept count %s\n",
4695c87c606SMark Murray 						*args);
4705c87c606SMark Murray 					badarg = 1;
4715c87c606SMark Murray 					}
4725c87c606SMark Murray 				}
4735c87c606SMark Murray 			else badarg = 1;
4745c87c606SMark Murray 			}
4755c87c606SMark Murray 		else if (!strcmp (*args, "-ndays"))
4765c87c606SMark Murray 			{
4775c87c606SMark Murray 			if (args[1])
4785c87c606SMark Murray 				{
4795c87c606SMark Murray 				args++;
4805c87c606SMark Murray 				ndays = atol(*args);
4815c87c606SMark Murray 				if (ndays < 0)
4825c87c606SMark Murray 					{
4835c87c606SMark Murray 					BIO_printf(bio_err,
4845c87c606SMark Murray 						"Illegal update period %s\n",
4855c87c606SMark Murray 						*args);
4865c87c606SMark Murray 					badarg = 1;
4875c87c606SMark Murray 					}
4885c87c606SMark Murray 				}
4895c87c606SMark Murray 			else badarg = 1;
4905c87c606SMark Murray 			}
4915c87c606SMark Murray 		else if (!strcmp(*args, "-rsigner"))
4925c87c606SMark Murray 			{
4935c87c606SMark Murray 			if (args[1])
4945c87c606SMark Murray 				{
4955c87c606SMark Murray 				args++;
4965c87c606SMark Murray 				rsignfile = *args;
4975c87c606SMark Murray 				}
4985c87c606SMark Murray 			else badarg = 1;
4995c87c606SMark Murray 			}
5005c87c606SMark Murray 		else if (!strcmp(*args, "-rkey"))
5015c87c606SMark Murray 			{
5025c87c606SMark Murray 			if (args[1])
5035c87c606SMark Murray 				{
5045c87c606SMark Murray 				args++;
5055c87c606SMark Murray 				rkeyfile = *args;
5065c87c606SMark Murray 				}
5075c87c606SMark Murray 			else badarg = 1;
5085c87c606SMark Murray 			}
5095c87c606SMark Murray 		else if (!strcmp(*args, "-rother"))
5105c87c606SMark Murray 			{
5115c87c606SMark Murray 			if (args[1])
5125c87c606SMark Murray 				{
5135c87c606SMark Murray 				args++;
5145c87c606SMark Murray 				rcertfile = *args;
5155c87c606SMark Murray 				}
5165c87c606SMark Murray 			else badarg = 1;
5175c87c606SMark Murray 			}
5185c87c606SMark Murray 		else badarg = 1;
5195c87c606SMark Murray 		args++;
5205c87c606SMark Murray 		}
5215c87c606SMark Murray 
5225c87c606SMark Murray 	/* Have we anything to do? */
5235c87c606SMark Murray 	if (!req && !reqin && !respin && !(port && ridx_filename)) badarg = 1;
5245c87c606SMark Murray 
5255c87c606SMark Murray 	if (badarg)
5265c87c606SMark Murray 		{
5275c87c606SMark Murray 		BIO_printf (bio_err, "OCSP utility\n");
5285c87c606SMark Murray 		BIO_printf (bio_err, "Usage ocsp [options]\n");
5295c87c606SMark Murray 		BIO_printf (bio_err, "where options are\n");
5305c87c606SMark Murray 		BIO_printf (bio_err, "-out file          output filename\n");
5315c87c606SMark Murray 		BIO_printf (bio_err, "-issuer file       issuer certificate\n");
5325c87c606SMark Murray 		BIO_printf (bio_err, "-cert file         certificate to check\n");
5335c87c606SMark Murray 		BIO_printf (bio_err, "-serial n          serial number to check\n");
5345c87c606SMark Murray 		BIO_printf (bio_err, "-signer file       certificate to sign OCSP request with\n");
5355c87c606SMark Murray 		BIO_printf (bio_err, "-signkey file      private key to sign OCSP request with\n");
53650ef0093SJacques Vidrine 		BIO_printf (bio_err, "-sign_other file   additional certificates to include in signed request\n");
5375c87c606SMark Murray 		BIO_printf (bio_err, "-no_certs          don't include any certificates in signed request\n");
5385c87c606SMark Murray 		BIO_printf (bio_err, "-req_text          print text form of request\n");
5395c87c606SMark Murray 		BIO_printf (bio_err, "-resp_text         print text form of response\n");
5405c87c606SMark Murray 		BIO_printf (bio_err, "-text              print text form of request and response\n");
5415c87c606SMark Murray 		BIO_printf (bio_err, "-reqout file       write DER encoded OCSP request to \"file\"\n");
5425c87c606SMark Murray 		BIO_printf (bio_err, "-respout file      write DER encoded OCSP reponse to \"file\"\n");
5435c87c606SMark Murray 		BIO_printf (bio_err, "-reqin file        read DER encoded OCSP request from \"file\"\n");
5445c87c606SMark Murray 		BIO_printf (bio_err, "-respin file       read DER encoded OCSP reponse from \"file\"\n");
5455c87c606SMark Murray 		BIO_printf (bio_err, "-nonce             add OCSP nonce to request\n");
5465c87c606SMark Murray 		BIO_printf (bio_err, "-no_nonce          don't add OCSP nonce to request\n");
5475c87c606SMark Murray 		BIO_printf (bio_err, "-url URL           OCSP responder URL\n");
5485c87c606SMark Murray 		BIO_printf (bio_err, "-host host:n       send OCSP request to host on port n\n");
5495c87c606SMark Murray 		BIO_printf (bio_err, "-path              path to use in OCSP request\n");
5505c87c606SMark Murray 		BIO_printf (bio_err, "-CApath dir        trusted certificates directory\n");
5515c87c606SMark Murray 		BIO_printf (bio_err, "-CAfile file       trusted certificates file\n");
5525c87c606SMark Murray 		BIO_printf (bio_err, "-VAfile file       validator certificates file\n");
5535c87c606SMark Murray 		BIO_printf (bio_err, "-validity_period n maximum validity discrepancy in seconds\n");
5545c87c606SMark Murray 		BIO_printf (bio_err, "-status_age n      maximum status age in seconds\n");
5555c87c606SMark Murray 		BIO_printf (bio_err, "-noverify          don't verify response at all\n");
55650ef0093SJacques Vidrine 		BIO_printf (bio_err, "-verify_other file additional certificates to search for signer\n");
5575c87c606SMark Murray 		BIO_printf (bio_err, "-trust_other       don't verify additional certificates\n");
5585c87c606SMark Murray 		BIO_printf (bio_err, "-no_intern         don't search certificates contained in response for signer\n");
55950ef0093SJacques Vidrine 		BIO_printf (bio_err, "-no_signature_verify don't check signature on response\n");
5605c87c606SMark Murray 		BIO_printf (bio_err, "-no_cert_verify    don't check signing certificate\n");
5615c87c606SMark Murray 		BIO_printf (bio_err, "-no_chain          don't chain verify response\n");
5625c87c606SMark Murray 		BIO_printf (bio_err, "-no_cert_checks    don't do additional checks on signing certificate\n");
5635c87c606SMark Murray 		BIO_printf (bio_err, "-port num		 port to run responder on\n");
5645c87c606SMark Murray 		BIO_printf (bio_err, "-index file	 certificate status index file\n");
5655c87c606SMark Murray 		BIO_printf (bio_err, "-CA file		 CA certificate\n");
5665c87c606SMark Murray 		BIO_printf (bio_err, "-rsigner file	 responder certificate to sign responses with\n");
5675c87c606SMark Murray 		BIO_printf (bio_err, "-rkey file	 responder key to sign responses with\n");
5685c87c606SMark Murray 		BIO_printf (bio_err, "-rother file	 other certificates to include in response\n");
5695c87c606SMark Murray 		BIO_printf (bio_err, "-resp_no_certs     don't include any certificates in response\n");
5705c87c606SMark Murray 		BIO_printf (bio_err, "-nmin n	 	 number of minutes before next update\n");
5715c87c606SMark Murray 		BIO_printf (bio_err, "-ndays n	 	 number of days before next update\n");
5725c87c606SMark Murray 		BIO_printf (bio_err, "-resp_key_id       identify reponse by signing certificate key ID\n");
5735c87c606SMark Murray 		BIO_printf (bio_err, "-nrequest n        number of requests to accept (default unlimited)\n");
5745c87c606SMark Murray 		goto end;
5755c87c606SMark Murray 		}
5765c87c606SMark Murray 
5775c87c606SMark Murray 	if(outfile) out = BIO_new_file(outfile, "w");
5785c87c606SMark Murray 	else out = BIO_new_fp(stdout, BIO_NOCLOSE);
5795c87c606SMark Murray 
5805c87c606SMark Murray 	if(!out)
5815c87c606SMark Murray 		{
5825c87c606SMark Murray 		BIO_printf(bio_err, "Error opening output file\n");
5835c87c606SMark Murray 		goto end;
5845c87c606SMark Murray 		}
5855c87c606SMark Murray 
5865c87c606SMark Murray 	if (!req && (add_nonce != 2)) add_nonce = 0;
5875c87c606SMark Murray 
5885c87c606SMark Murray 	if (!req && reqin)
5895c87c606SMark Murray 		{
5905c87c606SMark Murray 		derbio = BIO_new_file(reqin, "rb");
5915c87c606SMark Murray 		if (!derbio)
5925c87c606SMark Murray 			{
5935c87c606SMark Murray 			BIO_printf(bio_err, "Error Opening OCSP request file\n");
5945c87c606SMark Murray 			goto end;
5955c87c606SMark Murray 			}
5965c87c606SMark Murray 		req = d2i_OCSP_REQUEST_bio(derbio, NULL);
5975c87c606SMark Murray 		BIO_free(derbio);
5985c87c606SMark Murray 		if(!req)
5995c87c606SMark Murray 			{
6005c87c606SMark Murray 			BIO_printf(bio_err, "Error reading OCSP request\n");
6015c87c606SMark Murray 			goto end;
6025c87c606SMark Murray 			}
6035c87c606SMark Murray 		}
6045c87c606SMark Murray 
6055c87c606SMark Murray 	if (!req && port)
6065c87c606SMark Murray 		{
6075c87c606SMark Murray 		acbio = init_responder(port);
6085c87c606SMark Murray 		if (!acbio)
6095c87c606SMark Murray 			goto end;
6105c87c606SMark Murray 		}
6115c87c606SMark Murray 
6125c87c606SMark Murray 	if (rsignfile && !rdb)
6135c87c606SMark Murray 		{
6145c87c606SMark Murray 		if (!rkeyfile) rkeyfile = rsignfile;
6155c87c606SMark Murray 		rsigner = load_cert(bio_err, rsignfile, FORMAT_PEM,
6165c87c606SMark Murray 			NULL, e, "responder certificate");
6175c87c606SMark Murray 		if (!rsigner)
6185c87c606SMark Murray 			{
6195c87c606SMark Murray 			BIO_printf(bio_err, "Error loading responder certificate\n");
6205c87c606SMark Murray 			goto end;
6215c87c606SMark Murray 			}
6225c87c606SMark Murray 		rca_cert = load_cert(bio_err, rca_filename, FORMAT_PEM,
6235c87c606SMark Murray 			NULL, e, "CA certificate");
6245c87c606SMark Murray 		if (rcertfile)
6255c87c606SMark Murray 			{
6265c87c606SMark Murray 			rother = load_certs(bio_err, rcertfile, FORMAT_PEM,
6275c87c606SMark Murray 				NULL, e, "responder other certificates");
6285c87c606SMark Murray 			if (!rother) goto end;
6295c87c606SMark Murray 			}
6305c87c606SMark Murray 		rkey = load_key(bio_err, rkeyfile, FORMAT_PEM, 0, NULL, NULL,
6315c87c606SMark Murray 			"responder private key");
6325c87c606SMark Murray 		if (!rkey)
6335c87c606SMark Murray 			goto end;
6345c87c606SMark Murray 		}
6355c87c606SMark Murray 	if(acbio)
6365c87c606SMark Murray 		BIO_printf(bio_err, "Waiting for OCSP client connections...\n");
6375c87c606SMark Murray 
6385c87c606SMark Murray 	redo_accept:
6395c87c606SMark Murray 
6405c87c606SMark Murray 	if (acbio)
6415c87c606SMark Murray 		{
6425c87c606SMark Murray 		if (!do_responder(&req, &cbio, acbio, port))
6435c87c606SMark Murray 			goto end;
6445c87c606SMark Murray 		if (!req)
6455c87c606SMark Murray 			{
6465c87c606SMark Murray 			resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL);
6475c87c606SMark Murray 			send_ocsp_response(cbio, resp);
6485c87c606SMark Murray 			goto done_resp;
6495c87c606SMark Murray 			}
6505c87c606SMark Murray 		}
6515c87c606SMark Murray 
6525c87c606SMark Murray 	if (!req && (signfile || reqout || host || add_nonce || ridx_filename))
6535c87c606SMark Murray 		{
6545c87c606SMark Murray 		BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
6555c87c606SMark Murray 		goto end;
6565c87c606SMark Murray 		}
6575c87c606SMark Murray 
6585c87c606SMark Murray 	if (req && add_nonce) OCSP_request_add1_nonce(req, NULL, -1);
6595c87c606SMark Murray 
6605c87c606SMark Murray 	if (signfile)
6615c87c606SMark Murray 		{
6625c87c606SMark Murray 		if (!keyfile) keyfile = signfile;
6635c87c606SMark Murray 		signer = load_cert(bio_err, signfile, FORMAT_PEM,
6645c87c606SMark Murray 			NULL, e, "signer certificate");
6655c87c606SMark Murray 		if (!signer)
6665c87c606SMark Murray 			{
6675c87c606SMark Murray 			BIO_printf(bio_err, "Error loading signer certificate\n");
6685c87c606SMark Murray 			goto end;
6695c87c606SMark Murray 			}
6705c87c606SMark Murray 		if (sign_certfile)
6715c87c606SMark Murray 			{
6725c87c606SMark Murray 			sign_other = load_certs(bio_err, sign_certfile, FORMAT_PEM,
6735c87c606SMark Murray 				NULL, e, "signer certificates");
6745c87c606SMark Murray 			if (!sign_other) goto end;
6755c87c606SMark Murray 			}
6765c87c606SMark Murray 		key = load_key(bio_err, keyfile, FORMAT_PEM, 0, NULL, NULL,
6775c87c606SMark Murray 			"signer private key");
6785c87c606SMark Murray 		if (!key)
6795c87c606SMark Murray 			goto end;
6805c87c606SMark Murray 		if (!OCSP_request_sign(req, signer, key, EVP_sha1(), sign_other, sign_flags))
6815c87c606SMark Murray 			{
6825c87c606SMark Murray 			BIO_printf(bio_err, "Error signing OCSP request\n");
6835c87c606SMark Murray 			goto end;
6845c87c606SMark Murray 			}
6855c87c606SMark Murray 		}
6865c87c606SMark Murray 
6875c87c606SMark Murray 	if (req_text && req) OCSP_REQUEST_print(out, req, 0);
6885c87c606SMark Murray 
6895c87c606SMark Murray 	if (reqout)
6905c87c606SMark Murray 		{
6915c87c606SMark Murray 		derbio = BIO_new_file(reqout, "wb");
6925c87c606SMark Murray 		if(!derbio)
6935c87c606SMark Murray 			{
6945c87c606SMark Murray 			BIO_printf(bio_err, "Error opening file %s\n", reqout);
6955c87c606SMark Murray 			goto end;
6965c87c606SMark Murray 			}
6975c87c606SMark Murray 		i2d_OCSP_REQUEST_bio(derbio, req);
6985c87c606SMark Murray 		BIO_free(derbio);
6995c87c606SMark Murray 		}
7005c87c606SMark Murray 
7015c87c606SMark Murray 	if (ridx_filename && (!rkey || !rsigner || !rca_cert))
7025c87c606SMark Murray 		{
7035c87c606SMark Murray 		BIO_printf(bio_err, "Need a responder certificate, key and CA for this operation!\n");
7045c87c606SMark Murray 		goto end;
7055c87c606SMark Murray 		}
7065c87c606SMark Murray 
7075c87c606SMark Murray 	if (ridx_filename && !rdb)
7085c87c606SMark Murray 		{
709ced566fdSJacques Vidrine 		rdb = load_index(ridx_filename, NULL);
710ced566fdSJacques Vidrine 		if (!rdb) goto end;
711ced566fdSJacques Vidrine 		if (!index_index(rdb)) goto end;
7125c87c606SMark Murray 		}
7135c87c606SMark Murray 
7145c87c606SMark Murray 	if (rdb)
7155c87c606SMark Murray 		{
7165c87c606SMark Murray 		i = make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey, rother, rflags, nmin, ndays);
7175c87c606SMark Murray 		if (cbio)
7185c87c606SMark Murray 			send_ocsp_response(cbio, resp);
7195c87c606SMark Murray 		}
7205c87c606SMark Murray 	else if (host)
7215c87c606SMark Murray 		{
722fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_SOCK
723db522d3aSSimon L. B. Nielsen 		resp = process_responder(bio_err, req, host, path,
724db522d3aSSimon L. B. Nielsen 						port, use_ssl, req_timeout);
725db522d3aSSimon L. B. Nielsen 		if (!resp)
726db522d3aSSimon L. B. Nielsen 			goto end;
727fceca8a3SJacques Vidrine #else
728fceca8a3SJacques Vidrine 		BIO_printf(bio_err, "Error creating connect BIO - sockets not supported.\n");
729fceca8a3SJacques Vidrine 		goto end;
730fceca8a3SJacques Vidrine #endif
7315c87c606SMark Murray 		}
7325c87c606SMark Murray 	else if (respin)
7335c87c606SMark Murray 		{
7345c87c606SMark Murray 		derbio = BIO_new_file(respin, "rb");
7355c87c606SMark Murray 		if (!derbio)
7365c87c606SMark Murray 			{
7375c87c606SMark Murray 			BIO_printf(bio_err, "Error Opening OCSP response file\n");
7385c87c606SMark Murray 			goto end;
7395c87c606SMark Murray 			}
7405c87c606SMark Murray 		resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
7415c87c606SMark Murray 		BIO_free(derbio);
7425c87c606SMark Murray 		if(!resp)
7435c87c606SMark Murray 			{
7445c87c606SMark Murray 			BIO_printf(bio_err, "Error reading OCSP response\n");
7455c87c606SMark Murray 			goto end;
7465c87c606SMark Murray 			}
7475c87c606SMark Murray 
7485c87c606SMark Murray 		}
7495c87c606SMark Murray 	else
7505c87c606SMark Murray 		{
7515c87c606SMark Murray 		ret = 0;
7525c87c606SMark Murray 		goto end;
7535c87c606SMark Murray 		}
7545c87c606SMark Murray 
7555c87c606SMark Murray 	done_resp:
7565c87c606SMark Murray 
7575c87c606SMark Murray 	if (respout)
7585c87c606SMark Murray 		{
7595c87c606SMark Murray 		derbio = BIO_new_file(respout, "wb");
7605c87c606SMark Murray 		if(!derbio)
7615c87c606SMark Murray 			{
7625c87c606SMark Murray 			BIO_printf(bio_err, "Error opening file %s\n", respout);
7635c87c606SMark Murray 			goto end;
7645c87c606SMark Murray 			}
7655c87c606SMark Murray 		i2d_OCSP_RESPONSE_bio(derbio, resp);
7665c87c606SMark Murray 		BIO_free(derbio);
7675c87c606SMark Murray 		}
7685c87c606SMark Murray 
7695c87c606SMark Murray 	i = OCSP_response_status(resp);
7705c87c606SMark Murray 
7715c87c606SMark Murray 	if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL)
7725c87c606SMark Murray 		{
7733b4e3dcbSSimon L. B. Nielsen 		BIO_printf(out, "Responder Error: %s (%d)\n",
7745c87c606SMark Murray 				OCSP_response_status_str(i), i);
77550ef0093SJacques Vidrine 		if (ignore_err)
77650ef0093SJacques Vidrine 			goto redo_accept;
7775c87c606SMark Murray 		ret = 0;
7785c87c606SMark Murray 		goto end;
7795c87c606SMark Murray 		}
7805c87c606SMark Murray 
7815c87c606SMark Murray 	if (resp_text) OCSP_RESPONSE_print(out, resp, 0);
7825c87c606SMark Murray 
7835c87c606SMark Murray 	/* If running as responder don't verify our own response */
7845c87c606SMark Murray 	if (cbio)
7855c87c606SMark Murray 		{
7865c87c606SMark Murray 		if (accept_count > 0)
7875c87c606SMark Murray 			accept_count--;
7885c87c606SMark Murray 		/* Redo if more connections needed */
7895c87c606SMark Murray 		if (accept_count)
7905c87c606SMark Murray 			{
7915c87c606SMark Murray 			BIO_free_all(cbio);
7925c87c606SMark Murray 			cbio = NULL;
7935c87c606SMark Murray 			OCSP_REQUEST_free(req);
7945c87c606SMark Murray 			req = NULL;
7955c87c606SMark Murray 			OCSP_RESPONSE_free(resp);
7965c87c606SMark Murray 			resp = NULL;
7975c87c606SMark Murray 			goto redo_accept;
7985c87c606SMark Murray 			}
7995c87c606SMark Murray 		goto end;
8005c87c606SMark Murray 		}
8015c87c606SMark Murray 
8025c87c606SMark Murray 	if (!store)
8035c87c606SMark Murray 		store = setup_verify(bio_err, CAfile, CApath);
8045c87c606SMark Murray 	if (!store)
8055c87c606SMark Murray 		goto end;
8065c87c606SMark Murray 	if (verify_certfile)
8075c87c606SMark Murray 		{
8085c87c606SMark Murray 		verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM,
8095c87c606SMark Murray 			NULL, e, "validator certificate");
8105c87c606SMark Murray 		if (!verify_other) goto end;
8115c87c606SMark Murray 		}
8125c87c606SMark Murray 
8135c87c606SMark Murray 	bs = OCSP_response_get1_basic(resp);
8145c87c606SMark Murray 
8155c87c606SMark Murray 	if (!bs)
8165c87c606SMark Murray 		{
8175c87c606SMark Murray 		BIO_printf(bio_err, "Error parsing response\n");
8185c87c606SMark Murray 		goto end;
8195c87c606SMark Murray 		}
8205c87c606SMark Murray 
8215c87c606SMark Murray 	if (!noverify)
8225c87c606SMark Murray 		{
8235c87c606SMark Murray 		if (req && ((i = OCSP_check_nonce(req, bs)) <= 0))
8245c87c606SMark Murray 			{
8255c87c606SMark Murray 			if (i == -1)
8265c87c606SMark Murray 				BIO_printf(bio_err, "WARNING: no nonce in response\n");
8275c87c606SMark Murray 			else
8285c87c606SMark Murray 				{
8295c87c606SMark Murray 				BIO_printf(bio_err, "Nonce Verify error\n");
8305c87c606SMark Murray 				goto end;
8315c87c606SMark Murray 				}
8325c87c606SMark Murray 			}
8335c87c606SMark Murray 
8345c87c606SMark Murray 		i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
8355c87c606SMark Murray                 if (i < 0) i = OCSP_basic_verify(bs, NULL, store, 0);
8365c87c606SMark Murray 
8375c87c606SMark Murray 		if(i <= 0)
8385c87c606SMark Murray 			{
8393b4e3dcbSSimon L. B. Nielsen 			BIO_printf(bio_err, "Response Verify Failure\n");
8405c87c606SMark Murray 			ERR_print_errors(bio_err);
8415c87c606SMark Murray 			}
8425c87c606SMark Murray 		else
8435c87c606SMark Murray 			BIO_printf(bio_err, "Response verify OK\n");
8445c87c606SMark Murray 
8455c87c606SMark Murray 		}
8465c87c606SMark Murray 
8475c87c606SMark Murray 	if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage))
8485c87c606SMark Murray 		goto end;
8495c87c606SMark Murray 
8505c87c606SMark Murray 	ret = 0;
8515c87c606SMark Murray 
8525c87c606SMark Murray end:
8535c87c606SMark Murray 	ERR_print_errors(bio_err);
8545c87c606SMark Murray 	X509_free(signer);
8555c87c606SMark Murray 	X509_STORE_free(store);
8565c87c606SMark Murray 	EVP_PKEY_free(key);
8575c87c606SMark Murray 	EVP_PKEY_free(rkey);
8585c87c606SMark Murray 	X509_free(issuer);
8595c87c606SMark Murray 	X509_free(cert);
8605c87c606SMark Murray 	X509_free(rsigner);
8615c87c606SMark Murray 	X509_free(rca_cert);
862ced566fdSJacques Vidrine 	free_index(rdb);
8635c87c606SMark Murray 	BIO_free_all(cbio);
8645c87c606SMark Murray 	BIO_free_all(acbio);
8655c87c606SMark Murray 	BIO_free(out);
8665c87c606SMark Murray 	OCSP_REQUEST_free(req);
8675c87c606SMark Murray 	OCSP_RESPONSE_free(resp);
8685c87c606SMark Murray 	OCSP_BASICRESP_free(bs);
8695c87c606SMark Murray 	sk_free(reqnames);
8705c87c606SMark Murray 	sk_OCSP_CERTID_free(ids);
8715c87c606SMark Murray 	sk_X509_pop_free(sign_other, X509_free);
8725c87c606SMark Murray 	sk_X509_pop_free(verify_other, X509_free);
8735c87c606SMark Murray 
8745c87c606SMark Murray 	if (use_ssl != -1)
8755c87c606SMark Murray 		{
8765c87c606SMark Murray 		OPENSSL_free(host);
8775c87c606SMark Murray 		OPENSSL_free(port);
8785c87c606SMark Murray 		OPENSSL_free(path);
8795c87c606SMark Murray 		}
8805c87c606SMark Murray 
8815c87c606SMark Murray 	OPENSSL_EXIT(ret);
8825c87c606SMark Murray }
8835c87c606SMark Murray 
8845c87c606SMark Murray static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
8855c87c606SMark Murray 				STACK_OF(OCSP_CERTID) *ids)
8865c87c606SMark Murray 	{
8875c87c606SMark Murray 	OCSP_CERTID *id;
8885c87c606SMark Murray 	if(!issuer)
8895c87c606SMark Murray 		{
8905c87c606SMark Murray 		BIO_printf(bio_err, "No issuer certificate specified\n");
8915c87c606SMark Murray 		return 0;
8925c87c606SMark Murray 		}
8935c87c606SMark Murray 	if(!*req) *req = OCSP_REQUEST_new();
8945c87c606SMark Murray 	if(!*req) goto err;
8955c87c606SMark Murray 	id = OCSP_cert_to_id(NULL, cert, issuer);
8965c87c606SMark Murray 	if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
8975c87c606SMark Murray 	if(!OCSP_request_add0_id(*req, id)) goto err;
8985c87c606SMark Murray 	return 1;
8995c87c606SMark Murray 
9005c87c606SMark Murray 	err:
9015c87c606SMark Murray 	BIO_printf(bio_err, "Error Creating OCSP request\n");
9025c87c606SMark Murray 	return 0;
9035c87c606SMark Murray 	}
9045c87c606SMark Murray 
9055c87c606SMark Murray static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer,
9065c87c606SMark Murray 				STACK_OF(OCSP_CERTID) *ids)
9075c87c606SMark Murray 	{
9085c87c606SMark Murray 	OCSP_CERTID *id;
9095c87c606SMark Murray 	X509_NAME *iname;
9105c87c606SMark Murray 	ASN1_BIT_STRING *ikey;
9115c87c606SMark Murray 	ASN1_INTEGER *sno;
9125c87c606SMark Murray 	if(!issuer)
9135c87c606SMark Murray 		{
9145c87c606SMark Murray 		BIO_printf(bio_err, "No issuer certificate specified\n");
9155c87c606SMark Murray 		return 0;
9165c87c606SMark Murray 		}
9175c87c606SMark Murray 	if(!*req) *req = OCSP_REQUEST_new();
9185c87c606SMark Murray 	if(!*req) goto err;
9195c87c606SMark Murray 	iname = X509_get_subject_name(issuer);
9205c87c606SMark Murray 	ikey = X509_get0_pubkey_bitstr(issuer);
9215c87c606SMark Murray 	sno = s2i_ASN1_INTEGER(NULL, serial);
9225c87c606SMark Murray 	if(!sno)
9235c87c606SMark Murray 		{
9245c87c606SMark Murray 		BIO_printf(bio_err, "Error converting serial number %s\n", serial);
9255c87c606SMark Murray 		return 0;
9265c87c606SMark Murray 		}
9275c87c606SMark Murray 	id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno);
9285c87c606SMark Murray 	ASN1_INTEGER_free(sno);
9295c87c606SMark Murray 	if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
9305c87c606SMark Murray 	if(!OCSP_request_add0_id(*req, id)) goto err;
9315c87c606SMark Murray 	return 1;
9325c87c606SMark Murray 
9335c87c606SMark Murray 	err:
9345c87c606SMark Murray 	BIO_printf(bio_err, "Error Creating OCSP request\n");
9355c87c606SMark Murray 	return 0;
9365c87c606SMark Murray 	}
9375c87c606SMark Murray 
9385c87c606SMark Murray static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
9395c87c606SMark Murray 					STACK *names, STACK_OF(OCSP_CERTID) *ids,
9405c87c606SMark Murray 					long nsec, long maxage)
9415c87c606SMark Murray 	{
9425c87c606SMark Murray 	OCSP_CERTID *id;
9435c87c606SMark Murray 	char *name;
9445c87c606SMark Murray 	int i;
9455c87c606SMark Murray 
9465c87c606SMark Murray 	int status, reason;
9475c87c606SMark Murray 
9485c87c606SMark Murray 	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
9495c87c606SMark Murray 
9505c87c606SMark Murray 	if (!bs || !req || !sk_num(names) || !sk_OCSP_CERTID_num(ids))
9515c87c606SMark Murray 		return 1;
9525c87c606SMark Murray 
9535c87c606SMark Murray 	for (i = 0; i < sk_OCSP_CERTID_num(ids); i++)
9545c87c606SMark Murray 		{
9555c87c606SMark Murray 		id = sk_OCSP_CERTID_value(ids, i);
9565c87c606SMark Murray 		name = sk_value(names, i);
9575c87c606SMark Murray 		BIO_printf(out, "%s: ", name);
9585c87c606SMark Murray 
9595c87c606SMark Murray 		if(!OCSP_resp_find_status(bs, id, &status, &reason,
9605c87c606SMark Murray 					&rev, &thisupd, &nextupd))
9615c87c606SMark Murray 			{
9625c87c606SMark Murray 			BIO_puts(out, "ERROR: No Status found.\n");
9635c87c606SMark Murray 			continue;
9645c87c606SMark Murray 			}
9655c87c606SMark Murray 
9665c87c606SMark Murray 		/* Check validity: if invalid write to output BIO so we
9675c87c606SMark Murray 		 * know which response this refers to.
9685c87c606SMark Murray 		 */
9695c87c606SMark Murray 		if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage))
9705c87c606SMark Murray 			{
9715c87c606SMark Murray 			BIO_puts(out, "WARNING: Status times invalid.\n");
9725c87c606SMark Murray 			ERR_print_errors(out);
9735c87c606SMark Murray 			}
9745c87c606SMark Murray 		BIO_printf(out, "%s\n", OCSP_cert_status_str(status));
9755c87c606SMark Murray 
9765c87c606SMark Murray 		BIO_puts(out, "\tThis Update: ");
9775c87c606SMark Murray 		ASN1_GENERALIZEDTIME_print(out, thisupd);
9785c87c606SMark Murray 		BIO_puts(out, "\n");
9795c87c606SMark Murray 
9805c87c606SMark Murray 		if(nextupd)
9815c87c606SMark Murray 			{
9825c87c606SMark Murray 			BIO_puts(out, "\tNext Update: ");
9835c87c606SMark Murray 			ASN1_GENERALIZEDTIME_print(out, nextupd);
9845c87c606SMark Murray 			BIO_puts(out, "\n");
9855c87c606SMark Murray 			}
9865c87c606SMark Murray 
9875c87c606SMark Murray 		if (status != V_OCSP_CERTSTATUS_REVOKED)
9885c87c606SMark Murray 			continue;
9895c87c606SMark Murray 
9905c87c606SMark Murray 		if (reason != -1)
9915c87c606SMark Murray 			BIO_printf(out, "\tReason: %s\n",
9925c87c606SMark Murray 				OCSP_crl_reason_str(reason));
9935c87c606SMark Murray 
9945c87c606SMark Murray 		BIO_puts(out, "\tRevocation Time: ");
9955c87c606SMark Murray 		ASN1_GENERALIZEDTIME_print(out, rev);
9965c87c606SMark Murray 		BIO_puts(out, "\n");
9975c87c606SMark Murray 		}
9985c87c606SMark Murray 
9995c87c606SMark Murray 	return 1;
10005c87c606SMark Murray 	}
10015c87c606SMark Murray 
10025c87c606SMark Murray 
1003ced566fdSJacques Vidrine static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, CA_DB *db,
10045c87c606SMark Murray 			X509 *ca, X509 *rcert, EVP_PKEY *rkey,
10055c87c606SMark Murray 			STACK_OF(X509) *rother, unsigned long flags,
10065c87c606SMark Murray 			int nmin, int ndays)
10075c87c606SMark Murray 	{
10085c87c606SMark Murray 	ASN1_TIME *thisupd = NULL, *nextupd = NULL;
10095c87c606SMark Murray 	OCSP_CERTID *cid, *ca_id = NULL;
10105c87c606SMark Murray 	OCSP_BASICRESP *bs = NULL;
10115c87c606SMark Murray 	int i, id_count, ret = 1;
10125c87c606SMark Murray 
10135c87c606SMark Murray 
10145c87c606SMark Murray 	id_count = OCSP_request_onereq_count(req);
10155c87c606SMark Murray 
10165c87c606SMark Murray 	if (id_count <= 0)
10175c87c606SMark Murray 		{
10185c87c606SMark Murray 		*resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL);
10195c87c606SMark Murray 		goto end;
10205c87c606SMark Murray 		}
10215c87c606SMark Murray 
10225c87c606SMark Murray 	ca_id = OCSP_cert_to_id(EVP_sha1(), NULL, ca);
10235c87c606SMark Murray 
10245c87c606SMark Murray 	bs = OCSP_BASICRESP_new();
10255c87c606SMark Murray 	thisupd = X509_gmtime_adj(NULL, 0);
10265c87c606SMark Murray 	if (ndays != -1)
10275c87c606SMark Murray 		nextupd = X509_gmtime_adj(NULL, nmin * 60 + ndays * 3600 * 24 );
10285c87c606SMark Murray 
10295c87c606SMark Murray 	/* Examine each certificate id in the request */
10305c87c606SMark Murray 	for (i = 0; i < id_count; i++)
10315c87c606SMark Murray 		{
10325c87c606SMark Murray 		OCSP_ONEREQ *one;
10335c87c606SMark Murray 		ASN1_INTEGER *serial;
10345c87c606SMark Murray 		char **inf;
10355c87c606SMark Murray 		one = OCSP_request_onereq_get0(req, i);
10365c87c606SMark Murray 		cid = OCSP_onereq_get0_id(one);
10375c87c606SMark Murray 		/* Is this request about our CA? */
10385c87c606SMark Murray 		if (OCSP_id_issuer_cmp(ca_id, cid))
10395c87c606SMark Murray 			{
10405c87c606SMark Murray 			OCSP_basic_add1_status(bs, cid,
10415c87c606SMark Murray 						V_OCSP_CERTSTATUS_UNKNOWN,
10425c87c606SMark Murray 						0, NULL,
10435c87c606SMark Murray 						thisupd, nextupd);
10445c87c606SMark Murray 			continue;
10455c87c606SMark Murray 			}
10465c87c606SMark Murray 		OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid);
10475c87c606SMark Murray 		inf = lookup_serial(db, serial);
10485c87c606SMark Murray 		if (!inf)
10495c87c606SMark Murray 			OCSP_basic_add1_status(bs, cid,
10505c87c606SMark Murray 						V_OCSP_CERTSTATUS_UNKNOWN,
10515c87c606SMark Murray 						0, NULL,
10525c87c606SMark Murray 						thisupd, nextupd);
10535c87c606SMark Murray 		else if (inf[DB_type][0] == DB_TYPE_VAL)
10545c87c606SMark Murray 			OCSP_basic_add1_status(bs, cid,
10555c87c606SMark Murray 						V_OCSP_CERTSTATUS_GOOD,
10565c87c606SMark Murray 						0, NULL,
10575c87c606SMark Murray 						thisupd, nextupd);
10585c87c606SMark Murray 		else if (inf[DB_type][0] == DB_TYPE_REV)
10595c87c606SMark Murray 			{
10605c87c606SMark Murray 			ASN1_OBJECT *inst = NULL;
10615c87c606SMark Murray 			ASN1_TIME *revtm = NULL;
10625c87c606SMark Murray 			ASN1_GENERALIZEDTIME *invtm = NULL;
10635c87c606SMark Murray 			OCSP_SINGLERESP *single;
10645c87c606SMark Murray 			int reason = -1;
10655c87c606SMark Murray 			unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]);
10665c87c606SMark Murray 			single = OCSP_basic_add1_status(bs, cid,
10675c87c606SMark Murray 						V_OCSP_CERTSTATUS_REVOKED,
10685c87c606SMark Murray 						reason, revtm,
10695c87c606SMark Murray 						thisupd, nextupd);
10705c87c606SMark Murray 			if (invtm)
10715c87c606SMark Murray 				OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date, invtm, 0, 0);
10725c87c606SMark Murray 			else if (inst)
10735c87c606SMark Murray 				OCSP_SINGLERESP_add1_ext_i2d(single, NID_hold_instruction_code, inst, 0, 0);
10745c87c606SMark Murray 			ASN1_OBJECT_free(inst);
10755c87c606SMark Murray 			ASN1_TIME_free(revtm);
10765c87c606SMark Murray 			ASN1_GENERALIZEDTIME_free(invtm);
10775c87c606SMark Murray 			}
10785c87c606SMark Murray 		}
10795c87c606SMark Murray 
10805c87c606SMark Murray 	OCSP_copy_nonce(bs, req);
10815c87c606SMark Murray 
10825c87c606SMark Murray 	OCSP_basic_sign(bs, rcert, rkey, EVP_sha1(), rother, flags);
10835c87c606SMark Murray 
10845c87c606SMark Murray 	*resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs);
10855c87c606SMark Murray 
10865c87c606SMark Murray 	end:
10875c87c606SMark Murray 	ASN1_TIME_free(thisupd);
10885c87c606SMark Murray 	ASN1_TIME_free(nextupd);
10895c87c606SMark Murray 	OCSP_CERTID_free(ca_id);
10905c87c606SMark Murray 	OCSP_BASICRESP_free(bs);
10915c87c606SMark Murray 	return ret;
10925c87c606SMark Murray 
10935c87c606SMark Murray 	}
10945c87c606SMark Murray 
1095ced566fdSJacques Vidrine static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
10965c87c606SMark Murray 	{
10975c87c606SMark Murray 	int i;
10985c87c606SMark Murray 	BIGNUM *bn = NULL;
10995c87c606SMark Murray 	char *itmp, *row[DB_NUMBER],**rrow;
11005c87c606SMark Murray 	for (i = 0; i < DB_NUMBER; i++) row[i] = NULL;
11015c87c606SMark Murray 	bn = ASN1_INTEGER_to_BN(ser,NULL);
1102db522d3aSSimon L. B. Nielsen 	OPENSSL_assert(bn); /* FIXME: should report an error at this point and abort */
11035c87c606SMark Murray 	if (BN_is_zero(bn))
11045c87c606SMark Murray 		itmp = BUF_strdup("00");
11055c87c606SMark Murray 	else
11065c87c606SMark Murray 		itmp = BN_bn2hex(bn);
11075c87c606SMark Murray 	row[DB_serial] = itmp;
11085c87c606SMark Murray 	BN_free(bn);
1109ced566fdSJacques Vidrine 	rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
11105c87c606SMark Murray 	OPENSSL_free(itmp);
11115c87c606SMark Murray 	return rrow;
11125c87c606SMark Murray 	}
11135c87c606SMark Murray 
11145c87c606SMark Murray /* Quick and dirty OCSP server: read in and parse input request */
11155c87c606SMark Murray 
11165c87c606SMark Murray static BIO *init_responder(char *port)
11175c87c606SMark Murray 	{
11185c87c606SMark Murray 	BIO *acbio = NULL, *bufbio = NULL;
11195c87c606SMark Murray 	bufbio = BIO_new(BIO_f_buffer());
11205c87c606SMark Murray 	if (!bufbio)
11215c87c606SMark Murray 		goto err;
1122fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_SOCK
11235c87c606SMark Murray 	acbio = BIO_new_accept(port);
1124fceca8a3SJacques Vidrine #else
1125fceca8a3SJacques Vidrine 	BIO_printf(bio_err, "Error setting up accept BIO - sockets not supported.\n");
1126fceca8a3SJacques Vidrine #endif
11275c87c606SMark Murray 	if (!acbio)
11285c87c606SMark Murray 		goto err;
11295c87c606SMark Murray 	BIO_set_accept_bios(acbio, bufbio);
11305c87c606SMark Murray 	bufbio = NULL;
11315c87c606SMark Murray 
11325c87c606SMark Murray 	if (BIO_do_accept(acbio) <= 0)
11335c87c606SMark Murray 		{
11345c87c606SMark Murray 			BIO_printf(bio_err, "Error setting up accept BIO\n");
11355c87c606SMark Murray 			ERR_print_errors(bio_err);
11365c87c606SMark Murray 			goto err;
11375c87c606SMark Murray 		}
11385c87c606SMark Murray 
11395c87c606SMark Murray 	return acbio;
11405c87c606SMark Murray 
11415c87c606SMark Murray 	err:
11425c87c606SMark Murray 	BIO_free_all(acbio);
11435c87c606SMark Murray 	BIO_free(bufbio);
11445c87c606SMark Murray 	return NULL;
11455c87c606SMark Murray 	}
11465c87c606SMark Murray 
11475c87c606SMark Murray static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, char *port)
11485c87c606SMark Murray 	{
11495c87c606SMark Murray 	int have_post = 0, len;
11505c87c606SMark Murray 	OCSP_REQUEST *req = NULL;
11515c87c606SMark Murray 	char inbuf[1024];
11525c87c606SMark Murray 	BIO *cbio = NULL;
11535c87c606SMark Murray 
11545c87c606SMark Murray 	if (BIO_do_accept(acbio) <= 0)
11555c87c606SMark Murray 		{
11565c87c606SMark Murray 			BIO_printf(bio_err, "Error accepting connection\n");
11575c87c606SMark Murray 			ERR_print_errors(bio_err);
11585c87c606SMark Murray 			return 0;
11595c87c606SMark Murray 		}
11605c87c606SMark Murray 
11615c87c606SMark Murray 	cbio = BIO_pop(acbio);
11625c87c606SMark Murray 	*pcbio = cbio;
11635c87c606SMark Murray 
11645c87c606SMark Murray 	for(;;)
11655c87c606SMark Murray 		{
11665c87c606SMark Murray 		len = BIO_gets(cbio, inbuf, sizeof inbuf);
11675c87c606SMark Murray 		if (len <= 0)
11685c87c606SMark Murray 			return 1;
11695c87c606SMark Murray 		/* Look for "POST" signalling start of query */
11705c87c606SMark Murray 		if (!have_post)
11715c87c606SMark Murray 			{
11725c87c606SMark Murray 			if(strncmp(inbuf, "POST", 4))
11735c87c606SMark Murray 				{
11745c87c606SMark Murray 				BIO_printf(bio_err, "Invalid request\n");
11755c87c606SMark Murray 				return 1;
11765c87c606SMark Murray 				}
11775c87c606SMark Murray 			have_post = 1;
11785c87c606SMark Murray 			}
11795c87c606SMark Murray 		/* Look for end of headers */
11805c87c606SMark Murray 		if ((inbuf[0] == '\r') || (inbuf[0] == '\n'))
11815c87c606SMark Murray 			break;
11825c87c606SMark Murray 		}
11835c87c606SMark Murray 
11845c87c606SMark Murray 	/* Try to read OCSP request */
11855c87c606SMark Murray 
11865c87c606SMark Murray 	req = d2i_OCSP_REQUEST_bio(cbio, NULL);
11875c87c606SMark Murray 
11885c87c606SMark Murray 	if (!req)
11895c87c606SMark Murray 		{
11905c87c606SMark Murray 		BIO_printf(bio_err, "Error parsing OCSP request\n");
11915c87c606SMark Murray 		ERR_print_errors(bio_err);
11925c87c606SMark Murray 		}
11935c87c606SMark Murray 
11945c87c606SMark Murray 	*preq = req;
11955c87c606SMark Murray 
11965c87c606SMark Murray 	return 1;
11975c87c606SMark Murray 
11985c87c606SMark Murray 	}
11995c87c606SMark Murray 
12005c87c606SMark Murray static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
12015c87c606SMark Murray 	{
12025c87c606SMark Murray 	char http_resp[] =
12035c87c606SMark Murray 		"HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n"
12045c87c606SMark Murray 		"Content-Length: %d\r\n\r\n";
12055c87c606SMark Murray 	if (!cbio)
12065c87c606SMark Murray 		return 0;
12075c87c606SMark Murray 	BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL));
12085c87c606SMark Murray 	i2d_OCSP_RESPONSE_bio(cbio, resp);
1209db522d3aSSimon L. B. Nielsen 	(void)BIO_flush(cbio);
12105c87c606SMark Murray 	return 1;
12115c87c606SMark Murray 	}
12125c87c606SMark Murray 
1213db522d3aSSimon L. B. Nielsen static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path,
1214db522d3aSSimon L. B. Nielsen 				OCSP_REQUEST *req, int req_timeout)
1215db522d3aSSimon L. B. Nielsen 	{
1216db522d3aSSimon L. B. Nielsen 	int fd;
1217db522d3aSSimon L. B. Nielsen 	int rv;
1218db522d3aSSimon L. B. Nielsen 	OCSP_REQ_CTX *ctx = NULL;
1219db522d3aSSimon L. B. Nielsen 	OCSP_RESPONSE *rsp = NULL;
1220db522d3aSSimon L. B. Nielsen 	fd_set confds;
1221db522d3aSSimon L. B. Nielsen 	struct timeval tv;
1222db522d3aSSimon L. B. Nielsen 
1223db522d3aSSimon L. B. Nielsen 	if (req_timeout != -1)
1224db522d3aSSimon L. B. Nielsen 		BIO_set_nbio(cbio, 1);
1225db522d3aSSimon L. B. Nielsen 
1226db522d3aSSimon L. B. Nielsen 	rv = BIO_do_connect(cbio);
1227db522d3aSSimon L. B. Nielsen 
1228db522d3aSSimon L. B. Nielsen 	if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio)))
1229db522d3aSSimon L. B. Nielsen 		{
1230db522d3aSSimon L. B. Nielsen 		BIO_puts(err, "Error connecting BIO\n");
1231db522d3aSSimon L. B. Nielsen 		return NULL;
1232db522d3aSSimon L. B. Nielsen 		}
1233db522d3aSSimon L. B. Nielsen 
1234db522d3aSSimon L. B. Nielsen 	if (req_timeout == -1)
1235db522d3aSSimon L. B. Nielsen 		return OCSP_sendreq_bio(cbio, path, req);
1236db522d3aSSimon L. B. Nielsen 
1237db522d3aSSimon L. B. Nielsen 	if (BIO_get_fd(cbio, &fd) <= 0)
1238db522d3aSSimon L. B. Nielsen 		{
1239db522d3aSSimon L. B. Nielsen 		BIO_puts(err, "Can't get connection fd\n");
1240db522d3aSSimon L. B. Nielsen 		goto err;
1241db522d3aSSimon L. B. Nielsen 		}
1242db522d3aSSimon L. B. Nielsen 
1243db522d3aSSimon L. B. Nielsen 	if (rv <= 0)
1244db522d3aSSimon L. B. Nielsen 		{
1245db522d3aSSimon L. B. Nielsen 		FD_ZERO(&confds);
1246db522d3aSSimon L. B. Nielsen 		openssl_fdset(fd, &confds);
1247db522d3aSSimon L. B. Nielsen 		tv.tv_usec = 0;
1248db522d3aSSimon L. B. Nielsen 		tv.tv_sec = req_timeout;
1249db522d3aSSimon L. B. Nielsen 		rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
1250db522d3aSSimon L. B. Nielsen 		if (rv == 0)
1251db522d3aSSimon L. B. Nielsen 			{
1252db522d3aSSimon L. B. Nielsen 			BIO_puts(err, "Timeout on connect\n");
1253db522d3aSSimon L. B. Nielsen 			return NULL;
1254db522d3aSSimon L. B. Nielsen 			}
1255db522d3aSSimon L. B. Nielsen 		}
1256db522d3aSSimon L. B. Nielsen 
1257db522d3aSSimon L. B. Nielsen 
1258db522d3aSSimon L. B. Nielsen 	ctx = OCSP_sendreq_new(cbio, path, req, -1);
1259db522d3aSSimon L. B. Nielsen 	if (!ctx)
1260db522d3aSSimon L. B. Nielsen 		return NULL;
1261db522d3aSSimon L. B. Nielsen 
1262db522d3aSSimon L. B. Nielsen 	for (;;)
1263db522d3aSSimon L. B. Nielsen 		{
1264db522d3aSSimon L. B. Nielsen 		rv = OCSP_sendreq_nbio(&rsp, ctx);
1265db522d3aSSimon L. B. Nielsen 		if (rv != -1)
1266db522d3aSSimon L. B. Nielsen 			break;
1267db522d3aSSimon L. B. Nielsen 		FD_ZERO(&confds);
1268db522d3aSSimon L. B. Nielsen 		openssl_fdset(fd, &confds);
1269db522d3aSSimon L. B. Nielsen 		tv.tv_usec = 0;
1270db522d3aSSimon L. B. Nielsen 		tv.tv_sec = req_timeout;
1271db522d3aSSimon L. B. Nielsen 		if (BIO_should_read(cbio))
1272db522d3aSSimon L. B. Nielsen 			rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv);
1273db522d3aSSimon L. B. Nielsen 		else if (BIO_should_write(cbio))
1274db522d3aSSimon L. B. Nielsen 			rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
1275db522d3aSSimon L. B. Nielsen 		else
1276db522d3aSSimon L. B. Nielsen 			{
1277db522d3aSSimon L. B. Nielsen 			BIO_puts(err, "Unexpected retry condition\n");
1278db522d3aSSimon L. B. Nielsen 			goto err;
1279db522d3aSSimon L. B. Nielsen 			}
1280db522d3aSSimon L. B. Nielsen 		if (rv == 0)
1281db522d3aSSimon L. B. Nielsen 			{
1282db522d3aSSimon L. B. Nielsen 			BIO_puts(err, "Timeout on request\n");
1283db522d3aSSimon L. B. Nielsen 			break;
1284db522d3aSSimon L. B. Nielsen 			}
1285db522d3aSSimon L. B. Nielsen 		if (rv == -1)
1286db522d3aSSimon L. B. Nielsen 			{
1287db522d3aSSimon L. B. Nielsen 			BIO_puts(err, "Select error\n");
1288db522d3aSSimon L. B. Nielsen 			break;
1289db522d3aSSimon L. B. Nielsen 			}
1290db522d3aSSimon L. B. Nielsen 
1291db522d3aSSimon L. B. Nielsen 		}
1292db522d3aSSimon L. B. Nielsen 	err:
1293db522d3aSSimon L. B. Nielsen 	if (ctx)
1294db522d3aSSimon L. B. Nielsen 		OCSP_REQ_CTX_free(ctx);
1295db522d3aSSimon L. B. Nielsen 
1296db522d3aSSimon L. B. Nielsen 	return rsp;
1297db522d3aSSimon L. B. Nielsen 	}
1298db522d3aSSimon L. B. Nielsen 
1299db522d3aSSimon L. B. Nielsen OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req,
1300db522d3aSSimon L. B. Nielsen 			char *host, char *path, char *port, int use_ssl,
1301db522d3aSSimon L. B. Nielsen 			int req_timeout)
1302db522d3aSSimon L. B. Nielsen 	{
1303db522d3aSSimon L. B. Nielsen 	BIO *cbio = NULL;
1304db522d3aSSimon L. B. Nielsen 	SSL_CTX *ctx = NULL;
1305db522d3aSSimon L. B. Nielsen 	OCSP_RESPONSE *resp = NULL;
1306db522d3aSSimon L. B. Nielsen 	cbio = BIO_new_connect(host);
1307db522d3aSSimon L. B. Nielsen 	if (!cbio)
1308db522d3aSSimon L. B. Nielsen 		{
1309db522d3aSSimon L. B. Nielsen 		BIO_printf(err, "Error creating connect BIO\n");
1310db522d3aSSimon L. B. Nielsen 		goto end;
1311db522d3aSSimon L. B. Nielsen 		}
1312db522d3aSSimon L. B. Nielsen 	if (port) BIO_set_conn_port(cbio, port);
1313db522d3aSSimon L. B. Nielsen 	if (use_ssl == 1)
1314db522d3aSSimon L. B. Nielsen 		{
1315db522d3aSSimon L. B. Nielsen 		BIO *sbio;
1316db522d3aSSimon L. B. Nielsen #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
1317db522d3aSSimon L. B. Nielsen 		ctx = SSL_CTX_new(SSLv23_client_method());
1318db522d3aSSimon L. B. Nielsen #elif !defined(OPENSSL_NO_SSL3)
1319db522d3aSSimon L. B. Nielsen 		ctx = SSL_CTX_new(SSLv3_client_method());
1320db522d3aSSimon L. B. Nielsen #elif !defined(OPENSSL_NO_SSL2)
1321db522d3aSSimon L. B. Nielsen 		ctx = SSL_CTX_new(SSLv2_client_method());
1322db522d3aSSimon L. B. Nielsen #else
1323db522d3aSSimon L. B. Nielsen 		BIO_printf(err, "SSL is disabled\n");
1324db522d3aSSimon L. B. Nielsen 			goto end;
1325db522d3aSSimon L. B. Nielsen #endif
1326db522d3aSSimon L. B. Nielsen 		if (ctx == NULL)
1327db522d3aSSimon L. B. Nielsen 			{
1328db522d3aSSimon L. B. Nielsen 			BIO_printf(err, "Error creating SSL context.\n");
1329db522d3aSSimon L. B. Nielsen 			goto end;
1330db522d3aSSimon L. B. Nielsen 			}
1331db522d3aSSimon L. B. Nielsen 		SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
1332db522d3aSSimon L. B. Nielsen 		sbio = BIO_new_ssl(ctx, 1);
1333db522d3aSSimon L. B. Nielsen 		cbio = BIO_push(sbio, cbio);
1334db522d3aSSimon L. B. Nielsen 		}
1335db522d3aSSimon L. B. Nielsen 	resp = query_responder(err, cbio, path, req, req_timeout);
1336db522d3aSSimon L. B. Nielsen 	if (!resp)
1337db522d3aSSimon L. B. Nielsen 		BIO_printf(bio_err, "Error querying OCSP responsder\n");
1338db522d3aSSimon L. B. Nielsen 	end:
1339db522d3aSSimon L. B. Nielsen 	if (ctx)
1340db522d3aSSimon L. B. Nielsen 		SSL_CTX_free(ctx);
1341db522d3aSSimon L. B. Nielsen 	if (cbio)
1342db522d3aSSimon L. B. Nielsen 		BIO_free_all(cbio);
1343db522d3aSSimon L. B. Nielsen 	return resp;
1344db522d3aSSimon L. B. Nielsen 	}
1345db522d3aSSimon L. B. Nielsen 
1346fceca8a3SJacques Vidrine #endif
1347