xref: /freebsd/crypto/openssl/apps/ocsp.c (revision 8180e704acbcb94cca5b29bf64a208add3e1edb6)
15c87c606SMark Murray /* ocsp.c */
26f9291ceSJung-uk Kim /*
36f9291ceSJung-uk Kim  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
46f9291ceSJung-uk Kim  * 2000.
55c87c606SMark Murray  */
65c87c606SMark Murray /* ====================================================================
75c87c606SMark Murray  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
85c87c606SMark Murray  *
95c87c606SMark Murray  * Redistribution and use in source and binary forms, with or without
105c87c606SMark Murray  * modification, are permitted provided that the following conditions
115c87c606SMark Murray  * are met:
125c87c606SMark Murray  *
135c87c606SMark Murray  * 1. Redistributions of source code must retain the above copyright
145c87c606SMark Murray  *    notice, this list of conditions and the following disclaimer.
155c87c606SMark Murray  *
165c87c606SMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
175c87c606SMark Murray  *    notice, this list of conditions and the following disclaimer in
185c87c606SMark Murray  *    the documentation and/or other materials provided with the
195c87c606SMark Murray  *    distribution.
205c87c606SMark Murray  *
215c87c606SMark Murray  * 3. All advertising materials mentioning features or use of this
225c87c606SMark Murray  *    software must display the following acknowledgment:
235c87c606SMark Murray  *    "This product includes software developed by the OpenSSL Project
245c87c606SMark Murray  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
255c87c606SMark Murray  *
265c87c606SMark Murray  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
275c87c606SMark Murray  *    endorse or promote products derived from this software without
285c87c606SMark Murray  *    prior written permission. For written permission, please contact
295c87c606SMark Murray  *    licensing@OpenSSL.org.
305c87c606SMark Murray  *
315c87c606SMark Murray  * 5. Products derived from this software may not be called "OpenSSL"
325c87c606SMark Murray  *    nor may "OpenSSL" appear in their names without prior written
335c87c606SMark Murray  *    permission of the OpenSSL Project.
345c87c606SMark Murray  *
355c87c606SMark Murray  * 6. Redistributions of any form whatsoever must retain the following
365c87c606SMark Murray  *    acknowledgment:
375c87c606SMark Murray  *    "This product includes software developed by the OpenSSL Project
385c87c606SMark Murray  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
395c87c606SMark Murray  *
405c87c606SMark Murray  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
415c87c606SMark Murray  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
425c87c606SMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
435c87c606SMark Murray  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
445c87c606SMark Murray  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
455c87c606SMark Murray  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
465c87c606SMark Murray  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
475c87c606SMark Murray  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
485c87c606SMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
495c87c606SMark Murray  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
505c87c606SMark Murray  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
515c87c606SMark Murray  * OF THE POSSIBILITY OF SUCH DAMAGE.
525c87c606SMark Murray  * ====================================================================
535c87c606SMark Murray  *
545c87c606SMark Murray  * This product includes cryptographic software written by Eric Young
555c87c606SMark Murray  * (eay@cryptsoft.com).  This product includes software written by Tim
565c87c606SMark Murray  * Hudson (tjh@cryptsoft.com).
575c87c606SMark Murray  *
585c87c606SMark Murray  */
59fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_OCSP
601f13597dSJung-uk Kim 
611f13597dSJung-uk Kim # ifdef OPENSSL_SYS_VMS
621f13597dSJung-uk Kim #  define _XOPEN_SOURCE_EXTENDED/* So fd_set and friends get properly defined
636f9291ceSJung-uk Kim                                  * on OpenVMS */
641f13597dSJung-uk Kim # endif
651f13597dSJung-uk Kim 
66db522d3aSSimon L. B. Nielsen # define USE_SOCKETS
671f13597dSJung-uk Kim 
685c87c606SMark Murray # include <stdio.h>
69db522d3aSSimon L. B. Nielsen # include <stdlib.h>
705c87c606SMark Murray # include <string.h>
711f13597dSJung-uk Kim # include <time.h>
726f9291ceSJung-uk Kim # include "apps.h"              /* needs to be included before the openssl
736f9291ceSJung-uk Kim                                  * headers! */
74db522d3aSSimon L. B. Nielsen # include <openssl/e_os2.h>
751f13597dSJung-uk Kim # include <openssl/crypto.h>
76db522d3aSSimon L. B. Nielsen # include <openssl/err.h>
771f13597dSJung-uk Kim # include <openssl/ssl.h>
781f13597dSJung-uk Kim # include <openssl/evp.h>
791f13597dSJung-uk Kim # include <openssl/bn.h>
801f13597dSJung-uk Kim # include <openssl/x509v3.h>
811f13597dSJung-uk Kim 
821f13597dSJung-uk Kim # if defined(NETWARE_CLIB)
831f13597dSJung-uk Kim #  ifdef NETWARE_BSDSOCK
841f13597dSJung-uk Kim #   include <sys/socket.h>
851f13597dSJung-uk Kim #   include <sys/bsdskt.h>
861f13597dSJung-uk Kim #  else
871f13597dSJung-uk Kim #   include <novsock2.h>
881f13597dSJung-uk Kim #  endif
891f13597dSJung-uk Kim # elif defined(NETWARE_LIBC)
901f13597dSJung-uk Kim #  ifdef NETWARE_BSDSOCK
911f13597dSJung-uk Kim #   include <sys/select.h>
921f13597dSJung-uk Kim #  else
931f13597dSJung-uk Kim #   include <novsock2.h>
941f13597dSJung-uk Kim #  endif
951f13597dSJung-uk Kim # endif
965c87c606SMark Murray 
975c87c606SMark Murray /* Maximum leeway in validity period: default 5 minutes */
985c87c606SMark Murray # define MAX_VALIDITY_PERIOD     (5 * 60)
995c87c606SMark Murray 
1006f9291ceSJung-uk Kim static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert,
1016f9291ceSJung-uk Kim                          const EVP_MD *cert_id_md, X509 *issuer,
1025c87c606SMark Murray                          STACK_OF(OCSP_CERTID) *ids);
1036f9291ceSJung-uk Kim static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
1046f9291ceSJung-uk Kim                            const EVP_MD *cert_id_md, X509 *issuer,
1055c87c606SMark Murray                            STACK_OF(OCSP_CERTID) *ids);
1065c87c606SMark Murray static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
1071f13597dSJung-uk Kim                               STACK_OF(OPENSSL_STRING) *names,
1081f13597dSJung-uk Kim                               STACK_OF(OCSP_CERTID) *ids, long nsec,
1091f13597dSJung-uk Kim                               long maxage);
1105c87c606SMark Murray 
1116f9291ceSJung-uk Kim static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req,
1126f9291ceSJung-uk Kim                               CA_DB *db, X509 *ca, X509 *rcert,
1137bded2dbSJung-uk Kim                               EVP_PKEY *rkey, const EVP_MD *md,
1147bded2dbSJung-uk Kim                               STACK_OF(X509) *rother, unsigned long flags,
1157bded2dbSJung-uk Kim                               int nmin, int ndays, int badsig);
1165c87c606SMark Murray 
117ced566fdSJacques Vidrine static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser);
1187bded2dbSJung-uk Kim static BIO *init_responder(const char *port);
1196f9291ceSJung-uk Kim static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio,
1207bded2dbSJung-uk Kim                         const char *port);
1215c87c606SMark Murray static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp);
1227bded2dbSJung-uk Kim static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, const char *path,
1237bded2dbSJung-uk Kim                                       const STACK_OF(CONF_VALUE) *headers,
124db522d3aSSimon L. B. Nielsen                                       OCSP_REQUEST *req, int req_timeout);
1255c87c606SMark Murray 
1265c87c606SMark Murray # undef PROG
1275c87c606SMark Murray # define PROG ocsp_main
1285c87c606SMark Murray 
1295c87c606SMark Murray int MAIN(int, char **);
1305c87c606SMark Murray 
1315c87c606SMark Murray int MAIN(int argc, char **argv)
1325c87c606SMark Murray {
1335c87c606SMark Murray     ENGINE *e = NULL;
1345c87c606SMark Murray     char **args;
1355c87c606SMark Murray     char *host = NULL, *port = NULL, *path = "/";
13694ad176cSJung-uk Kim     char *thost = NULL, *tport = NULL, *tpath = NULL;
1375c87c606SMark Murray     char *reqin = NULL, *respin = NULL;
1385c87c606SMark Murray     char *reqout = NULL, *respout = NULL;
1395c87c606SMark Murray     char *signfile = NULL, *keyfile = NULL;
1405c87c606SMark Murray     char *rsignfile = NULL, *rkeyfile = NULL;
1415c87c606SMark Murray     char *outfile = NULL;
1425c87c606SMark Murray     int add_nonce = 1, noverify = 0, use_ssl = -1;
1431f13597dSJung-uk Kim     STACK_OF(CONF_VALUE) *headers = NULL;
1445c87c606SMark Murray     OCSP_REQUEST *req = NULL;
1455c87c606SMark Murray     OCSP_RESPONSE *resp = NULL;
1465c87c606SMark Murray     OCSP_BASICRESP *bs = NULL;
1475c87c606SMark Murray     X509 *issuer = NULL, *cert = NULL;
1485c87c606SMark Murray     X509 *signer = NULL, *rsigner = NULL;
1495c87c606SMark Murray     EVP_PKEY *key = NULL, *rkey = NULL;
1505c87c606SMark Murray     BIO *acbio = NULL, *cbio = NULL;
1515c87c606SMark Murray     BIO *derbio = NULL;
1525c87c606SMark Murray     BIO *out = NULL;
153db522d3aSSimon L. B. Nielsen     int req_timeout = -1;
1545c87c606SMark Murray     int req_text = 0, resp_text = 0;
1555c87c606SMark Murray     long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
1565c87c606SMark Murray     char *CAfile = NULL, *CApath = NULL;
1575c87c606SMark Murray     X509_STORE *store = NULL;
1587bded2dbSJung-uk Kim     X509_VERIFY_PARAM *vpm = NULL;
1595c87c606SMark Murray     STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL;
1605c87c606SMark Murray     char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
1615c87c606SMark Murray     unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
1625c87c606SMark Murray     int ret = 1;
1635c87c606SMark Murray     int accept_count = -1;
1645c87c606SMark Murray     int badarg = 0;
1657bded2dbSJung-uk Kim     int badsig = 0;
1665c87c606SMark Murray     int i;
16750ef0093SJacques Vidrine     int ignore_err = 0;
1681f13597dSJung-uk Kim     STACK_OF(OPENSSL_STRING) *reqnames = NULL;
1695c87c606SMark Murray     STACK_OF(OCSP_CERTID) *ids = NULL;
1705c87c606SMark Murray 
1715c87c606SMark Murray     X509 *rca_cert = NULL;
1725c87c606SMark Murray     char *ridx_filename = NULL;
1735c87c606SMark Murray     char *rca_filename = NULL;
174ced566fdSJacques Vidrine     CA_DB *rdb = NULL;
1755c87c606SMark Murray     int nmin = 0, ndays = -1;
1767bded2dbSJung-uk Kim     const EVP_MD *cert_id_md = NULL, *rsign_md = NULL;
1775c87c606SMark Murray 
1786f9291ceSJung-uk Kim     if (bio_err == NULL)
1796f9291ceSJung-uk Kim         bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
1805c87c606SMark Murray 
1815c87c606SMark Murray     if (!load_config(bio_err, NULL))
1825c87c606SMark Murray         goto end;
1835c87c606SMark Murray     SSL_load_error_strings();
1845471f83eSSimon L. B. Nielsen     OpenSSL_add_ssl_algorithms();
1855c87c606SMark Murray     args = argv + 1;
1861f13597dSJung-uk Kim     reqnames = sk_OPENSSL_STRING_new_null();
1875c87c606SMark Murray     ids = sk_OCSP_CERTID_new_null();
1886f9291ceSJung-uk Kim     while (!badarg && *args && *args[0] == '-') {
1896f9291ceSJung-uk Kim         if (!strcmp(*args, "-out")) {
1906f9291ceSJung-uk Kim             if (args[1]) {
1915c87c606SMark Murray                 args++;
1925c87c606SMark Murray                 outfile = *args;
1936f9291ceSJung-uk Kim             } else
1946f9291ceSJung-uk Kim                 badarg = 1;
1956f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-timeout")) {
1966f9291ceSJung-uk Kim             if (args[1]) {
197db522d3aSSimon L. B. Nielsen                 args++;
198db522d3aSSimon L. B. Nielsen                 req_timeout = atol(*args);
1996f9291ceSJung-uk Kim                 if (req_timeout < 0) {
2006f9291ceSJung-uk Kim                     BIO_printf(bio_err, "Illegal timeout value %s\n", *args);
201db522d3aSSimon L. B. Nielsen                     badarg = 1;
202db522d3aSSimon L. B. Nielsen                 }
2036f9291ceSJung-uk Kim             } else
2046f9291ceSJung-uk Kim                 badarg = 1;
2056f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-url")) {
20694ad176cSJung-uk Kim             if (thost)
20794ad176cSJung-uk Kim                 OPENSSL_free(thost);
20894ad176cSJung-uk Kim             if (tport)
20994ad176cSJung-uk Kim                 OPENSSL_free(tport);
21094ad176cSJung-uk Kim             if (tpath)
21194ad176cSJung-uk Kim                 OPENSSL_free(tpath);
2127bded2dbSJung-uk Kim             thost = tport = tpath = NULL;
2136f9291ceSJung-uk Kim             if (args[1]) {
2145c87c606SMark Murray                 args++;
2156f9291ceSJung-uk Kim                 if (!OCSP_parse_url(*args, &host, &port, &path, &use_ssl)) {
2165c87c606SMark Murray                     BIO_printf(bio_err, "Error parsing URL\n");
2175c87c606SMark Murray                     badarg = 1;
2185c87c606SMark Murray                 }
21994ad176cSJung-uk Kim                 thost = host;
22094ad176cSJung-uk Kim                 tport = port;
22194ad176cSJung-uk Kim                 tpath = path;
2226f9291ceSJung-uk Kim             } else
2236f9291ceSJung-uk Kim                 badarg = 1;
2246f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-host")) {
2256f9291ceSJung-uk Kim             if (args[1]) {
2265c87c606SMark Murray                 args++;
2275c87c606SMark Murray                 host = *args;
2286f9291ceSJung-uk Kim             } else
2296f9291ceSJung-uk Kim                 badarg = 1;
2306f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-port")) {
2316f9291ceSJung-uk Kim             if (args[1]) {
2325c87c606SMark Murray                 args++;
2335c87c606SMark Murray                 port = *args;
2346f9291ceSJung-uk Kim             } else
2356f9291ceSJung-uk Kim                 badarg = 1;
2366f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-header")) {
2376f9291ceSJung-uk Kim             if (args[1] && args[2]) {
2381f13597dSJung-uk Kim                 if (!X509V3_add_value(args[1], args[2], &headers))
2391f13597dSJung-uk Kim                     goto end;
2401f13597dSJung-uk Kim                 args += 2;
2416f9291ceSJung-uk Kim             } else
2426f9291ceSJung-uk Kim                 badarg = 1;
2436f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-ignore_err"))
24450ef0093SJacques Vidrine             ignore_err = 1;
2455c87c606SMark Murray         else if (!strcmp(*args, "-noverify"))
2465c87c606SMark Murray             noverify = 1;
2475c87c606SMark Murray         else if (!strcmp(*args, "-nonce"))
2485c87c606SMark Murray             add_nonce = 2;
2495c87c606SMark Murray         else if (!strcmp(*args, "-no_nonce"))
2505c87c606SMark Murray             add_nonce = 0;
2515c87c606SMark Murray         else if (!strcmp(*args, "-resp_no_certs"))
2525c87c606SMark Murray             rflags |= OCSP_NOCERTS;
2535c87c606SMark Murray         else if (!strcmp(*args, "-resp_key_id"))
2545c87c606SMark Murray             rflags |= OCSP_RESPID_KEY;
2555c87c606SMark Murray         else if (!strcmp(*args, "-no_certs"))
2565c87c606SMark Murray             sign_flags |= OCSP_NOCERTS;
2575c87c606SMark Murray         else if (!strcmp(*args, "-no_signature_verify"))
2585c87c606SMark Murray             verify_flags |= OCSP_NOSIGS;
2595c87c606SMark Murray         else if (!strcmp(*args, "-no_cert_verify"))
2605c87c606SMark Murray             verify_flags |= OCSP_NOVERIFY;
2615c87c606SMark Murray         else if (!strcmp(*args, "-no_chain"))
2625c87c606SMark Murray             verify_flags |= OCSP_NOCHAIN;
2635c87c606SMark Murray         else if (!strcmp(*args, "-no_cert_checks"))
2645c87c606SMark Murray             verify_flags |= OCSP_NOCHECKS;
2655c87c606SMark Murray         else if (!strcmp(*args, "-no_explicit"))
2665c87c606SMark Murray             verify_flags |= OCSP_NOEXPLICIT;
2675c87c606SMark Murray         else if (!strcmp(*args, "-trust_other"))
2685c87c606SMark Murray             verify_flags |= OCSP_TRUSTOTHER;
2695c87c606SMark Murray         else if (!strcmp(*args, "-no_intern"))
2705c87c606SMark Murray             verify_flags |= OCSP_NOINTERN;
2717bded2dbSJung-uk Kim         else if (!strcmp(*args, "-badsig"))
2727bded2dbSJung-uk Kim             badsig = 1;
2736f9291ceSJung-uk Kim         else if (!strcmp(*args, "-text")) {
2745c87c606SMark Murray             req_text = 1;
2755c87c606SMark Murray             resp_text = 1;
2766f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-req_text"))
2775c87c606SMark Murray             req_text = 1;
2785c87c606SMark Murray         else if (!strcmp(*args, "-resp_text"))
2795c87c606SMark Murray             resp_text = 1;
2806f9291ceSJung-uk Kim         else if (!strcmp(*args, "-reqin")) {
2816f9291ceSJung-uk Kim             if (args[1]) {
2825c87c606SMark Murray                 args++;
2835c87c606SMark Murray                 reqin = *args;
2846f9291ceSJung-uk Kim             } else
2856f9291ceSJung-uk Kim                 badarg = 1;
2866f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-respin")) {
2876f9291ceSJung-uk Kim             if (args[1]) {
2885c87c606SMark Murray                 args++;
2895c87c606SMark Murray                 respin = *args;
2906f9291ceSJung-uk Kim             } else
2916f9291ceSJung-uk Kim                 badarg = 1;
2926f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-signer")) {
2936f9291ceSJung-uk Kim             if (args[1]) {
2945c87c606SMark Murray                 args++;
2955c87c606SMark Murray                 signfile = *args;
2966f9291ceSJung-uk Kim             } else
2976f9291ceSJung-uk Kim                 badarg = 1;
2986f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-VAfile")) {
2996f9291ceSJung-uk Kim             if (args[1]) {
3005c87c606SMark Murray                 args++;
3015c87c606SMark Murray                 verify_certfile = *args;
3025c87c606SMark Murray                 verify_flags |= OCSP_TRUSTOTHER;
3036f9291ceSJung-uk Kim             } else
3046f9291ceSJung-uk Kim                 badarg = 1;
3056f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-sign_other")) {
3066f9291ceSJung-uk Kim             if (args[1]) {
3075c87c606SMark Murray                 args++;
3085c87c606SMark Murray                 sign_certfile = *args;
3096f9291ceSJung-uk Kim             } else
3106f9291ceSJung-uk Kim                 badarg = 1;
3116f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-verify_other")) {
3126f9291ceSJung-uk Kim             if (args[1]) {
3135c87c606SMark Murray                 args++;
3145c87c606SMark Murray                 verify_certfile = *args;
3156f9291ceSJung-uk Kim             } else
3166f9291ceSJung-uk Kim                 badarg = 1;
3176f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-CAfile")) {
3186f9291ceSJung-uk Kim             if (args[1]) {
3195c87c606SMark Murray                 args++;
3205c87c606SMark Murray                 CAfile = *args;
3216f9291ceSJung-uk Kim             } else
3226f9291ceSJung-uk Kim                 badarg = 1;
3236f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-CApath")) {
3246f9291ceSJung-uk Kim             if (args[1]) {
3255c87c606SMark Murray                 args++;
3265c87c606SMark Murray                 CApath = *args;
3276f9291ceSJung-uk Kim             } else
3286f9291ceSJung-uk Kim                 badarg = 1;
3297bded2dbSJung-uk Kim         } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) {
3307bded2dbSJung-uk Kim             if (badarg)
3317bded2dbSJung-uk Kim                 goto end;
3327bded2dbSJung-uk Kim             continue;
3336f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-validity_period")) {
3346f9291ceSJung-uk Kim             if (args[1]) {
3355c87c606SMark Murray                 args++;
3365c87c606SMark Murray                 nsec = atol(*args);
3376f9291ceSJung-uk Kim                 if (nsec < 0) {
3385c87c606SMark Murray                     BIO_printf(bio_err,
3396f9291ceSJung-uk Kim                                "Illegal validity period %s\n", *args);
3405c87c606SMark Murray                     badarg = 1;
3415c87c606SMark Murray                 }
3426f9291ceSJung-uk Kim             } else
3436f9291ceSJung-uk Kim                 badarg = 1;
3446f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-status_age")) {
3456f9291ceSJung-uk Kim             if (args[1]) {
3465c87c606SMark Murray                 args++;
3475c87c606SMark Murray                 maxage = atol(*args);
3486f9291ceSJung-uk Kim                 if (maxage < 0) {
3496f9291ceSJung-uk Kim                     BIO_printf(bio_err, "Illegal validity age %s\n", *args);
3505c87c606SMark Murray                     badarg = 1;
3515c87c606SMark Murray                 }
3526f9291ceSJung-uk Kim             } else
3536f9291ceSJung-uk Kim                 badarg = 1;
3546f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-signkey")) {
3556f9291ceSJung-uk Kim             if (args[1]) {
3565c87c606SMark Murray                 args++;
3575c87c606SMark Murray                 keyfile = *args;
3586f9291ceSJung-uk Kim             } else
3596f9291ceSJung-uk Kim                 badarg = 1;
3606f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-reqout")) {
3616f9291ceSJung-uk Kim             if (args[1]) {
3625c87c606SMark Murray                 args++;
3635c87c606SMark Murray                 reqout = *args;
3646f9291ceSJung-uk Kim             } else
3656f9291ceSJung-uk Kim                 badarg = 1;
3666f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-respout")) {
3676f9291ceSJung-uk Kim             if (args[1]) {
3685c87c606SMark Murray                 args++;
3695c87c606SMark Murray                 respout = *args;
3706f9291ceSJung-uk Kim             } else
3716f9291ceSJung-uk Kim                 badarg = 1;
3726f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-path")) {
3736f9291ceSJung-uk Kim             if (args[1]) {
3745c87c606SMark Murray                 args++;
3755c87c606SMark Murray                 path = *args;
3766f9291ceSJung-uk Kim             } else
3776f9291ceSJung-uk Kim                 badarg = 1;
3786f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-issuer")) {
3796f9291ceSJung-uk Kim             if (args[1]) {
3805c87c606SMark Murray                 args++;
3815c87c606SMark Murray                 X509_free(issuer);
3825c87c606SMark Murray                 issuer = load_cert(bio_err, *args, FORMAT_PEM,
3835c87c606SMark Murray                                    NULL, e, "issuer certificate");
3846f9291ceSJung-uk Kim                 if (!issuer)
3856f9291ceSJung-uk Kim                     goto end;
3866f9291ceSJung-uk Kim             } else
3876f9291ceSJung-uk Kim                 badarg = 1;
3886f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-cert")) {
3896f9291ceSJung-uk Kim             if (args[1]) {
3905c87c606SMark Murray                 args++;
3915c87c606SMark Murray                 X509_free(cert);
3925c87c606SMark Murray                 cert = load_cert(bio_err, *args, FORMAT_PEM,
3935c87c606SMark Murray                                  NULL, e, "certificate");
3946f9291ceSJung-uk Kim                 if (!cert)
3956f9291ceSJung-uk Kim                     goto end;
3966f9291ceSJung-uk Kim                 if (!cert_id_md)
3976f9291ceSJung-uk Kim                     cert_id_md = EVP_sha1();
3981f13597dSJung-uk Kim                 if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids))
3995c87c606SMark Murray                     goto end;
4001f13597dSJung-uk Kim                 if (!sk_OPENSSL_STRING_push(reqnames, *args))
4015c87c606SMark Murray                     goto end;
4026f9291ceSJung-uk Kim             } else
4036f9291ceSJung-uk Kim                 badarg = 1;
4046f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-serial")) {
4056f9291ceSJung-uk Kim             if (args[1]) {
4065c87c606SMark Murray                 args++;
4076f9291ceSJung-uk Kim                 if (!cert_id_md)
4086f9291ceSJung-uk Kim                     cert_id_md = EVP_sha1();
4091f13597dSJung-uk Kim                 if (!add_ocsp_serial(&req, *args, cert_id_md, issuer, ids))
4105c87c606SMark Murray                     goto end;
4111f13597dSJung-uk Kim                 if (!sk_OPENSSL_STRING_push(reqnames, *args))
4125c87c606SMark Murray                     goto end;
4136f9291ceSJung-uk Kim             } else
4146f9291ceSJung-uk Kim                 badarg = 1;
4156f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-index")) {
4166f9291ceSJung-uk Kim             if (args[1]) {
4175c87c606SMark Murray                 args++;
4185c87c606SMark Murray                 ridx_filename = *args;
4196f9291ceSJung-uk Kim             } else
4206f9291ceSJung-uk Kim                 badarg = 1;
4216f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-CA")) {
4226f9291ceSJung-uk Kim             if (args[1]) {
4235c87c606SMark Murray                 args++;
4245c87c606SMark Murray                 rca_filename = *args;
4256f9291ceSJung-uk Kim             } else
4266f9291ceSJung-uk Kim                 badarg = 1;
4276f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-nmin")) {
4286f9291ceSJung-uk Kim             if (args[1]) {
4295c87c606SMark Murray                 args++;
4305c87c606SMark Murray                 nmin = atol(*args);
4316f9291ceSJung-uk Kim                 if (nmin < 0) {
4326f9291ceSJung-uk Kim                     BIO_printf(bio_err, "Illegal update period %s\n", *args);
4335c87c606SMark Murray                     badarg = 1;
4345c87c606SMark Murray                 }
4355c87c606SMark Murray             }
4365c87c606SMark Murray             if (ndays == -1)
4375c87c606SMark Murray                 ndays = 0;
4386f9291ceSJung-uk Kim             else
4396f9291ceSJung-uk Kim                 badarg = 1;
4406f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-nrequest")) {
4416f9291ceSJung-uk Kim             if (args[1]) {
4425c87c606SMark Murray                 args++;
4435c87c606SMark Murray                 accept_count = atol(*args);
4446f9291ceSJung-uk Kim                 if (accept_count < 0) {
4456f9291ceSJung-uk Kim                     BIO_printf(bio_err, "Illegal accept count %s\n", *args);
4465c87c606SMark Murray                     badarg = 1;
4475c87c606SMark Murray                 }
4486f9291ceSJung-uk Kim             } else
4496f9291ceSJung-uk Kim                 badarg = 1;
4506f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-ndays")) {
4516f9291ceSJung-uk Kim             if (args[1]) {
4525c87c606SMark Murray                 args++;
4535c87c606SMark Murray                 ndays = atol(*args);
4546f9291ceSJung-uk Kim                 if (ndays < 0) {
4556f9291ceSJung-uk Kim                     BIO_printf(bio_err, "Illegal update period %s\n", *args);
4565c87c606SMark Murray                     badarg = 1;
4575c87c606SMark Murray                 }
4586f9291ceSJung-uk Kim             } else
4596f9291ceSJung-uk Kim                 badarg = 1;
4606f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-rsigner")) {
4616f9291ceSJung-uk Kim             if (args[1]) {
4625c87c606SMark Murray                 args++;
4635c87c606SMark Murray                 rsignfile = *args;
4646f9291ceSJung-uk Kim             } else
4656f9291ceSJung-uk Kim                 badarg = 1;
4666f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-rkey")) {
4676f9291ceSJung-uk Kim             if (args[1]) {
4685c87c606SMark Murray                 args++;
4695c87c606SMark Murray                 rkeyfile = *args;
4706f9291ceSJung-uk Kim             } else
4716f9291ceSJung-uk Kim                 badarg = 1;
4726f9291ceSJung-uk Kim         } else if (!strcmp(*args, "-rother")) {
4736f9291ceSJung-uk Kim             if (args[1]) {
4745c87c606SMark Murray                 args++;
4755c87c606SMark Murray                 rcertfile = *args;
4766f9291ceSJung-uk Kim             } else
4776f9291ceSJung-uk Kim                 badarg = 1;
4787bded2dbSJung-uk Kim         } else if (!strcmp(*args, "-rmd")) {
4797bded2dbSJung-uk Kim             if (args[1]) {
4807bded2dbSJung-uk Kim                 args++;
4817bded2dbSJung-uk Kim                 rsign_md = EVP_get_digestbyname(*args);
4827bded2dbSJung-uk Kim                 if (!rsign_md)
4837bded2dbSJung-uk Kim                     badarg = 1;
4847bded2dbSJung-uk Kim             } else
4857bded2dbSJung-uk Kim                 badarg = 1;
4866f9291ceSJung-uk Kim         } else if ((cert_id_md = EVP_get_digestbyname((*args) + 1)) == NULL) {
4871f13597dSJung-uk Kim             badarg = 1;
4881f13597dSJung-uk Kim         }
4895c87c606SMark Murray         args++;
4905c87c606SMark Murray     }
4915c87c606SMark Murray 
4925c87c606SMark Murray     /* Have we anything to do? */
4936f9291ceSJung-uk Kim     if (!req && !reqin && !respin && !(port && ridx_filename))
4946f9291ceSJung-uk Kim         badarg = 1;
4955c87c606SMark Murray 
4966f9291ceSJung-uk Kim     if (badarg) {
4975c87c606SMark Murray         BIO_printf(bio_err, "OCSP utility\n");
4985c87c606SMark Murray         BIO_printf(bio_err, "Usage ocsp [options]\n");
4995c87c606SMark Murray         BIO_printf(bio_err, "where options are\n");
5005c87c606SMark Murray         BIO_printf(bio_err, "-out file            output filename\n");
5015c87c606SMark Murray         BIO_printf(bio_err, "-issuer file         issuer certificate\n");
5025c87c606SMark Murray         BIO_printf(bio_err, "-cert file           certificate to check\n");
5035c87c606SMark Murray         BIO_printf(bio_err, "-serial n            serial number to check\n");
5046f9291ceSJung-uk Kim         BIO_printf(bio_err,
5056f9291ceSJung-uk Kim                    "-signer file         certificate to sign OCSP request with\n");
5066f9291ceSJung-uk Kim         BIO_printf(bio_err,
5076f9291ceSJung-uk Kim                    "-signkey file        private key to sign OCSP request with\n");
5086f9291ceSJung-uk Kim         BIO_printf(bio_err,
5096f9291ceSJung-uk Kim                    "-sign_other file     additional certificates to include in signed request\n");
5106f9291ceSJung-uk Kim         BIO_printf(bio_err,
5116f9291ceSJung-uk Kim                    "-no_certs            don't include any certificates in signed request\n");
5126f9291ceSJung-uk Kim         BIO_printf(bio_err,
5136f9291ceSJung-uk Kim                    "-req_text            print text form of request\n");
5146f9291ceSJung-uk Kim         BIO_printf(bio_err,
5156f9291ceSJung-uk Kim                    "-resp_text           print text form of response\n");
5166f9291ceSJung-uk Kim         BIO_printf(bio_err,
5176f9291ceSJung-uk Kim                    "-text                print text form of request and response\n");
5186f9291ceSJung-uk Kim         BIO_printf(bio_err,
5196f9291ceSJung-uk Kim                    "-reqout file         write DER encoded OCSP request to \"file\"\n");
5206f9291ceSJung-uk Kim         BIO_printf(bio_err,
5216f9291ceSJung-uk Kim                    "-respout file        write DER encoded OCSP reponse to \"file\"\n");
5226f9291ceSJung-uk Kim         BIO_printf(bio_err,
5236f9291ceSJung-uk Kim                    "-reqin file          read DER encoded OCSP request from \"file\"\n");
5246f9291ceSJung-uk Kim         BIO_printf(bio_err,
5256f9291ceSJung-uk Kim                    "-respin file         read DER encoded OCSP reponse from \"file\"\n");
5266f9291ceSJung-uk Kim         BIO_printf(bio_err,
5276f9291ceSJung-uk Kim                    "-nonce               add OCSP nonce to request\n");
5286f9291ceSJung-uk Kim         BIO_printf(bio_err,
5296f9291ceSJung-uk Kim                    "-no_nonce            don't add OCSP nonce to request\n");
5305c87c606SMark Murray         BIO_printf(bio_err, "-url URL             OCSP responder URL\n");
5316f9291ceSJung-uk Kim         BIO_printf(bio_err,
5326f9291ceSJung-uk Kim                    "-host host:n         send OCSP request to host on port n\n");
5336f9291ceSJung-uk Kim         BIO_printf(bio_err,
5346f9291ceSJung-uk Kim                    "-path                path to use in OCSP request\n");
5356f9291ceSJung-uk Kim         BIO_printf(bio_err,
5366f9291ceSJung-uk Kim                    "-CApath dir          trusted certificates directory\n");
5376f9291ceSJung-uk Kim         BIO_printf(bio_err,
5386f9291ceSJung-uk Kim                    "-CAfile file         trusted certificates file\n");
5396f9291ceSJung-uk Kim         BIO_printf(bio_err,
540ed6b93beSJung-uk Kim                    "-no_alt_chains       only ever use the first certificate chain found\n");
541ed6b93beSJung-uk Kim         BIO_printf(bio_err,
5426f9291ceSJung-uk Kim                    "-VAfile file         validator certificates file\n");
5436f9291ceSJung-uk Kim         BIO_printf(bio_err,
5446f9291ceSJung-uk Kim                    "-validity_period n   maximum validity discrepancy in seconds\n");
5456f9291ceSJung-uk Kim         BIO_printf(bio_err,
5466f9291ceSJung-uk Kim                    "-status_age n        maximum status age in seconds\n");
5476f9291ceSJung-uk Kim         BIO_printf(bio_err,
5486f9291ceSJung-uk Kim                    "-noverify            don't verify response at all\n");
5496f9291ceSJung-uk Kim         BIO_printf(bio_err,
5506f9291ceSJung-uk Kim                    "-verify_other file   additional certificates to search for signer\n");
5516f9291ceSJung-uk Kim         BIO_printf(bio_err,
5526f9291ceSJung-uk Kim                    "-trust_other         don't verify additional certificates\n");
5536f9291ceSJung-uk Kim         BIO_printf(bio_err,
5546f9291ceSJung-uk Kim                    "-no_intern           don't search certificates contained in response for signer\n");
5556f9291ceSJung-uk Kim         BIO_printf(bio_err,
5566f9291ceSJung-uk Kim                    "-no_signature_verify don't check signature on response\n");
5576f9291ceSJung-uk Kim         BIO_printf(bio_err,
5586f9291ceSJung-uk Kim                    "-no_cert_verify      don't check signing certificate\n");
5596f9291ceSJung-uk Kim         BIO_printf(bio_err,
5606f9291ceSJung-uk Kim                    "-no_chain            don't chain verify response\n");
5616f9291ceSJung-uk Kim         BIO_printf(bio_err,
5626f9291ceSJung-uk Kim                    "-no_cert_checks      don't do additional checks on signing certificate\n");
5636f9291ceSJung-uk Kim         BIO_printf(bio_err,
5646f9291ceSJung-uk Kim                    "-port num            port to run responder on\n");
5656f9291ceSJung-uk Kim         BIO_printf(bio_err,
5666f9291ceSJung-uk Kim                    "-index file          certificate status index file\n");
5675c87c606SMark Murray         BIO_printf(bio_err, "-CA file             CA certificate\n");
5686f9291ceSJung-uk Kim         BIO_printf(bio_err,
5696f9291ceSJung-uk Kim                    "-rsigner file        responder certificate to sign responses with\n");
5706f9291ceSJung-uk Kim         BIO_printf(bio_err,
5716f9291ceSJung-uk Kim                    "-rkey file           responder key to sign responses with\n");
5726f9291ceSJung-uk Kim         BIO_printf(bio_err,
5736f9291ceSJung-uk Kim                    "-rother file         other certificates to include in response\n");
5746f9291ceSJung-uk Kim         BIO_printf(bio_err,
5756f9291ceSJung-uk Kim                    "-resp_no_certs       don't include any certificates in response\n");
5766f9291ceSJung-uk Kim         BIO_printf(bio_err,
5776f9291ceSJung-uk Kim                    "-nmin n              number of minutes before next update\n");
5786f9291ceSJung-uk Kim         BIO_printf(bio_err,
5796f9291ceSJung-uk Kim                    "-ndays n             number of days before next update\n");
5806f9291ceSJung-uk Kim         BIO_printf(bio_err,
5816f9291ceSJung-uk Kim                    "-resp_key_id         identify reponse by signing certificate key ID\n");
5826f9291ceSJung-uk Kim         BIO_printf(bio_err,
5836f9291ceSJung-uk Kim                    "-nrequest n          number of requests to accept (default unlimited)\n");
5846f9291ceSJung-uk Kim         BIO_printf(bio_err,
5856f9291ceSJung-uk Kim                    "-<dgst alg>          use specified digest in the request\n");
5866f9291ceSJung-uk Kim         BIO_printf(bio_err,
5876f9291ceSJung-uk Kim                    "-timeout n           timeout connection to OCSP responder after n seconds\n");
5885c87c606SMark Murray         goto end;
5895c87c606SMark Murray     }
5905c87c606SMark Murray 
5916f9291ceSJung-uk Kim     if (outfile)
5926f9291ceSJung-uk Kim         out = BIO_new_file(outfile, "w");
5936f9291ceSJung-uk Kim     else
5946f9291ceSJung-uk Kim         out = BIO_new_fp(stdout, BIO_NOCLOSE);
5955c87c606SMark Murray 
5966f9291ceSJung-uk Kim     if (!out) {
5975c87c606SMark Murray         BIO_printf(bio_err, "Error opening output file\n");
5985c87c606SMark Murray         goto end;
5995c87c606SMark Murray     }
6005c87c606SMark Murray 
6016f9291ceSJung-uk Kim     if (!req && (add_nonce != 2))
6026f9291ceSJung-uk Kim         add_nonce = 0;
6035c87c606SMark Murray 
6046f9291ceSJung-uk Kim     if (!req && reqin) {
6057bded2dbSJung-uk Kim         if (!strcmp(reqin, "-"))
6067bded2dbSJung-uk Kim             derbio = BIO_new_fp(stdin, BIO_NOCLOSE);
6077bded2dbSJung-uk Kim         else
6085c87c606SMark Murray             derbio = BIO_new_file(reqin, "rb");
6096f9291ceSJung-uk Kim         if (!derbio) {
6105c87c606SMark Murray             BIO_printf(bio_err, "Error Opening OCSP request file\n");
6115c87c606SMark Murray             goto end;
6125c87c606SMark Murray         }
6135c87c606SMark Murray         req = d2i_OCSP_REQUEST_bio(derbio, NULL);
6145c87c606SMark Murray         BIO_free(derbio);
6156f9291ceSJung-uk Kim         if (!req) {
6165c87c606SMark Murray             BIO_printf(bio_err, "Error reading OCSP request\n");
6175c87c606SMark Murray             goto end;
6185c87c606SMark Murray         }
6195c87c606SMark Murray     }
6205c87c606SMark Murray 
6216f9291ceSJung-uk Kim     if (!req && port) {
6225c87c606SMark Murray         acbio = init_responder(port);
6235c87c606SMark Murray         if (!acbio)
6245c87c606SMark Murray             goto end;
6255c87c606SMark Murray     }
6265c87c606SMark Murray 
6276f9291ceSJung-uk Kim     if (rsignfile && !rdb) {
6286f9291ceSJung-uk Kim         if (!rkeyfile)
6296f9291ceSJung-uk Kim             rkeyfile = rsignfile;
6305c87c606SMark Murray         rsigner = load_cert(bio_err, rsignfile, FORMAT_PEM,
6315c87c606SMark Murray                             NULL, e, "responder certificate");
6326f9291ceSJung-uk Kim         if (!rsigner) {
6335c87c606SMark Murray             BIO_printf(bio_err, "Error loading responder certificate\n");
6345c87c606SMark Murray             goto end;
6355c87c606SMark Murray         }
6365c87c606SMark Murray         rca_cert = load_cert(bio_err, rca_filename, FORMAT_PEM,
6375c87c606SMark Murray                              NULL, e, "CA certificate");
6386f9291ceSJung-uk Kim         if (rcertfile) {
6395c87c606SMark Murray             rother = load_certs(bio_err, rcertfile, FORMAT_PEM,
6405c87c606SMark Murray                                 NULL, e, "responder other certificates");
6416f9291ceSJung-uk Kim             if (!rother)
6426f9291ceSJung-uk Kim                 goto end;
6435c87c606SMark Murray         }
6445c87c606SMark Murray         rkey = load_key(bio_err, rkeyfile, FORMAT_PEM, 0, NULL, NULL,
6455c87c606SMark Murray                         "responder private key");
6465c87c606SMark Murray         if (!rkey)
6475c87c606SMark Murray             goto end;
6485c87c606SMark Murray     }
6495c87c606SMark Murray     if (acbio)
6505c87c606SMark Murray         BIO_printf(bio_err, "Waiting for OCSP client connections...\n");
6515c87c606SMark Murray 
6525c87c606SMark Murray  redo_accept:
6535c87c606SMark Murray 
6546f9291ceSJung-uk Kim     if (acbio) {
6555c87c606SMark Murray         if (!do_responder(&req, &cbio, acbio, port))
6565c87c606SMark Murray             goto end;
6576f9291ceSJung-uk Kim         if (!req) {
6586f9291ceSJung-uk Kim             resp =
6596f9291ceSJung-uk Kim                 OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
6606f9291ceSJung-uk Kim                                      NULL);
6615c87c606SMark Murray             send_ocsp_response(cbio, resp);
6625c87c606SMark Murray             goto done_resp;
6635c87c606SMark Murray         }
6645c87c606SMark Murray     }
6655c87c606SMark Murray 
6666f9291ceSJung-uk Kim     if (!req && (signfile || reqout || host || add_nonce || ridx_filename)) {
6675c87c606SMark Murray         BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
6685c87c606SMark Murray         goto end;
6695c87c606SMark Murray     }
6705c87c606SMark Murray 
6716f9291ceSJung-uk Kim     if (req && add_nonce)
6726f9291ceSJung-uk Kim         OCSP_request_add1_nonce(req, NULL, -1);
6735c87c606SMark Murray 
6746f9291ceSJung-uk Kim     if (signfile) {
6756f9291ceSJung-uk Kim         if (!keyfile)
6766f9291ceSJung-uk Kim             keyfile = signfile;
6775c87c606SMark Murray         signer = load_cert(bio_err, signfile, FORMAT_PEM,
6785c87c606SMark Murray                            NULL, e, "signer certificate");
6796f9291ceSJung-uk Kim         if (!signer) {
6805c87c606SMark Murray             BIO_printf(bio_err, "Error loading signer certificate\n");
6815c87c606SMark Murray             goto end;
6825c87c606SMark Murray         }
6836f9291ceSJung-uk Kim         if (sign_certfile) {
6845c87c606SMark Murray             sign_other = load_certs(bio_err, sign_certfile, FORMAT_PEM,
6855c87c606SMark Murray                                     NULL, e, "signer certificates");
6866f9291ceSJung-uk Kim             if (!sign_other)
6876f9291ceSJung-uk Kim                 goto end;
6885c87c606SMark Murray         }
6895c87c606SMark Murray         key = load_key(bio_err, keyfile, FORMAT_PEM, 0, NULL, NULL,
6905c87c606SMark Murray                        "signer private key");
6915c87c606SMark Murray         if (!key)
6925c87c606SMark Murray             goto end;
6931f13597dSJung-uk Kim 
6946f9291ceSJung-uk Kim         if (!OCSP_request_sign
6956f9291ceSJung-uk Kim             (req, signer, key, NULL, sign_other, sign_flags)) {
6965c87c606SMark Murray             BIO_printf(bio_err, "Error signing OCSP request\n");
6975c87c606SMark Murray             goto end;
6985c87c606SMark Murray         }
6995c87c606SMark Murray     }
7005c87c606SMark Murray 
7016f9291ceSJung-uk Kim     if (req_text && req)
7026f9291ceSJung-uk Kim         OCSP_REQUEST_print(out, req, 0);
7035c87c606SMark Murray 
7046f9291ceSJung-uk Kim     if (reqout) {
7057bded2dbSJung-uk Kim         if (!strcmp(reqout, "-"))
7067bded2dbSJung-uk Kim             derbio = BIO_new_fp(stdout, BIO_NOCLOSE);
7077bded2dbSJung-uk Kim         else
7085c87c606SMark Murray             derbio = BIO_new_file(reqout, "wb");
7096f9291ceSJung-uk Kim         if (!derbio) {
7105c87c606SMark Murray             BIO_printf(bio_err, "Error opening file %s\n", reqout);
7115c87c606SMark Murray             goto end;
7125c87c606SMark Murray         }
7135c87c606SMark Murray         i2d_OCSP_REQUEST_bio(derbio, req);
7145c87c606SMark Murray         BIO_free(derbio);
7155c87c606SMark Murray     }
7165c87c606SMark Murray 
7176f9291ceSJung-uk Kim     if (ridx_filename && (!rkey || !rsigner || !rca_cert)) {
7186f9291ceSJung-uk Kim         BIO_printf(bio_err,
7196f9291ceSJung-uk Kim                    "Need a responder certificate, key and CA for this operation!\n");
7205c87c606SMark Murray         goto end;
7215c87c606SMark Murray     }
7225c87c606SMark Murray 
7236f9291ceSJung-uk Kim     if (ridx_filename && !rdb) {
724ced566fdSJacques Vidrine         rdb = load_index(ridx_filename, NULL);
7256f9291ceSJung-uk Kim         if (!rdb)
7266f9291ceSJung-uk Kim             goto end;
7276f9291ceSJung-uk Kim         if (!index_index(rdb))
7286f9291ceSJung-uk Kim             goto end;
7295c87c606SMark Murray     }
7305c87c606SMark Murray 
7316f9291ceSJung-uk Kim     if (rdb) {
7326f9291ceSJung-uk Kim         i = make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey,
7337bded2dbSJung-uk Kim                                rsign_md, rother, rflags, nmin, ndays, badsig);
7345c87c606SMark Murray         if (cbio)
7355c87c606SMark Murray             send_ocsp_response(cbio, resp);
7366f9291ceSJung-uk Kim     } else if (host) {
737fceca8a3SJacques Vidrine # ifndef OPENSSL_NO_SOCK
738db522d3aSSimon L. B. Nielsen         resp = process_responder(bio_err, req, host, path,
7391f13597dSJung-uk Kim                                  port, use_ssl, headers, req_timeout);
740db522d3aSSimon L. B. Nielsen         if (!resp)
741db522d3aSSimon L. B. Nielsen             goto end;
742fceca8a3SJacques Vidrine # else
7436f9291ceSJung-uk Kim         BIO_printf(bio_err,
7446f9291ceSJung-uk Kim                    "Error creating connect BIO - sockets not supported.\n");
745fceca8a3SJacques Vidrine         goto end;
746fceca8a3SJacques Vidrine # endif
7476f9291ceSJung-uk Kim     } else if (respin) {
7487bded2dbSJung-uk Kim         if (!strcmp(respin, "-"))
7497bded2dbSJung-uk Kim             derbio = BIO_new_fp(stdin, BIO_NOCLOSE);
7507bded2dbSJung-uk Kim         else
7515c87c606SMark Murray             derbio = BIO_new_file(respin, "rb");
7526f9291ceSJung-uk Kim         if (!derbio) {
7535c87c606SMark Murray             BIO_printf(bio_err, "Error Opening OCSP response file\n");
7545c87c606SMark Murray             goto end;
7555c87c606SMark Murray         }
7565c87c606SMark Murray         resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
7575c87c606SMark Murray         BIO_free(derbio);
7586f9291ceSJung-uk Kim         if (!resp) {
7595c87c606SMark Murray             BIO_printf(bio_err, "Error reading OCSP response\n");
7605c87c606SMark Murray             goto end;
7615c87c606SMark Murray         }
7625c87c606SMark Murray 
7636f9291ceSJung-uk Kim     } else {
7645c87c606SMark Murray         ret = 0;
7655c87c606SMark Murray         goto end;
7665c87c606SMark Murray     }
7675c87c606SMark Murray 
7685c87c606SMark Murray  done_resp:
7695c87c606SMark Murray 
7706f9291ceSJung-uk Kim     if (respout) {
7717bded2dbSJung-uk Kim         if (!strcmp(respout, "-"))
7727bded2dbSJung-uk Kim             derbio = BIO_new_fp(stdout, BIO_NOCLOSE);
7737bded2dbSJung-uk Kim         else
7745c87c606SMark Murray             derbio = BIO_new_file(respout, "wb");
7756f9291ceSJung-uk Kim         if (!derbio) {
7765c87c606SMark Murray             BIO_printf(bio_err, "Error opening file %s\n", respout);
7775c87c606SMark Murray             goto end;
7785c87c606SMark Murray         }
7795c87c606SMark Murray         i2d_OCSP_RESPONSE_bio(derbio, resp);
7805c87c606SMark Murray         BIO_free(derbio);
7815c87c606SMark Murray     }
7825c87c606SMark Murray 
7835c87c606SMark Murray     i = OCSP_response_status(resp);
7845c87c606SMark Murray 
7856f9291ceSJung-uk Kim     if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
7863b4e3dcbSSimon L. B. Nielsen         BIO_printf(out, "Responder Error: %s (%d)\n",
7875c87c606SMark Murray                    OCSP_response_status_str(i), i);
78850ef0093SJacques Vidrine         if (ignore_err)
78950ef0093SJacques Vidrine             goto redo_accept;
7905c87c606SMark Murray         ret = 0;
7915c87c606SMark Murray         goto end;
7925c87c606SMark Murray     }
7935c87c606SMark Murray 
7946f9291ceSJung-uk Kim     if (resp_text)
7956f9291ceSJung-uk Kim         OCSP_RESPONSE_print(out, resp, 0);
7965c87c606SMark Murray 
7975c87c606SMark Murray     /* If running as responder don't verify our own response */
7986f9291ceSJung-uk Kim     if (cbio) {
7995c87c606SMark Murray         if (accept_count > 0)
8005c87c606SMark Murray             accept_count--;
8015c87c606SMark Murray         /* Redo if more connections needed */
8026f9291ceSJung-uk Kim         if (accept_count) {
8035c87c606SMark Murray             BIO_free_all(cbio);
8045c87c606SMark Murray             cbio = NULL;
8055c87c606SMark Murray             OCSP_REQUEST_free(req);
8065c87c606SMark Murray             req = NULL;
8075c87c606SMark Murray             OCSP_RESPONSE_free(resp);
8085c87c606SMark Murray             resp = NULL;
8095c87c606SMark Murray             goto redo_accept;
8105c87c606SMark Murray         }
8117bded2dbSJung-uk Kim         ret = 0;
8127bded2dbSJung-uk Kim         goto end;
8137bded2dbSJung-uk Kim     } else if (ridx_filename) {
8147bded2dbSJung-uk Kim         ret = 0;
8155c87c606SMark Murray         goto end;
8165c87c606SMark Murray     }
8175c87c606SMark Murray 
8185c87c606SMark Murray     if (!store)
8195c87c606SMark Murray         store = setup_verify(bio_err, CAfile, CApath);
8205c87c606SMark Murray     if (!store)
8215c87c606SMark Murray         goto end;
8227bded2dbSJung-uk Kim     if (vpm)
8237bded2dbSJung-uk Kim         X509_STORE_set1_param(store, vpm);
8246f9291ceSJung-uk Kim     if (verify_certfile) {
8255c87c606SMark Murray         verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM,
8265c87c606SMark Murray                                   NULL, e, "validator certificate");
8276f9291ceSJung-uk Kim         if (!verify_other)
8286f9291ceSJung-uk Kim             goto end;
8295c87c606SMark Murray     }
8305c87c606SMark Murray 
8315c87c606SMark Murray     bs = OCSP_response_get1_basic(resp);
8325c87c606SMark Murray 
8336f9291ceSJung-uk Kim     if (!bs) {
8345c87c606SMark Murray         BIO_printf(bio_err, "Error parsing response\n");
8355c87c606SMark Murray         goto end;
8365c87c606SMark Murray     }
8375c87c606SMark Murray 
8387bded2dbSJung-uk Kim     ret = 0;
8397bded2dbSJung-uk Kim 
8406f9291ceSJung-uk Kim     if (!noverify) {
8416f9291ceSJung-uk Kim         if (req && ((i = OCSP_check_nonce(req, bs)) <= 0)) {
8425c87c606SMark Murray             if (i == -1)
8435c87c606SMark Murray                 BIO_printf(bio_err, "WARNING: no nonce in response\n");
8446f9291ceSJung-uk Kim             else {
8455c87c606SMark Murray                 BIO_printf(bio_err, "Nonce Verify error\n");
8467bded2dbSJung-uk Kim                 ret = 1;
8475c87c606SMark Murray                 goto end;
8485c87c606SMark Murray             }
8495c87c606SMark Murray         }
8505c87c606SMark Murray 
8515c87c606SMark Murray         i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
8526f9291ceSJung-uk Kim         if (i <= 0) {
8533b4e3dcbSSimon L. B. Nielsen             BIO_printf(bio_err, "Response Verify Failure\n");
8545c87c606SMark Murray             ERR_print_errors(bio_err);
8557bded2dbSJung-uk Kim             ret = 1;
8566f9291ceSJung-uk Kim         } else
8575c87c606SMark Murray             BIO_printf(bio_err, "Response verify OK\n");
8585c87c606SMark Murray 
8595c87c606SMark Murray     }
8605c87c606SMark Murray 
8615c87c606SMark Murray     if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage))
8627bded2dbSJung-uk Kim         ret = 1;
8635c87c606SMark Murray 
8645c87c606SMark Murray  end:
8655c87c606SMark Murray     ERR_print_errors(bio_err);
8665c87c606SMark Murray     X509_free(signer);
8675c87c606SMark Murray     X509_STORE_free(store);
8687bded2dbSJung-uk Kim     if (vpm)
8697bded2dbSJung-uk Kim         X509_VERIFY_PARAM_free(vpm);
8705c87c606SMark Murray     EVP_PKEY_free(key);
8715c87c606SMark Murray     EVP_PKEY_free(rkey);
8725c87c606SMark Murray     X509_free(issuer);
8735c87c606SMark Murray     X509_free(cert);
8745c87c606SMark Murray     X509_free(rsigner);
8755c87c606SMark Murray     X509_free(rca_cert);
876ced566fdSJacques Vidrine     free_index(rdb);
8775c87c606SMark Murray     BIO_free_all(cbio);
8785c87c606SMark Murray     BIO_free_all(acbio);
8795c87c606SMark Murray     BIO_free(out);
8805c87c606SMark Murray     OCSP_REQUEST_free(req);
8815c87c606SMark Murray     OCSP_RESPONSE_free(resp);
8825c87c606SMark Murray     OCSP_BASICRESP_free(bs);
8831f13597dSJung-uk Kim     sk_OPENSSL_STRING_free(reqnames);
8845c87c606SMark Murray     sk_OCSP_CERTID_free(ids);
8855c87c606SMark Murray     sk_X509_pop_free(sign_other, X509_free);
8865c87c606SMark Murray     sk_X509_pop_free(verify_other, X509_free);
8871f13597dSJung-uk Kim     sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);
8885c87c606SMark Murray 
88994ad176cSJung-uk Kim     if (thost)
89094ad176cSJung-uk Kim         OPENSSL_free(thost);
89194ad176cSJung-uk Kim     if (tport)
89294ad176cSJung-uk Kim         OPENSSL_free(tport);
89394ad176cSJung-uk Kim     if (tpath)
89494ad176cSJung-uk Kim         OPENSSL_free(tpath);
8955c87c606SMark Murray 
8965c87c606SMark Murray     OPENSSL_EXIT(ret);
8975c87c606SMark Murray }
8985c87c606SMark Murray 
8996f9291ceSJung-uk Kim static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert,
9006f9291ceSJung-uk Kim                          const EVP_MD *cert_id_md, X509 *issuer,
9015c87c606SMark Murray                          STACK_OF(OCSP_CERTID) *ids)
9025c87c606SMark Murray {
9035c87c606SMark Murray     OCSP_CERTID *id;
9046f9291ceSJung-uk Kim     if (!issuer) {
9055c87c606SMark Murray         BIO_printf(bio_err, "No issuer certificate specified\n");
9065c87c606SMark Murray         return 0;
9075c87c606SMark Murray     }
9086f9291ceSJung-uk Kim     if (!*req)
9096f9291ceSJung-uk Kim         *req = OCSP_REQUEST_new();
9106f9291ceSJung-uk Kim     if (!*req)
9116f9291ceSJung-uk Kim         goto err;
9121f13597dSJung-uk Kim     id = OCSP_cert_to_id(cert_id_md, cert, issuer);
9136f9291ceSJung-uk Kim     if (!id || !sk_OCSP_CERTID_push(ids, id))
9146f9291ceSJung-uk Kim         goto err;
9156f9291ceSJung-uk Kim     if (!OCSP_request_add0_id(*req, id))
9166f9291ceSJung-uk Kim         goto err;
9175c87c606SMark Murray     return 1;
9185c87c606SMark Murray 
9195c87c606SMark Murray  err:
9205c87c606SMark Murray     BIO_printf(bio_err, "Error Creating OCSP request\n");
9215c87c606SMark Murray     return 0;
9225c87c606SMark Murray }
9235c87c606SMark Murray 
9246f9291ceSJung-uk Kim static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
9256f9291ceSJung-uk Kim                            const EVP_MD *cert_id_md, X509 *issuer,
9265c87c606SMark Murray                            STACK_OF(OCSP_CERTID) *ids)
9275c87c606SMark Murray {
9285c87c606SMark Murray     OCSP_CERTID *id;
9295c87c606SMark Murray     X509_NAME *iname;
9305c87c606SMark Murray     ASN1_BIT_STRING *ikey;
9315c87c606SMark Murray     ASN1_INTEGER *sno;
9326f9291ceSJung-uk Kim     if (!issuer) {
9335c87c606SMark Murray         BIO_printf(bio_err, "No issuer certificate specified\n");
9345c87c606SMark Murray         return 0;
9355c87c606SMark Murray     }
9366f9291ceSJung-uk Kim     if (!*req)
9376f9291ceSJung-uk Kim         *req = OCSP_REQUEST_new();
9386f9291ceSJung-uk Kim     if (!*req)
9396f9291ceSJung-uk Kim         goto err;
9405c87c606SMark Murray     iname = X509_get_subject_name(issuer);
9415c87c606SMark Murray     ikey = X509_get0_pubkey_bitstr(issuer);
9425c87c606SMark Murray     sno = s2i_ASN1_INTEGER(NULL, serial);
9436f9291ceSJung-uk Kim     if (!sno) {
9445c87c606SMark Murray         BIO_printf(bio_err, "Error converting serial number %s\n", serial);
9455c87c606SMark Murray         return 0;
9465c87c606SMark Murray     }
9471f13597dSJung-uk Kim     id = OCSP_cert_id_new(cert_id_md, iname, ikey, sno);
9485c87c606SMark Murray     ASN1_INTEGER_free(sno);
9496f9291ceSJung-uk Kim     if (!id || !sk_OCSP_CERTID_push(ids, id))
9506f9291ceSJung-uk Kim         goto err;
9516f9291ceSJung-uk Kim     if (!OCSP_request_add0_id(*req, id))
9526f9291ceSJung-uk Kim         goto err;
9535c87c606SMark Murray     return 1;
9545c87c606SMark Murray 
9555c87c606SMark Murray  err:
9565c87c606SMark Murray     BIO_printf(bio_err, "Error Creating OCSP request\n");
9575c87c606SMark Murray     return 0;
9585c87c606SMark Murray }
9595c87c606SMark Murray 
9605c87c606SMark Murray static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
9611f13597dSJung-uk Kim                               STACK_OF(OPENSSL_STRING) *names,
9621f13597dSJung-uk Kim                               STACK_OF(OCSP_CERTID) *ids, long nsec,
9631f13597dSJung-uk Kim                               long maxage)
9645c87c606SMark Murray {
9655c87c606SMark Murray     OCSP_CERTID *id;
9665c87c606SMark Murray     char *name;
9675c87c606SMark Murray     int i;
9685c87c606SMark Murray 
9695c87c606SMark Murray     int status, reason;
9705c87c606SMark Murray 
9715c87c606SMark Murray     ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
9725c87c606SMark Murray 
9736f9291ceSJung-uk Kim     if (!bs || !req || !sk_OPENSSL_STRING_num(names)
9746f9291ceSJung-uk Kim         || !sk_OCSP_CERTID_num(ids))
9755c87c606SMark Murray         return 1;
9765c87c606SMark Murray 
9776f9291ceSJung-uk Kim     for (i = 0; i < sk_OCSP_CERTID_num(ids); i++) {
9785c87c606SMark Murray         id = sk_OCSP_CERTID_value(ids, i);
9791f13597dSJung-uk Kim         name = sk_OPENSSL_STRING_value(names, i);
9805c87c606SMark Murray         BIO_printf(out, "%s: ", name);
9815c87c606SMark Murray 
9825c87c606SMark Murray         if (!OCSP_resp_find_status(bs, id, &status, &reason,
9836f9291ceSJung-uk Kim                                    &rev, &thisupd, &nextupd)) {
9845c87c606SMark Murray             BIO_puts(out, "ERROR: No Status found.\n");
9855c87c606SMark Murray             continue;
9865c87c606SMark Murray         }
9875c87c606SMark Murray 
9886f9291ceSJung-uk Kim         /*
9896f9291ceSJung-uk Kim          * Check validity: if invalid write to output BIO so we know which
9906f9291ceSJung-uk Kim          * response this refers to.
9915c87c606SMark Murray          */
9926f9291ceSJung-uk Kim         if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) {
9935c87c606SMark Murray             BIO_puts(out, "WARNING: Status times invalid.\n");
9945c87c606SMark Murray             ERR_print_errors(out);
9955c87c606SMark Murray         }
9965c87c606SMark Murray         BIO_printf(out, "%s\n", OCSP_cert_status_str(status));
9975c87c606SMark Murray 
9985c87c606SMark Murray         BIO_puts(out, "\tThis Update: ");
9995c87c606SMark Murray         ASN1_GENERALIZEDTIME_print(out, thisupd);
10005c87c606SMark Murray         BIO_puts(out, "\n");
10015c87c606SMark Murray 
10026f9291ceSJung-uk Kim         if (nextupd) {
10035c87c606SMark Murray             BIO_puts(out, "\tNext Update: ");
10045c87c606SMark Murray             ASN1_GENERALIZEDTIME_print(out, nextupd);
10055c87c606SMark Murray             BIO_puts(out, "\n");
10065c87c606SMark Murray         }
10075c87c606SMark Murray 
10085c87c606SMark Murray         if (status != V_OCSP_CERTSTATUS_REVOKED)
10095c87c606SMark Murray             continue;
10105c87c606SMark Murray 
10115c87c606SMark Murray         if (reason != -1)
10126f9291ceSJung-uk Kim             BIO_printf(out, "\tReason: %s\n", OCSP_crl_reason_str(reason));
10135c87c606SMark Murray 
10145c87c606SMark Murray         BIO_puts(out, "\tRevocation Time: ");
10155c87c606SMark Murray         ASN1_GENERALIZEDTIME_print(out, rev);
10165c87c606SMark Murray         BIO_puts(out, "\n");
10175c87c606SMark Murray     }
10185c87c606SMark Murray 
10195c87c606SMark Murray     return 1;
10205c87c606SMark Murray }
10215c87c606SMark Murray 
10226f9291ceSJung-uk Kim static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req,
10236f9291ceSJung-uk Kim                               CA_DB *db, X509 *ca, X509 *rcert,
10247bded2dbSJung-uk Kim                               EVP_PKEY *rkey, const EVP_MD *rmd,
10257bded2dbSJung-uk Kim                               STACK_OF(X509) *rother, unsigned long flags,
10267bded2dbSJung-uk Kim                               int nmin, int ndays, int badsig)
10275c87c606SMark Murray {
10285c87c606SMark Murray     ASN1_TIME *thisupd = NULL, *nextupd = NULL;
10295c87c606SMark Murray     OCSP_CERTID *cid, *ca_id = NULL;
10305c87c606SMark Murray     OCSP_BASICRESP *bs = NULL;
10315c87c606SMark Murray     int i, id_count, ret = 1;
10325c87c606SMark Murray 
10335c87c606SMark Murray     id_count = OCSP_request_onereq_count(req);
10345c87c606SMark Murray 
10356f9291ceSJung-uk Kim     if (id_count <= 0) {
10366f9291ceSJung-uk Kim         *resp =
10376f9291ceSJung-uk Kim             OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL);
10385c87c606SMark Murray         goto end;
10395c87c606SMark Murray     }
10405c87c606SMark Murray 
10415c87c606SMark Murray     bs = OCSP_BASICRESP_new();
10425c87c606SMark Murray     thisupd = X509_gmtime_adj(NULL, 0);
10435c87c606SMark Murray     if (ndays != -1)
1044*8180e704SJung-uk Kim         nextupd = X509_time_adj_ex(NULL, ndays, nmin * 60, NULL);
10455c87c606SMark Murray 
10465c87c606SMark Murray     /* Examine each certificate id in the request */
10476f9291ceSJung-uk Kim     for (i = 0; i < id_count; i++) {
10485c87c606SMark Murray         OCSP_ONEREQ *one;
10495c87c606SMark Murray         ASN1_INTEGER *serial;
10505c87c606SMark Murray         char **inf;
10511f13597dSJung-uk Kim         ASN1_OBJECT *cert_id_md_oid;
10521f13597dSJung-uk Kim         const EVP_MD *cert_id_md;
10535c87c606SMark Murray         one = OCSP_request_onereq_get0(req, i);
10545c87c606SMark Murray         cid = OCSP_onereq_get0_id(one);
10551f13597dSJung-uk Kim 
10561f13597dSJung-uk Kim         OCSP_id_get0_info(NULL, &cert_id_md_oid, NULL, NULL, cid);
10571f13597dSJung-uk Kim 
10581f13597dSJung-uk Kim         cert_id_md = EVP_get_digestbyobj(cert_id_md_oid);
10596f9291ceSJung-uk Kim         if (!cert_id_md) {
10601f13597dSJung-uk Kim             *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR,
10611f13597dSJung-uk Kim                                          NULL);
10621f13597dSJung-uk Kim             goto end;
10631f13597dSJung-uk Kim         }
10646f9291ceSJung-uk Kim         if (ca_id)
10656f9291ceSJung-uk Kim             OCSP_CERTID_free(ca_id);
10661f13597dSJung-uk Kim         ca_id = OCSP_cert_to_id(cert_id_md, NULL, ca);
10671f13597dSJung-uk Kim 
10685c87c606SMark Murray         /* Is this request about our CA? */
10696f9291ceSJung-uk Kim         if (OCSP_id_issuer_cmp(ca_id, cid)) {
10705c87c606SMark Murray             OCSP_basic_add1_status(bs, cid,
10715c87c606SMark Murray                                    V_OCSP_CERTSTATUS_UNKNOWN,
10726f9291ceSJung-uk Kim                                    0, NULL, thisupd, nextupd);
10735c87c606SMark Murray             continue;
10745c87c606SMark Murray         }
10755c87c606SMark Murray         OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid);
10765c87c606SMark Murray         inf = lookup_serial(db, serial);
10775c87c606SMark Murray         if (!inf)
10785c87c606SMark Murray             OCSP_basic_add1_status(bs, cid,
10795c87c606SMark Murray                                    V_OCSP_CERTSTATUS_UNKNOWN,
10806f9291ceSJung-uk Kim                                    0, NULL, thisupd, nextupd);
10815c87c606SMark Murray         else if (inf[DB_type][0] == DB_TYPE_VAL)
10825c87c606SMark Murray             OCSP_basic_add1_status(bs, cid,
10835c87c606SMark Murray                                    V_OCSP_CERTSTATUS_GOOD,
10846f9291ceSJung-uk Kim                                    0, NULL, thisupd, nextupd);
10856f9291ceSJung-uk Kim         else if (inf[DB_type][0] == DB_TYPE_REV) {
10865c87c606SMark Murray             ASN1_OBJECT *inst = NULL;
10875c87c606SMark Murray             ASN1_TIME *revtm = NULL;
10885c87c606SMark Murray             ASN1_GENERALIZEDTIME *invtm = NULL;
10895c87c606SMark Murray             OCSP_SINGLERESP *single;
10905c87c606SMark Murray             int reason = -1;
10915c87c606SMark Murray             unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]);
10925c87c606SMark Murray             single = OCSP_basic_add1_status(bs, cid,
10935c87c606SMark Murray                                             V_OCSP_CERTSTATUS_REVOKED,
10946f9291ceSJung-uk Kim                                             reason, revtm, thisupd, nextupd);
10955c87c606SMark Murray             if (invtm)
10966f9291ceSJung-uk Kim                 OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date,
10976f9291ceSJung-uk Kim                                              invtm, 0, 0);
10985c87c606SMark Murray             else if (inst)
10996f9291ceSJung-uk Kim                 OCSP_SINGLERESP_add1_ext_i2d(single,
11006f9291ceSJung-uk Kim                                              NID_hold_instruction_code, inst,
11016f9291ceSJung-uk Kim                                              0, 0);
11025c87c606SMark Murray             ASN1_OBJECT_free(inst);
11035c87c606SMark Murray             ASN1_TIME_free(revtm);
11045c87c606SMark Murray             ASN1_GENERALIZEDTIME_free(invtm);
11055c87c606SMark Murray         }
11065c87c606SMark Murray     }
11075c87c606SMark Murray 
11085c87c606SMark Murray     OCSP_copy_nonce(bs, req);
11095c87c606SMark Murray 
11107bded2dbSJung-uk Kim     OCSP_basic_sign(bs, rcert, rkey, rmd, rother, flags);
11117bded2dbSJung-uk Kim 
11127bded2dbSJung-uk Kim     if (badsig)
11137bded2dbSJung-uk Kim         bs->signature->data[bs->signature->length - 1] ^= 0x1;
11145c87c606SMark Murray 
11155c87c606SMark Murray     *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs);
11165c87c606SMark Murray 
11175c87c606SMark Murray  end:
11185c87c606SMark Murray     ASN1_TIME_free(thisupd);
11195c87c606SMark Murray     ASN1_TIME_free(nextupd);
11205c87c606SMark Murray     OCSP_CERTID_free(ca_id);
11215c87c606SMark Murray     OCSP_BASICRESP_free(bs);
11225c87c606SMark Murray     return ret;
11235c87c606SMark Murray 
11245c87c606SMark Murray }
11255c87c606SMark Murray 
1126ced566fdSJacques Vidrine static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
11275c87c606SMark Murray {
11285c87c606SMark Murray     int i;
11295c87c606SMark Murray     BIGNUM *bn = NULL;
11305c87c606SMark Murray     char *itmp, *row[DB_NUMBER], **rrow;
11316f9291ceSJung-uk Kim     for (i = 0; i < DB_NUMBER; i++)
11326f9291ceSJung-uk Kim         row[i] = NULL;
11335c87c606SMark Murray     bn = ASN1_INTEGER_to_BN(ser, NULL);
11346f9291ceSJung-uk Kim     OPENSSL_assert(bn);         /* FIXME: should report an error at this
11356f9291ceSJung-uk Kim                                  * point and abort */
11365c87c606SMark Murray     if (BN_is_zero(bn))
11375c87c606SMark Murray         itmp = BUF_strdup("00");
11385c87c606SMark Murray     else
11395c87c606SMark Murray         itmp = BN_bn2hex(bn);
11405c87c606SMark Murray     row[DB_serial] = itmp;
11415c87c606SMark Murray     BN_free(bn);
1142ced566fdSJacques Vidrine     rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
11435c87c606SMark Murray     OPENSSL_free(itmp);
11445c87c606SMark Murray     return rrow;
11455c87c606SMark Murray }
11465c87c606SMark Murray 
11475c87c606SMark Murray /* Quick and dirty OCSP server: read in and parse input request */
11485c87c606SMark Murray 
11497bded2dbSJung-uk Kim static BIO *init_responder(const char *port)
11505c87c606SMark Murray {
11515c87c606SMark Murray     BIO *acbio = NULL, *bufbio = NULL;
11525c87c606SMark Murray     bufbio = BIO_new(BIO_f_buffer());
11535c87c606SMark Murray     if (!bufbio)
11545c87c606SMark Murray         goto err;
1155fceca8a3SJacques Vidrine # ifndef OPENSSL_NO_SOCK
11565c87c606SMark Murray     acbio = BIO_new_accept(port);
1157fceca8a3SJacques Vidrine # else
11586f9291ceSJung-uk Kim     BIO_printf(bio_err,
11596f9291ceSJung-uk Kim                "Error setting up accept BIO - sockets not supported.\n");
1160fceca8a3SJacques Vidrine # endif
11615c87c606SMark Murray     if (!acbio)
11625c87c606SMark Murray         goto err;
11635c87c606SMark Murray     BIO_set_accept_bios(acbio, bufbio);
11645c87c606SMark Murray     bufbio = NULL;
11655c87c606SMark Murray 
11666f9291ceSJung-uk Kim     if (BIO_do_accept(acbio) <= 0) {
11675c87c606SMark Murray         BIO_printf(bio_err, "Error setting up accept BIO\n");
11685c87c606SMark Murray         ERR_print_errors(bio_err);
11695c87c606SMark Murray         goto err;
11705c87c606SMark Murray     }
11715c87c606SMark Murray 
11725c87c606SMark Murray     return acbio;
11735c87c606SMark Murray 
11745c87c606SMark Murray  err:
11755c87c606SMark Murray     BIO_free_all(acbio);
11765c87c606SMark Murray     BIO_free(bufbio);
11775c87c606SMark Murray     return NULL;
11785c87c606SMark Murray }
11795c87c606SMark Murray 
11806f9291ceSJung-uk Kim static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio,
11817bded2dbSJung-uk Kim                         const char *port)
11825c87c606SMark Murray {
11835c87c606SMark Murray     int have_post = 0, len;
11845c87c606SMark Murray     OCSP_REQUEST *req = NULL;
11855c87c606SMark Murray     char inbuf[1024];
11865c87c606SMark Murray     BIO *cbio = NULL;
11875c87c606SMark Murray 
11886f9291ceSJung-uk Kim     if (BIO_do_accept(acbio) <= 0) {
11895c87c606SMark Murray         BIO_printf(bio_err, "Error accepting connection\n");
11905c87c606SMark Murray         ERR_print_errors(bio_err);
11915c87c606SMark Murray         return 0;
11925c87c606SMark Murray     }
11935c87c606SMark Murray 
11945c87c606SMark Murray     cbio = BIO_pop(acbio);
11955c87c606SMark Murray     *pcbio = cbio;
11965c87c606SMark Murray 
11976f9291ceSJung-uk Kim     for (;;) {
11985c87c606SMark Murray         len = BIO_gets(cbio, inbuf, sizeof inbuf);
11995c87c606SMark Murray         if (len <= 0)
12005c87c606SMark Murray             return 1;
12015c87c606SMark Murray         /* Look for "POST" signalling start of query */
12026f9291ceSJung-uk Kim         if (!have_post) {
12036f9291ceSJung-uk Kim             if (strncmp(inbuf, "POST", 4)) {
12045c87c606SMark Murray                 BIO_printf(bio_err, "Invalid request\n");
12055c87c606SMark Murray                 return 1;
12065c87c606SMark Murray             }
12075c87c606SMark Murray             have_post = 1;
12085c87c606SMark Murray         }
12095c87c606SMark Murray         /* Look for end of headers */
12105c87c606SMark Murray         if ((inbuf[0] == '\r') || (inbuf[0] == '\n'))
12115c87c606SMark Murray             break;
12125c87c606SMark Murray     }
12135c87c606SMark Murray 
12145c87c606SMark Murray     /* Try to read OCSP request */
12155c87c606SMark Murray 
12165c87c606SMark Murray     req = d2i_OCSP_REQUEST_bio(cbio, NULL);
12175c87c606SMark Murray 
12186f9291ceSJung-uk Kim     if (!req) {
12195c87c606SMark Murray         BIO_printf(bio_err, "Error parsing OCSP request\n");
12205c87c606SMark Murray         ERR_print_errors(bio_err);
12215c87c606SMark Murray     }
12225c87c606SMark Murray 
12235c87c606SMark Murray     *preq = req;
12245c87c606SMark Murray 
12255c87c606SMark Murray     return 1;
12265c87c606SMark Murray 
12275c87c606SMark Murray }
12285c87c606SMark Murray 
12295c87c606SMark Murray static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
12305c87c606SMark Murray {
12315c87c606SMark Murray     char http_resp[] =
12325c87c606SMark Murray         "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n"
12335c87c606SMark Murray         "Content-Length: %d\r\n\r\n";
12345c87c606SMark Murray     if (!cbio)
12355c87c606SMark Murray         return 0;
12365c87c606SMark Murray     BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL));
12375c87c606SMark Murray     i2d_OCSP_RESPONSE_bio(cbio, resp);
1238db522d3aSSimon L. B. Nielsen     (void)BIO_flush(cbio);
12395c87c606SMark Murray     return 1;
12405c87c606SMark Murray }
12415c87c606SMark Murray 
12427bded2dbSJung-uk Kim static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, const char *path,
12437bded2dbSJung-uk Kim                                       const STACK_OF(CONF_VALUE) *headers,
1244db522d3aSSimon L. B. Nielsen                                       OCSP_REQUEST *req, int req_timeout)
1245db522d3aSSimon L. B. Nielsen {
1246db522d3aSSimon L. B. Nielsen     int fd;
1247db522d3aSSimon L. B. Nielsen     int rv;
12481f13597dSJung-uk Kim     int i;
1249db522d3aSSimon L. B. Nielsen     OCSP_REQ_CTX *ctx = NULL;
1250db522d3aSSimon L. B. Nielsen     OCSP_RESPONSE *rsp = NULL;
1251db522d3aSSimon L. B. Nielsen     fd_set confds;
1252db522d3aSSimon L. B. Nielsen     struct timeval tv;
1253db522d3aSSimon L. B. Nielsen 
1254db522d3aSSimon L. B. Nielsen     if (req_timeout != -1)
1255db522d3aSSimon L. B. Nielsen         BIO_set_nbio(cbio, 1);
1256db522d3aSSimon L. B. Nielsen 
1257db522d3aSSimon L. B. Nielsen     rv = BIO_do_connect(cbio);
1258db522d3aSSimon L. B. Nielsen 
12596f9291ceSJung-uk Kim     if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) {
1260db522d3aSSimon L. B. Nielsen         BIO_puts(err, "Error connecting BIO\n");
1261db522d3aSSimon L. B. Nielsen         return NULL;
1262db522d3aSSimon L. B. Nielsen     }
1263db522d3aSSimon L. B. Nielsen 
126480815a77SJung-uk Kim     if (BIO_get_fd(cbio, &fd) < 0) {
126580815a77SJung-uk Kim         BIO_puts(bio_err, "Can't get connection fd\n");
1266db522d3aSSimon L. B. Nielsen         goto err;
1267db522d3aSSimon L. B. Nielsen     }
1268db522d3aSSimon L. B. Nielsen 
12696f9291ceSJung-uk Kim     if (req_timeout != -1 && rv <= 0) {
1270db522d3aSSimon L. B. Nielsen         FD_ZERO(&confds);
1271db522d3aSSimon L. B. Nielsen         openssl_fdset(fd, &confds);
1272db522d3aSSimon L. B. Nielsen         tv.tv_usec = 0;
1273db522d3aSSimon L. B. Nielsen         tv.tv_sec = req_timeout;
1274db522d3aSSimon L. B. Nielsen         rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
12756f9291ceSJung-uk Kim         if (rv == 0) {
1276db522d3aSSimon L. B. Nielsen             BIO_puts(err, "Timeout on connect\n");
1277db522d3aSSimon L. B. Nielsen             return NULL;
1278db522d3aSSimon L. B. Nielsen         }
1279db522d3aSSimon L. B. Nielsen     }
1280db522d3aSSimon L. B. Nielsen 
12811f13597dSJung-uk Kim     ctx = OCSP_sendreq_new(cbio, path, NULL, -1);
1282db522d3aSSimon L. B. Nielsen     if (!ctx)
1283db522d3aSSimon L. B. Nielsen         return NULL;
1284db522d3aSSimon L. B. Nielsen 
12856f9291ceSJung-uk Kim     for (i = 0; i < sk_CONF_VALUE_num(headers); i++) {
12861f13597dSJung-uk Kim         CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i);
12871f13597dSJung-uk Kim         if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value))
12881f13597dSJung-uk Kim             goto err;
12891f13597dSJung-uk Kim     }
12901f13597dSJung-uk Kim 
12911f13597dSJung-uk Kim     if (!OCSP_REQ_CTX_set1_req(ctx, req))
12921f13597dSJung-uk Kim         goto err;
12931f13597dSJung-uk Kim 
12946f9291ceSJung-uk Kim     for (;;) {
1295db522d3aSSimon L. B. Nielsen         rv = OCSP_sendreq_nbio(&rsp, ctx);
1296db522d3aSSimon L. B. Nielsen         if (rv != -1)
1297db522d3aSSimon L. B. Nielsen             break;
12981f13597dSJung-uk Kim         if (req_timeout == -1)
12991f13597dSJung-uk Kim             continue;
1300db522d3aSSimon L. B. Nielsen         FD_ZERO(&confds);
1301db522d3aSSimon L. B. Nielsen         openssl_fdset(fd, &confds);
1302db522d3aSSimon L. B. Nielsen         tv.tv_usec = 0;
1303db522d3aSSimon L. B. Nielsen         tv.tv_sec = req_timeout;
1304db522d3aSSimon L. B. Nielsen         if (BIO_should_read(cbio))
1305db522d3aSSimon L. B. Nielsen             rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv);
1306db522d3aSSimon L. B. Nielsen         else if (BIO_should_write(cbio))
1307db522d3aSSimon L. B. Nielsen             rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
13086f9291ceSJung-uk Kim         else {
1309db522d3aSSimon L. B. Nielsen             BIO_puts(err, "Unexpected retry condition\n");
1310db522d3aSSimon L. B. Nielsen             goto err;
1311db522d3aSSimon L. B. Nielsen         }
13126f9291ceSJung-uk Kim         if (rv == 0) {
1313db522d3aSSimon L. B. Nielsen             BIO_puts(err, "Timeout on request\n");
1314db522d3aSSimon L. B. Nielsen             break;
1315db522d3aSSimon L. B. Nielsen         }
13166f9291ceSJung-uk Kim         if (rv == -1) {
1317db522d3aSSimon L. B. Nielsen             BIO_puts(err, "Select error\n");
1318db522d3aSSimon L. B. Nielsen             break;
1319db522d3aSSimon L. B. Nielsen         }
1320db522d3aSSimon L. B. Nielsen 
1321db522d3aSSimon L. B. Nielsen     }
1322db522d3aSSimon L. B. Nielsen  err:
1323db522d3aSSimon L. B. Nielsen     if (ctx)
1324db522d3aSSimon L. B. Nielsen         OCSP_REQ_CTX_free(ctx);
1325db522d3aSSimon L. B. Nielsen 
1326db522d3aSSimon L. B. Nielsen     return rsp;
1327db522d3aSSimon L. B. Nielsen }
1328db522d3aSSimon L. B. Nielsen 
1329db522d3aSSimon L. B. Nielsen OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req,
13307bded2dbSJung-uk Kim                                  const char *host, const char *path,
13317bded2dbSJung-uk Kim                                  const char *port, int use_ssl,
13327bded2dbSJung-uk Kim                                  const STACK_OF(CONF_VALUE) *headers,
1333db522d3aSSimon L. B. Nielsen                                  int req_timeout)
1334db522d3aSSimon L. B. Nielsen {
1335db522d3aSSimon L. B. Nielsen     BIO *cbio = NULL;
1336db522d3aSSimon L. B. Nielsen     SSL_CTX *ctx = NULL;
1337db522d3aSSimon L. B. Nielsen     OCSP_RESPONSE *resp = NULL;
1338db522d3aSSimon L. B. Nielsen     cbio = BIO_new_connect(host);
13396f9291ceSJung-uk Kim     if (!cbio) {
1340db522d3aSSimon L. B. Nielsen         BIO_printf(err, "Error creating connect BIO\n");
1341db522d3aSSimon L. B. Nielsen         goto end;
1342db522d3aSSimon L. B. Nielsen     }
13436f9291ceSJung-uk Kim     if (port)
13446f9291ceSJung-uk Kim         BIO_set_conn_port(cbio, port);
13456f9291ceSJung-uk Kim     if (use_ssl == 1) {
1346db522d3aSSimon L. B. Nielsen         BIO *sbio;
1347db522d3aSSimon L. B. Nielsen         ctx = SSL_CTX_new(SSLv23_client_method());
13486f9291ceSJung-uk Kim         if (ctx == NULL) {
1349db522d3aSSimon L. B. Nielsen             BIO_printf(err, "Error creating SSL context.\n");
1350db522d3aSSimon L. B. Nielsen             goto end;
1351db522d3aSSimon L. B. Nielsen         }
1352db522d3aSSimon L. B. Nielsen         SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
1353db522d3aSSimon L. B. Nielsen         sbio = BIO_new_ssl(ctx, 1);
1354db522d3aSSimon L. B. Nielsen         cbio = BIO_push(sbio, cbio);
1355db522d3aSSimon L. B. Nielsen     }
13561f13597dSJung-uk Kim     resp = query_responder(err, cbio, path, headers, req, req_timeout);
1357db522d3aSSimon L. B. Nielsen     if (!resp)
1358a93cbc2bSJung-uk Kim         BIO_printf(bio_err, "Error querying OCSP responder\n");
1359db522d3aSSimon L. B. Nielsen  end:
1360db522d3aSSimon L. B. Nielsen     if (cbio)
1361db522d3aSSimon L. B. Nielsen         BIO_free_all(cbio);
13621f13597dSJung-uk Kim     if (ctx)
13631f13597dSJung-uk Kim         SSL_CTX_free(ctx);
1364db522d3aSSimon L. B. Nielsen     return resp;
1365db522d3aSSimon L. B. Nielsen }
1366db522d3aSSimon L. B. Nielsen 
1367fceca8a3SJacques Vidrine #endif
1368