15c87c606SMark Murray /* ocsp.c */ 25c87c606SMark Murray /* Written by Dr Stephen N Henson (shenson@bigfoot.com) 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 595c87c606SMark Murray 605c87c606SMark Murray #include <stdio.h> 615c87c606SMark Murray #include <string.h> 625c87c606SMark Murray #include "apps.h" 635c87c606SMark Murray #include <openssl/pem.h> 645c87c606SMark Murray #include <openssl/ocsp.h> 655c87c606SMark Murray #include <openssl/err.h> 665c87c606SMark Murray #include <openssl/ssl.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); 885c87c606SMark Murray 895c87c606SMark Murray #undef PROG 905c87c606SMark Murray #define PROG ocsp_main 915c87c606SMark Murray 925c87c606SMark Murray int MAIN(int, char **); 935c87c606SMark Murray 945c87c606SMark Murray int MAIN(int argc, char **argv) 955c87c606SMark Murray { 965c87c606SMark Murray ENGINE *e = NULL; 975c87c606SMark Murray char **args; 985c87c606SMark Murray char *host = NULL, *port = NULL, *path = "/"; 995c87c606SMark Murray char *reqin = NULL, *respin = NULL; 1005c87c606SMark Murray char *reqout = NULL, *respout = NULL; 1015c87c606SMark Murray char *signfile = NULL, *keyfile = NULL; 1025c87c606SMark Murray char *rsignfile = NULL, *rkeyfile = NULL; 1035c87c606SMark Murray char *outfile = NULL; 1045c87c606SMark Murray int add_nonce = 1, noverify = 0, use_ssl = -1; 1055c87c606SMark Murray OCSP_REQUEST *req = NULL; 1065c87c606SMark Murray OCSP_RESPONSE *resp = NULL; 1075c87c606SMark Murray OCSP_BASICRESP *bs = NULL; 1085c87c606SMark Murray X509 *issuer = NULL, *cert = NULL; 1095c87c606SMark Murray X509 *signer = NULL, *rsigner = NULL; 1105c87c606SMark Murray EVP_PKEY *key = NULL, *rkey = NULL; 1115c87c606SMark Murray BIO *acbio = NULL, *cbio = NULL; 1125c87c606SMark Murray BIO *derbio = NULL; 1135c87c606SMark Murray BIO *out = NULL; 1145c87c606SMark Murray int req_text = 0, resp_text = 0; 1155c87c606SMark Murray long nsec = MAX_VALIDITY_PERIOD, maxage = -1; 1165c87c606SMark Murray char *CAfile = NULL, *CApath = NULL; 1175c87c606SMark Murray X509_STORE *store = NULL; 1185c87c606SMark Murray SSL_CTX *ctx = NULL; 1195c87c606SMark Murray STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL; 1205c87c606SMark Murray char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL; 1215c87c606SMark Murray unsigned long sign_flags = 0, verify_flags = 0, rflags = 0; 1225c87c606SMark Murray int ret = 1; 1235c87c606SMark Murray int accept_count = -1; 1245c87c606SMark Murray int badarg = 0; 1255c87c606SMark Murray int i; 12650ef0093SJacques Vidrine int ignore_err = 0; 1275c87c606SMark Murray STACK *reqnames = NULL; 1285c87c606SMark Murray STACK_OF(OCSP_CERTID) *ids = NULL; 1295c87c606SMark Murray 1305c87c606SMark Murray X509 *rca_cert = NULL; 1315c87c606SMark Murray char *ridx_filename = NULL; 1325c87c606SMark Murray char *rca_filename = NULL; 133ced566fdSJacques Vidrine CA_DB *rdb = NULL; 1345c87c606SMark Murray int nmin = 0, ndays = -1; 1355c87c606SMark Murray 1365c87c606SMark Murray if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 1375c87c606SMark Murray 1385c87c606SMark Murray if (!load_config(bio_err, NULL)) 1395c87c606SMark Murray goto end; 1405c87c606SMark Murray SSL_load_error_strings(); 1415c87c606SMark Murray args = argv + 1; 1425c87c606SMark Murray reqnames = sk_new_null(); 1435c87c606SMark Murray ids = sk_OCSP_CERTID_new_null(); 1445c87c606SMark Murray while (!badarg && *args && *args[0] == '-') 1455c87c606SMark Murray { 1465c87c606SMark Murray if (!strcmp(*args, "-out")) 1475c87c606SMark Murray { 1485c87c606SMark Murray if (args[1]) 1495c87c606SMark Murray { 1505c87c606SMark Murray args++; 1515c87c606SMark Murray outfile = *args; 1525c87c606SMark Murray } 1535c87c606SMark Murray else badarg = 1; 1545c87c606SMark Murray } 1555c87c606SMark Murray else if (!strcmp(*args, "-url")) 1565c87c606SMark Murray { 1575c87c606SMark Murray if (args[1]) 1585c87c606SMark Murray { 1595c87c606SMark Murray args++; 1605c87c606SMark Murray if (!OCSP_parse_url(*args, &host, &port, &path, &use_ssl)) 1615c87c606SMark Murray { 1625c87c606SMark Murray BIO_printf(bio_err, "Error parsing URL\n"); 1635c87c606SMark Murray badarg = 1; 1645c87c606SMark Murray } 1655c87c606SMark Murray } 1665c87c606SMark Murray else badarg = 1; 1675c87c606SMark Murray } 1685c87c606SMark Murray else if (!strcmp(*args, "-host")) 1695c87c606SMark Murray { 1705c87c606SMark Murray if (args[1]) 1715c87c606SMark Murray { 1725c87c606SMark Murray args++; 1735c87c606SMark Murray host = *args; 1745c87c606SMark Murray } 1755c87c606SMark Murray else badarg = 1; 1765c87c606SMark Murray } 1775c87c606SMark Murray else if (!strcmp(*args, "-port")) 1785c87c606SMark Murray { 1795c87c606SMark Murray if (args[1]) 1805c87c606SMark Murray { 1815c87c606SMark Murray args++; 1825c87c606SMark Murray port = *args; 1835c87c606SMark Murray } 1845c87c606SMark Murray else badarg = 1; 1855c87c606SMark Murray } 18650ef0093SJacques Vidrine else if (!strcmp(*args, "-ignore_err")) 18750ef0093SJacques Vidrine ignore_err = 1; 1885c87c606SMark Murray else if (!strcmp(*args, "-noverify")) 1895c87c606SMark Murray noverify = 1; 1905c87c606SMark Murray else if (!strcmp(*args, "-nonce")) 1915c87c606SMark Murray add_nonce = 2; 1925c87c606SMark Murray else if (!strcmp(*args, "-no_nonce")) 1935c87c606SMark Murray add_nonce = 0; 1945c87c606SMark Murray else if (!strcmp(*args, "-resp_no_certs")) 1955c87c606SMark Murray rflags |= OCSP_NOCERTS; 1965c87c606SMark Murray else if (!strcmp(*args, "-resp_key_id")) 1975c87c606SMark Murray rflags |= OCSP_RESPID_KEY; 1985c87c606SMark Murray else if (!strcmp(*args, "-no_certs")) 1995c87c606SMark Murray sign_flags |= OCSP_NOCERTS; 2005c87c606SMark Murray else if (!strcmp(*args, "-no_signature_verify")) 2015c87c606SMark Murray verify_flags |= OCSP_NOSIGS; 2025c87c606SMark Murray else if (!strcmp(*args, "-no_cert_verify")) 2035c87c606SMark Murray verify_flags |= OCSP_NOVERIFY; 2045c87c606SMark Murray else if (!strcmp(*args, "-no_chain")) 2055c87c606SMark Murray verify_flags |= OCSP_NOCHAIN; 2065c87c606SMark Murray else if (!strcmp(*args, "-no_cert_checks")) 2075c87c606SMark Murray verify_flags |= OCSP_NOCHECKS; 2085c87c606SMark Murray else if (!strcmp(*args, "-no_explicit")) 2095c87c606SMark Murray verify_flags |= OCSP_NOEXPLICIT; 2105c87c606SMark Murray else if (!strcmp(*args, "-trust_other")) 2115c87c606SMark Murray verify_flags |= OCSP_TRUSTOTHER; 2125c87c606SMark Murray else if (!strcmp(*args, "-no_intern")) 2135c87c606SMark Murray verify_flags |= OCSP_NOINTERN; 2145c87c606SMark Murray else if (!strcmp(*args, "-text")) 2155c87c606SMark Murray { 2165c87c606SMark Murray req_text = 1; 2175c87c606SMark Murray resp_text = 1; 2185c87c606SMark Murray } 2195c87c606SMark Murray else if (!strcmp(*args, "-req_text")) 2205c87c606SMark Murray req_text = 1; 2215c87c606SMark Murray else if (!strcmp(*args, "-resp_text")) 2225c87c606SMark Murray resp_text = 1; 2235c87c606SMark Murray else if (!strcmp(*args, "-reqin")) 2245c87c606SMark Murray { 2255c87c606SMark Murray if (args[1]) 2265c87c606SMark Murray { 2275c87c606SMark Murray args++; 2285c87c606SMark Murray reqin = *args; 2295c87c606SMark Murray } 2305c87c606SMark Murray else badarg = 1; 2315c87c606SMark Murray } 2325c87c606SMark Murray else if (!strcmp(*args, "-respin")) 2335c87c606SMark Murray { 2345c87c606SMark Murray if (args[1]) 2355c87c606SMark Murray { 2365c87c606SMark Murray args++; 2375c87c606SMark Murray respin = *args; 2385c87c606SMark Murray } 2395c87c606SMark Murray else badarg = 1; 2405c87c606SMark Murray } 2415c87c606SMark Murray else if (!strcmp(*args, "-signer")) 2425c87c606SMark Murray { 2435c87c606SMark Murray if (args[1]) 2445c87c606SMark Murray { 2455c87c606SMark Murray args++; 2465c87c606SMark Murray signfile = *args; 2475c87c606SMark Murray } 2485c87c606SMark Murray else badarg = 1; 2495c87c606SMark Murray } 2505c87c606SMark Murray else if (!strcmp (*args, "-VAfile")) 2515c87c606SMark Murray { 2525c87c606SMark Murray if (args[1]) 2535c87c606SMark Murray { 2545c87c606SMark Murray args++; 2555c87c606SMark Murray verify_certfile = *args; 2565c87c606SMark Murray verify_flags |= OCSP_TRUSTOTHER; 2575c87c606SMark Murray } 2585c87c606SMark Murray else badarg = 1; 2595c87c606SMark Murray } 2605c87c606SMark Murray else if (!strcmp(*args, "-sign_other")) 2615c87c606SMark Murray { 2625c87c606SMark Murray if (args[1]) 2635c87c606SMark Murray { 2645c87c606SMark Murray args++; 2655c87c606SMark Murray sign_certfile = *args; 2665c87c606SMark Murray } 2675c87c606SMark Murray else badarg = 1; 2685c87c606SMark Murray } 2695c87c606SMark Murray else if (!strcmp(*args, "-verify_other")) 2705c87c606SMark Murray { 2715c87c606SMark Murray if (args[1]) 2725c87c606SMark Murray { 2735c87c606SMark Murray args++; 2745c87c606SMark Murray verify_certfile = *args; 2755c87c606SMark Murray } 2765c87c606SMark Murray else badarg = 1; 2775c87c606SMark Murray } 2785c87c606SMark Murray else if (!strcmp (*args, "-CAfile")) 2795c87c606SMark Murray { 2805c87c606SMark Murray if (args[1]) 2815c87c606SMark Murray { 2825c87c606SMark Murray args++; 2835c87c606SMark Murray CAfile = *args; 2845c87c606SMark Murray } 2855c87c606SMark Murray else badarg = 1; 2865c87c606SMark Murray } 2875c87c606SMark Murray else if (!strcmp (*args, "-CApath")) 2885c87c606SMark Murray { 2895c87c606SMark Murray if (args[1]) 2905c87c606SMark Murray { 2915c87c606SMark Murray args++; 2925c87c606SMark Murray CApath = *args; 2935c87c606SMark Murray } 2945c87c606SMark Murray else badarg = 1; 2955c87c606SMark Murray } 2965c87c606SMark Murray else if (!strcmp (*args, "-validity_period")) 2975c87c606SMark Murray { 2985c87c606SMark Murray if (args[1]) 2995c87c606SMark Murray { 3005c87c606SMark Murray args++; 3015c87c606SMark Murray nsec = atol(*args); 3025c87c606SMark Murray if (nsec < 0) 3035c87c606SMark Murray { 3045c87c606SMark Murray BIO_printf(bio_err, 3055c87c606SMark Murray "Illegal validity period %s\n", 3065c87c606SMark Murray *args); 3075c87c606SMark Murray badarg = 1; 3085c87c606SMark Murray } 3095c87c606SMark Murray } 3105c87c606SMark Murray else badarg = 1; 3115c87c606SMark Murray } 3125c87c606SMark Murray else if (!strcmp (*args, "-status_age")) 3135c87c606SMark Murray { 3145c87c606SMark Murray if (args[1]) 3155c87c606SMark Murray { 3165c87c606SMark Murray args++; 3175c87c606SMark Murray maxage = atol(*args); 3185c87c606SMark Murray if (maxage < 0) 3195c87c606SMark Murray { 3205c87c606SMark Murray BIO_printf(bio_err, 3215c87c606SMark Murray "Illegal validity age %s\n", 3225c87c606SMark Murray *args); 3235c87c606SMark Murray badarg = 1; 3245c87c606SMark Murray } 3255c87c606SMark Murray } 3265c87c606SMark Murray else badarg = 1; 3275c87c606SMark Murray } 3285c87c606SMark Murray else if (!strcmp(*args, "-signkey")) 3295c87c606SMark Murray { 3305c87c606SMark Murray if (args[1]) 3315c87c606SMark Murray { 3325c87c606SMark Murray args++; 3335c87c606SMark Murray keyfile = *args; 3345c87c606SMark Murray } 3355c87c606SMark Murray else badarg = 1; 3365c87c606SMark Murray } 3375c87c606SMark Murray else if (!strcmp(*args, "-reqout")) 3385c87c606SMark Murray { 3395c87c606SMark Murray if (args[1]) 3405c87c606SMark Murray { 3415c87c606SMark Murray args++; 3425c87c606SMark Murray reqout = *args; 3435c87c606SMark Murray } 3445c87c606SMark Murray else badarg = 1; 3455c87c606SMark Murray } 3465c87c606SMark Murray else if (!strcmp(*args, "-respout")) 3475c87c606SMark Murray { 3485c87c606SMark Murray if (args[1]) 3495c87c606SMark Murray { 3505c87c606SMark Murray args++; 3515c87c606SMark Murray respout = *args; 3525c87c606SMark Murray } 3535c87c606SMark Murray else badarg = 1; 3545c87c606SMark Murray } 3555c87c606SMark Murray else if (!strcmp(*args, "-path")) 3565c87c606SMark Murray { 3575c87c606SMark Murray if (args[1]) 3585c87c606SMark Murray { 3595c87c606SMark Murray args++; 3605c87c606SMark Murray path = *args; 3615c87c606SMark Murray } 3625c87c606SMark Murray else badarg = 1; 3635c87c606SMark Murray } 3645c87c606SMark Murray else if (!strcmp(*args, "-issuer")) 3655c87c606SMark Murray { 3665c87c606SMark Murray if (args[1]) 3675c87c606SMark Murray { 3685c87c606SMark Murray args++; 3695c87c606SMark Murray X509_free(issuer); 3705c87c606SMark Murray issuer = load_cert(bio_err, *args, FORMAT_PEM, 3715c87c606SMark Murray NULL, e, "issuer certificate"); 3725c87c606SMark Murray if(!issuer) goto end; 3735c87c606SMark Murray } 3745c87c606SMark Murray else badarg = 1; 3755c87c606SMark Murray } 3765c87c606SMark Murray else if (!strcmp (*args, "-cert")) 3775c87c606SMark Murray { 3785c87c606SMark Murray if (args[1]) 3795c87c606SMark Murray { 3805c87c606SMark Murray args++; 3815c87c606SMark Murray X509_free(cert); 3825c87c606SMark Murray cert = load_cert(bio_err, *args, FORMAT_PEM, 3835c87c606SMark Murray NULL, e, "certificate"); 3845c87c606SMark Murray if(!cert) goto end; 3855c87c606SMark Murray if(!add_ocsp_cert(&req, cert, issuer, ids)) 3865c87c606SMark Murray goto end; 3875c87c606SMark Murray if(!sk_push(reqnames, *args)) 3885c87c606SMark Murray goto end; 3895c87c606SMark Murray } 3905c87c606SMark Murray else badarg = 1; 3915c87c606SMark Murray } 3925c87c606SMark Murray else if (!strcmp(*args, "-serial")) 3935c87c606SMark Murray { 3945c87c606SMark Murray if (args[1]) 3955c87c606SMark Murray { 3965c87c606SMark Murray args++; 3975c87c606SMark Murray if(!add_ocsp_serial(&req, *args, issuer, ids)) 3985c87c606SMark Murray goto end; 3995c87c606SMark Murray if(!sk_push(reqnames, *args)) 4005c87c606SMark Murray goto end; 4015c87c606SMark Murray } 4025c87c606SMark Murray else badarg = 1; 4035c87c606SMark Murray } 4045c87c606SMark Murray else if (!strcmp(*args, "-index")) 4055c87c606SMark Murray { 4065c87c606SMark Murray if (args[1]) 4075c87c606SMark Murray { 4085c87c606SMark Murray args++; 4095c87c606SMark Murray ridx_filename = *args; 4105c87c606SMark Murray } 4115c87c606SMark Murray else badarg = 1; 4125c87c606SMark Murray } 4135c87c606SMark Murray else if (!strcmp(*args, "-CA")) 4145c87c606SMark Murray { 4155c87c606SMark Murray if (args[1]) 4165c87c606SMark Murray { 4175c87c606SMark Murray args++; 4185c87c606SMark Murray rca_filename = *args; 4195c87c606SMark Murray } 4205c87c606SMark Murray else badarg = 1; 4215c87c606SMark Murray } 4225c87c606SMark Murray else if (!strcmp (*args, "-nmin")) 4235c87c606SMark Murray { 4245c87c606SMark Murray if (args[1]) 4255c87c606SMark Murray { 4265c87c606SMark Murray args++; 4275c87c606SMark Murray nmin = atol(*args); 4285c87c606SMark Murray if (nmin < 0) 4295c87c606SMark Murray { 4305c87c606SMark Murray BIO_printf(bio_err, 4315c87c606SMark Murray "Illegal update period %s\n", 4325c87c606SMark Murray *args); 4335c87c606SMark Murray badarg = 1; 4345c87c606SMark Murray } 4355c87c606SMark Murray } 4365c87c606SMark Murray if (ndays == -1) 4375c87c606SMark Murray ndays = 0; 4385c87c606SMark Murray else badarg = 1; 4395c87c606SMark Murray } 4405c87c606SMark Murray else if (!strcmp (*args, "-nrequest")) 4415c87c606SMark Murray { 4425c87c606SMark Murray if (args[1]) 4435c87c606SMark Murray { 4445c87c606SMark Murray args++; 4455c87c606SMark Murray accept_count = atol(*args); 4465c87c606SMark Murray if (accept_count < 0) 4475c87c606SMark Murray { 4485c87c606SMark Murray BIO_printf(bio_err, 4495c87c606SMark Murray "Illegal accept count %s\n", 4505c87c606SMark Murray *args); 4515c87c606SMark Murray badarg = 1; 4525c87c606SMark Murray } 4535c87c606SMark Murray } 4545c87c606SMark Murray else badarg = 1; 4555c87c606SMark Murray } 4565c87c606SMark Murray else if (!strcmp (*args, "-ndays")) 4575c87c606SMark Murray { 4585c87c606SMark Murray if (args[1]) 4595c87c606SMark Murray { 4605c87c606SMark Murray args++; 4615c87c606SMark Murray ndays = atol(*args); 4625c87c606SMark Murray if (ndays < 0) 4635c87c606SMark Murray { 4645c87c606SMark Murray BIO_printf(bio_err, 4655c87c606SMark Murray "Illegal update period %s\n", 4665c87c606SMark Murray *args); 4675c87c606SMark Murray badarg = 1; 4685c87c606SMark Murray } 4695c87c606SMark Murray } 4705c87c606SMark Murray else badarg = 1; 4715c87c606SMark Murray } 4725c87c606SMark Murray else if (!strcmp(*args, "-rsigner")) 4735c87c606SMark Murray { 4745c87c606SMark Murray if (args[1]) 4755c87c606SMark Murray { 4765c87c606SMark Murray args++; 4775c87c606SMark Murray rsignfile = *args; 4785c87c606SMark Murray } 4795c87c606SMark Murray else badarg = 1; 4805c87c606SMark Murray } 4815c87c606SMark Murray else if (!strcmp(*args, "-rkey")) 4825c87c606SMark Murray { 4835c87c606SMark Murray if (args[1]) 4845c87c606SMark Murray { 4855c87c606SMark Murray args++; 4865c87c606SMark Murray rkeyfile = *args; 4875c87c606SMark Murray } 4885c87c606SMark Murray else badarg = 1; 4895c87c606SMark Murray } 4905c87c606SMark Murray else if (!strcmp(*args, "-rother")) 4915c87c606SMark Murray { 4925c87c606SMark Murray if (args[1]) 4935c87c606SMark Murray { 4945c87c606SMark Murray args++; 4955c87c606SMark Murray rcertfile = *args; 4965c87c606SMark Murray } 4975c87c606SMark Murray else badarg = 1; 4985c87c606SMark Murray } 4995c87c606SMark Murray else badarg = 1; 5005c87c606SMark Murray args++; 5015c87c606SMark Murray } 5025c87c606SMark Murray 5035c87c606SMark Murray /* Have we anything to do? */ 5045c87c606SMark Murray if (!req && !reqin && !respin && !(port && ridx_filename)) badarg = 1; 5055c87c606SMark Murray 5065c87c606SMark Murray if (badarg) 5075c87c606SMark Murray { 5085c87c606SMark Murray BIO_printf (bio_err, "OCSP utility\n"); 5095c87c606SMark Murray BIO_printf (bio_err, "Usage ocsp [options]\n"); 5105c87c606SMark Murray BIO_printf (bio_err, "where options are\n"); 5115c87c606SMark Murray BIO_printf (bio_err, "-out file output filename\n"); 5125c87c606SMark Murray BIO_printf (bio_err, "-issuer file issuer certificate\n"); 5135c87c606SMark Murray BIO_printf (bio_err, "-cert file certificate to check\n"); 5145c87c606SMark Murray BIO_printf (bio_err, "-serial n serial number to check\n"); 5155c87c606SMark Murray BIO_printf (bio_err, "-signer file certificate to sign OCSP request with\n"); 5165c87c606SMark Murray BIO_printf (bio_err, "-signkey file private key to sign OCSP request with\n"); 51750ef0093SJacques Vidrine BIO_printf (bio_err, "-sign_other file additional certificates to include in signed request\n"); 5185c87c606SMark Murray BIO_printf (bio_err, "-no_certs don't include any certificates in signed request\n"); 5195c87c606SMark Murray BIO_printf (bio_err, "-req_text print text form of request\n"); 5205c87c606SMark Murray BIO_printf (bio_err, "-resp_text print text form of response\n"); 5215c87c606SMark Murray BIO_printf (bio_err, "-text print text form of request and response\n"); 5225c87c606SMark Murray BIO_printf (bio_err, "-reqout file write DER encoded OCSP request to \"file\"\n"); 5235c87c606SMark Murray BIO_printf (bio_err, "-respout file write DER encoded OCSP reponse to \"file\"\n"); 5245c87c606SMark Murray BIO_printf (bio_err, "-reqin file read DER encoded OCSP request from \"file\"\n"); 5255c87c606SMark Murray BIO_printf (bio_err, "-respin file read DER encoded OCSP reponse from \"file\"\n"); 5265c87c606SMark Murray BIO_printf (bio_err, "-nonce add OCSP nonce to request\n"); 5275c87c606SMark Murray BIO_printf (bio_err, "-no_nonce don't add OCSP nonce to request\n"); 5285c87c606SMark Murray BIO_printf (bio_err, "-url URL OCSP responder URL\n"); 5295c87c606SMark Murray BIO_printf (bio_err, "-host host:n send OCSP request to host on port n\n"); 5305c87c606SMark Murray BIO_printf (bio_err, "-path path to use in OCSP request\n"); 5315c87c606SMark Murray BIO_printf (bio_err, "-CApath dir trusted certificates directory\n"); 5325c87c606SMark Murray BIO_printf (bio_err, "-CAfile file trusted certificates file\n"); 5335c87c606SMark Murray BIO_printf (bio_err, "-VAfile file validator certificates file\n"); 5345c87c606SMark Murray BIO_printf (bio_err, "-validity_period n maximum validity discrepancy in seconds\n"); 5355c87c606SMark Murray BIO_printf (bio_err, "-status_age n maximum status age in seconds\n"); 5365c87c606SMark Murray BIO_printf (bio_err, "-noverify don't verify response at all\n"); 53750ef0093SJacques Vidrine BIO_printf (bio_err, "-verify_other file additional certificates to search for signer\n"); 5385c87c606SMark Murray BIO_printf (bio_err, "-trust_other don't verify additional certificates\n"); 5395c87c606SMark Murray BIO_printf (bio_err, "-no_intern don't search certificates contained in response for signer\n"); 54050ef0093SJacques Vidrine BIO_printf (bio_err, "-no_signature_verify don't check signature on response\n"); 5415c87c606SMark Murray BIO_printf (bio_err, "-no_cert_verify don't check signing certificate\n"); 5425c87c606SMark Murray BIO_printf (bio_err, "-no_chain don't chain verify response\n"); 5435c87c606SMark Murray BIO_printf (bio_err, "-no_cert_checks don't do additional checks on signing certificate\n"); 5445c87c606SMark Murray BIO_printf (bio_err, "-port num port to run responder on\n"); 5455c87c606SMark Murray BIO_printf (bio_err, "-index file certificate status index file\n"); 5465c87c606SMark Murray BIO_printf (bio_err, "-CA file CA certificate\n"); 5475c87c606SMark Murray BIO_printf (bio_err, "-rsigner file responder certificate to sign responses with\n"); 5485c87c606SMark Murray BIO_printf (bio_err, "-rkey file responder key to sign responses with\n"); 5495c87c606SMark Murray BIO_printf (bio_err, "-rother file other certificates to include in response\n"); 5505c87c606SMark Murray BIO_printf (bio_err, "-resp_no_certs don't include any certificates in response\n"); 5515c87c606SMark Murray BIO_printf (bio_err, "-nmin n number of minutes before next update\n"); 5525c87c606SMark Murray BIO_printf (bio_err, "-ndays n number of days before next update\n"); 5535c87c606SMark Murray BIO_printf (bio_err, "-resp_key_id identify reponse by signing certificate key ID\n"); 5545c87c606SMark Murray BIO_printf (bio_err, "-nrequest n number of requests to accept (default unlimited)\n"); 5555c87c606SMark Murray goto end; 5565c87c606SMark Murray } 5575c87c606SMark Murray 5585c87c606SMark Murray if(outfile) out = BIO_new_file(outfile, "w"); 5595c87c606SMark Murray else out = BIO_new_fp(stdout, BIO_NOCLOSE); 5605c87c606SMark Murray 5615c87c606SMark Murray if(!out) 5625c87c606SMark Murray { 5635c87c606SMark Murray BIO_printf(bio_err, "Error opening output file\n"); 5645c87c606SMark Murray goto end; 5655c87c606SMark Murray } 5665c87c606SMark Murray 5675c87c606SMark Murray if (!req && (add_nonce != 2)) add_nonce = 0; 5685c87c606SMark Murray 5695c87c606SMark Murray if (!req && reqin) 5705c87c606SMark Murray { 5715c87c606SMark Murray derbio = BIO_new_file(reqin, "rb"); 5725c87c606SMark Murray if (!derbio) 5735c87c606SMark Murray { 5745c87c606SMark Murray BIO_printf(bio_err, "Error Opening OCSP request file\n"); 5755c87c606SMark Murray goto end; 5765c87c606SMark Murray } 5775c87c606SMark Murray req = d2i_OCSP_REQUEST_bio(derbio, NULL); 5785c87c606SMark Murray BIO_free(derbio); 5795c87c606SMark Murray if(!req) 5805c87c606SMark Murray { 5815c87c606SMark Murray BIO_printf(bio_err, "Error reading OCSP request\n"); 5825c87c606SMark Murray goto end; 5835c87c606SMark Murray } 5845c87c606SMark Murray } 5855c87c606SMark Murray 5865c87c606SMark Murray if (!req && port) 5875c87c606SMark Murray { 5885c87c606SMark Murray acbio = init_responder(port); 5895c87c606SMark Murray if (!acbio) 5905c87c606SMark Murray goto end; 5915c87c606SMark Murray } 5925c87c606SMark Murray 5935c87c606SMark Murray if (rsignfile && !rdb) 5945c87c606SMark Murray { 5955c87c606SMark Murray if (!rkeyfile) rkeyfile = rsignfile; 5965c87c606SMark Murray rsigner = load_cert(bio_err, rsignfile, FORMAT_PEM, 5975c87c606SMark Murray NULL, e, "responder certificate"); 5985c87c606SMark Murray if (!rsigner) 5995c87c606SMark Murray { 6005c87c606SMark Murray BIO_printf(bio_err, "Error loading responder certificate\n"); 6015c87c606SMark Murray goto end; 6025c87c606SMark Murray } 6035c87c606SMark Murray rca_cert = load_cert(bio_err, rca_filename, FORMAT_PEM, 6045c87c606SMark Murray NULL, e, "CA certificate"); 6055c87c606SMark Murray if (rcertfile) 6065c87c606SMark Murray { 6075c87c606SMark Murray rother = load_certs(bio_err, rcertfile, FORMAT_PEM, 6085c87c606SMark Murray NULL, e, "responder other certificates"); 6095c87c606SMark Murray if (!rother) goto end; 6105c87c606SMark Murray } 6115c87c606SMark Murray rkey = load_key(bio_err, rkeyfile, FORMAT_PEM, 0, NULL, NULL, 6125c87c606SMark Murray "responder private key"); 6135c87c606SMark Murray if (!rkey) 6145c87c606SMark Murray goto end; 6155c87c606SMark Murray } 6165c87c606SMark Murray if(acbio) 6175c87c606SMark Murray BIO_printf(bio_err, "Waiting for OCSP client connections...\n"); 6185c87c606SMark Murray 6195c87c606SMark Murray redo_accept: 6205c87c606SMark Murray 6215c87c606SMark Murray if (acbio) 6225c87c606SMark Murray { 6235c87c606SMark Murray if (!do_responder(&req, &cbio, acbio, port)) 6245c87c606SMark Murray goto end; 6255c87c606SMark Murray if (!req) 6265c87c606SMark Murray { 6275c87c606SMark Murray resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL); 6285c87c606SMark Murray send_ocsp_response(cbio, resp); 6295c87c606SMark Murray goto done_resp; 6305c87c606SMark Murray } 6315c87c606SMark Murray } 6325c87c606SMark Murray 6335c87c606SMark Murray if (!req && (signfile || reqout || host || add_nonce || ridx_filename)) 6345c87c606SMark Murray { 6355c87c606SMark Murray BIO_printf(bio_err, "Need an OCSP request for this operation!\n"); 6365c87c606SMark Murray goto end; 6375c87c606SMark Murray } 6385c87c606SMark Murray 6395c87c606SMark Murray if (req && add_nonce) OCSP_request_add1_nonce(req, NULL, -1); 6405c87c606SMark Murray 6415c87c606SMark Murray if (signfile) 6425c87c606SMark Murray { 6435c87c606SMark Murray if (!keyfile) keyfile = signfile; 6445c87c606SMark Murray signer = load_cert(bio_err, signfile, FORMAT_PEM, 6455c87c606SMark Murray NULL, e, "signer certificate"); 6465c87c606SMark Murray if (!signer) 6475c87c606SMark Murray { 6485c87c606SMark Murray BIO_printf(bio_err, "Error loading signer certificate\n"); 6495c87c606SMark Murray goto end; 6505c87c606SMark Murray } 6515c87c606SMark Murray if (sign_certfile) 6525c87c606SMark Murray { 6535c87c606SMark Murray sign_other = load_certs(bio_err, sign_certfile, FORMAT_PEM, 6545c87c606SMark Murray NULL, e, "signer certificates"); 6555c87c606SMark Murray if (!sign_other) goto end; 6565c87c606SMark Murray } 6575c87c606SMark Murray key = load_key(bio_err, keyfile, FORMAT_PEM, 0, NULL, NULL, 6585c87c606SMark Murray "signer private key"); 6595c87c606SMark Murray if (!key) 6605c87c606SMark Murray goto end; 6615c87c606SMark Murray if (!OCSP_request_sign(req, signer, key, EVP_sha1(), sign_other, sign_flags)) 6625c87c606SMark Murray { 6635c87c606SMark Murray BIO_printf(bio_err, "Error signing OCSP request\n"); 6645c87c606SMark Murray goto end; 6655c87c606SMark Murray } 6665c87c606SMark Murray } 6675c87c606SMark Murray 6685c87c606SMark Murray if (req_text && req) OCSP_REQUEST_print(out, req, 0); 6695c87c606SMark Murray 6705c87c606SMark Murray if (reqout) 6715c87c606SMark Murray { 6725c87c606SMark Murray derbio = BIO_new_file(reqout, "wb"); 6735c87c606SMark Murray if(!derbio) 6745c87c606SMark Murray { 6755c87c606SMark Murray BIO_printf(bio_err, "Error opening file %s\n", reqout); 6765c87c606SMark Murray goto end; 6775c87c606SMark Murray } 6785c87c606SMark Murray i2d_OCSP_REQUEST_bio(derbio, req); 6795c87c606SMark Murray BIO_free(derbio); 6805c87c606SMark Murray } 6815c87c606SMark Murray 6825c87c606SMark Murray if (ridx_filename && (!rkey || !rsigner || !rca_cert)) 6835c87c606SMark Murray { 6845c87c606SMark Murray BIO_printf(bio_err, "Need a responder certificate, key and CA for this operation!\n"); 6855c87c606SMark Murray goto end; 6865c87c606SMark Murray } 6875c87c606SMark Murray 6885c87c606SMark Murray if (ridx_filename && !rdb) 6895c87c606SMark Murray { 690ced566fdSJacques Vidrine rdb = load_index(ridx_filename, NULL); 691ced566fdSJacques Vidrine if (!rdb) goto end; 692ced566fdSJacques Vidrine if (!index_index(rdb)) goto end; 6935c87c606SMark Murray } 6945c87c606SMark Murray 6955c87c606SMark Murray if (rdb) 6965c87c606SMark Murray { 6975c87c606SMark Murray i = make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey, rother, rflags, nmin, ndays); 6985c87c606SMark Murray if (cbio) 6995c87c606SMark Murray send_ocsp_response(cbio, resp); 7005c87c606SMark Murray } 7015c87c606SMark Murray else if (host) 7025c87c606SMark Murray { 703fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_SOCK 7045c87c606SMark Murray cbio = BIO_new_connect(host); 705fceca8a3SJacques Vidrine #else 706fceca8a3SJacques Vidrine BIO_printf(bio_err, "Error creating connect BIO - sockets not supported.\n"); 707fceca8a3SJacques Vidrine goto end; 708fceca8a3SJacques Vidrine #endif 7095c87c606SMark Murray if (!cbio) 7105c87c606SMark Murray { 7115c87c606SMark Murray BIO_printf(bio_err, "Error creating connect BIO\n"); 7125c87c606SMark Murray goto end; 7135c87c606SMark Murray } 7145c87c606SMark Murray if (port) BIO_set_conn_port(cbio, port); 7155c87c606SMark Murray if (use_ssl == 1) 7165c87c606SMark Murray { 7175c87c606SMark Murray BIO *sbio; 718fceca8a3SJacques Vidrine #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) 7195c87c606SMark Murray ctx = SSL_CTX_new(SSLv23_client_method()); 720fceca8a3SJacques Vidrine #elif !defined(OPENSSL_NO_SSL3) 721fceca8a3SJacques Vidrine ctx = SSL_CTX_new(SSLv3_client_method()); 722fceca8a3SJacques Vidrine #elif !defined(OPENSSL_NO_SSL2) 723fceca8a3SJacques Vidrine ctx = SSL_CTX_new(SSLv2_client_method()); 724fceca8a3SJacques Vidrine #else 725fceca8a3SJacques Vidrine BIO_printf(bio_err, "SSL is disabled\n"); 726fceca8a3SJacques Vidrine goto end; 727fceca8a3SJacques Vidrine #endif 7285c87c606SMark Murray SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); 7295c87c606SMark Murray sbio = BIO_new_ssl(ctx, 1); 7305c87c606SMark Murray cbio = BIO_push(sbio, cbio); 7315c87c606SMark Murray } 7325c87c606SMark Murray if (BIO_do_connect(cbio) <= 0) 7335c87c606SMark Murray { 7345c87c606SMark Murray BIO_printf(bio_err, "Error connecting BIO\n"); 7355c87c606SMark Murray goto end; 7365c87c606SMark Murray } 7375c87c606SMark Murray resp = OCSP_sendreq_bio(cbio, path, req); 7385c87c606SMark Murray BIO_free_all(cbio); 7395c87c606SMark Murray cbio = NULL; 7405c87c606SMark Murray if (!resp) 7415c87c606SMark Murray { 7425c87c606SMark Murray BIO_printf(bio_err, "Error querying OCSP responsder\n"); 7435c87c606SMark Murray goto end; 7445c87c606SMark Murray } 7455c87c606SMark Murray } 7465c87c606SMark Murray else if (respin) 7475c87c606SMark Murray { 7485c87c606SMark Murray derbio = BIO_new_file(respin, "rb"); 7495c87c606SMark Murray if (!derbio) 7505c87c606SMark Murray { 7515c87c606SMark Murray BIO_printf(bio_err, "Error Opening OCSP response file\n"); 7525c87c606SMark Murray goto end; 7535c87c606SMark Murray } 7545c87c606SMark Murray resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); 7555c87c606SMark Murray BIO_free(derbio); 7565c87c606SMark Murray if(!resp) 7575c87c606SMark Murray { 7585c87c606SMark Murray BIO_printf(bio_err, "Error reading OCSP response\n"); 7595c87c606SMark Murray goto end; 7605c87c606SMark Murray } 7615c87c606SMark Murray 7625c87c606SMark Murray } 7635c87c606SMark Murray else 7645c87c606SMark Murray { 7655c87c606SMark Murray ret = 0; 7665c87c606SMark Murray goto end; 7675c87c606SMark Murray } 7685c87c606SMark Murray 7695c87c606SMark Murray done_resp: 7705c87c606SMark Murray 7715c87c606SMark Murray if (respout) 7725c87c606SMark Murray { 7735c87c606SMark Murray derbio = BIO_new_file(respout, "wb"); 7745c87c606SMark Murray if(!derbio) 7755c87c606SMark Murray { 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 7855c87c606SMark Murray if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) 7865c87c606SMark Murray { 7875c87c606SMark Murray BIO_printf(out, "Responder Error: %s (%ld)\n", 7885c87c606SMark Murray OCSP_response_status_str(i), i); 78950ef0093SJacques Vidrine if (ignore_err) 79050ef0093SJacques Vidrine goto redo_accept; 7915c87c606SMark Murray ret = 0; 7925c87c606SMark Murray goto end; 7935c87c606SMark Murray } 7945c87c606SMark Murray 7955c87c606SMark Murray if (resp_text) OCSP_RESPONSE_print(out, resp, 0); 7965c87c606SMark Murray 7975c87c606SMark Murray /* If running as responder don't verify our own response */ 7985c87c606SMark Murray if (cbio) 7995c87c606SMark Murray { 8005c87c606SMark Murray if (accept_count > 0) 8015c87c606SMark Murray accept_count--; 8025c87c606SMark Murray /* Redo if more connections needed */ 8035c87c606SMark Murray if (accept_count) 8045c87c606SMark Murray { 8055c87c606SMark Murray BIO_free_all(cbio); 8065c87c606SMark Murray cbio = NULL; 8075c87c606SMark Murray OCSP_REQUEST_free(req); 8085c87c606SMark Murray req = NULL; 8095c87c606SMark Murray OCSP_RESPONSE_free(resp); 8105c87c606SMark Murray resp = NULL; 8115c87c606SMark Murray goto redo_accept; 8125c87c606SMark Murray } 8135c87c606SMark Murray goto end; 8145c87c606SMark Murray } 8155c87c606SMark Murray 8165c87c606SMark Murray if (!store) 8175c87c606SMark Murray store = setup_verify(bio_err, CAfile, CApath); 8185c87c606SMark Murray if (!store) 8195c87c606SMark Murray goto end; 8205c87c606SMark Murray if (verify_certfile) 8215c87c606SMark Murray { 8225c87c606SMark Murray verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM, 8235c87c606SMark Murray NULL, e, "validator certificate"); 8245c87c606SMark Murray if (!verify_other) goto end; 8255c87c606SMark Murray } 8265c87c606SMark Murray 8275c87c606SMark Murray bs = OCSP_response_get1_basic(resp); 8285c87c606SMark Murray 8295c87c606SMark Murray if (!bs) 8305c87c606SMark Murray { 8315c87c606SMark Murray BIO_printf(bio_err, "Error parsing response\n"); 8325c87c606SMark Murray goto end; 8335c87c606SMark Murray } 8345c87c606SMark Murray 8355c87c606SMark Murray if (!noverify) 8365c87c606SMark Murray { 8375c87c606SMark Murray if (req && ((i = OCSP_check_nonce(req, bs)) <= 0)) 8385c87c606SMark Murray { 8395c87c606SMark Murray if (i == -1) 8405c87c606SMark Murray BIO_printf(bio_err, "WARNING: no nonce in response\n"); 8415c87c606SMark Murray else 8425c87c606SMark Murray { 8435c87c606SMark Murray BIO_printf(bio_err, "Nonce Verify error\n"); 8445c87c606SMark Murray goto end; 8455c87c606SMark Murray } 8465c87c606SMark Murray } 8475c87c606SMark Murray 8485c87c606SMark Murray i = OCSP_basic_verify(bs, verify_other, store, verify_flags); 8495c87c606SMark Murray if (i < 0) i = OCSP_basic_verify(bs, NULL, store, 0); 8505c87c606SMark Murray 8515c87c606SMark Murray if(i <= 0) 8525c87c606SMark Murray { 8535c87c606SMark Murray BIO_printf(bio_err, "Response Verify Failure\n", i); 8545c87c606SMark Murray ERR_print_errors(bio_err); 8555c87c606SMark Murray } 8565c87c606SMark Murray 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)) 8625c87c606SMark Murray goto end; 8635c87c606SMark Murray 8645c87c606SMark Murray ret = 0; 8655c87c606SMark Murray 8665c87c606SMark Murray end: 8675c87c606SMark Murray ERR_print_errors(bio_err); 8685c87c606SMark Murray X509_free(signer); 8695c87c606SMark Murray X509_STORE_free(store); 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); 8835c87c606SMark Murray sk_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); 8875c87c606SMark Murray 8885c87c606SMark Murray if (use_ssl != -1) 8895c87c606SMark Murray { 8905c87c606SMark Murray OPENSSL_free(host); 8915c87c606SMark Murray OPENSSL_free(port); 8925c87c606SMark Murray OPENSSL_free(path); 8935c87c606SMark Murray SSL_CTX_free(ctx); 8945c87c606SMark Murray } 8955c87c606SMark Murray 8965c87c606SMark Murray OPENSSL_EXIT(ret); 8975c87c606SMark Murray } 8985c87c606SMark Murray 8995c87c606SMark Murray static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer, 9005c87c606SMark Murray STACK_OF(OCSP_CERTID) *ids) 9015c87c606SMark Murray { 9025c87c606SMark Murray OCSP_CERTID *id; 9035c87c606SMark Murray if(!issuer) 9045c87c606SMark Murray { 9055c87c606SMark Murray BIO_printf(bio_err, "No issuer certificate specified\n"); 9065c87c606SMark Murray return 0; 9075c87c606SMark Murray } 9085c87c606SMark Murray if(!*req) *req = OCSP_REQUEST_new(); 9095c87c606SMark Murray if(!*req) goto err; 9105c87c606SMark Murray id = OCSP_cert_to_id(NULL, cert, issuer); 9115c87c606SMark Murray if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err; 9125c87c606SMark Murray if(!OCSP_request_add0_id(*req, id)) goto err; 9135c87c606SMark Murray return 1; 9145c87c606SMark Murray 9155c87c606SMark Murray err: 9165c87c606SMark Murray BIO_printf(bio_err, "Error Creating OCSP request\n"); 9175c87c606SMark Murray return 0; 9185c87c606SMark Murray } 9195c87c606SMark Murray 9205c87c606SMark Murray static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer, 9215c87c606SMark Murray STACK_OF(OCSP_CERTID) *ids) 9225c87c606SMark Murray { 9235c87c606SMark Murray OCSP_CERTID *id; 9245c87c606SMark Murray X509_NAME *iname; 9255c87c606SMark Murray ASN1_BIT_STRING *ikey; 9265c87c606SMark Murray ASN1_INTEGER *sno; 9275c87c606SMark Murray if(!issuer) 9285c87c606SMark Murray { 9295c87c606SMark Murray BIO_printf(bio_err, "No issuer certificate specified\n"); 9305c87c606SMark Murray return 0; 9315c87c606SMark Murray } 9325c87c606SMark Murray if(!*req) *req = OCSP_REQUEST_new(); 9335c87c606SMark Murray if(!*req) goto err; 9345c87c606SMark Murray iname = X509_get_subject_name(issuer); 9355c87c606SMark Murray ikey = X509_get0_pubkey_bitstr(issuer); 9365c87c606SMark Murray sno = s2i_ASN1_INTEGER(NULL, serial); 9375c87c606SMark Murray if(!sno) 9385c87c606SMark Murray { 9395c87c606SMark Murray BIO_printf(bio_err, "Error converting serial number %s\n", serial); 9405c87c606SMark Murray return 0; 9415c87c606SMark Murray } 9425c87c606SMark Murray id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno); 9435c87c606SMark Murray ASN1_INTEGER_free(sno); 9445c87c606SMark Murray if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err; 9455c87c606SMark Murray if(!OCSP_request_add0_id(*req, id)) goto err; 9465c87c606SMark Murray return 1; 9475c87c606SMark Murray 9485c87c606SMark Murray err: 9495c87c606SMark Murray BIO_printf(bio_err, "Error Creating OCSP request\n"); 9505c87c606SMark Murray return 0; 9515c87c606SMark Murray } 9525c87c606SMark Murray 9535c87c606SMark Murray static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, 9545c87c606SMark Murray STACK *names, STACK_OF(OCSP_CERTID) *ids, 9555c87c606SMark Murray long nsec, long maxage) 9565c87c606SMark Murray { 9575c87c606SMark Murray OCSP_CERTID *id; 9585c87c606SMark Murray char *name; 9595c87c606SMark Murray int i; 9605c87c606SMark Murray 9615c87c606SMark Murray int status, reason; 9625c87c606SMark Murray 9635c87c606SMark Murray ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; 9645c87c606SMark Murray 9655c87c606SMark Murray if (!bs || !req || !sk_num(names) || !sk_OCSP_CERTID_num(ids)) 9665c87c606SMark Murray return 1; 9675c87c606SMark Murray 9685c87c606SMark Murray for (i = 0; i < sk_OCSP_CERTID_num(ids); i++) 9695c87c606SMark Murray { 9705c87c606SMark Murray id = sk_OCSP_CERTID_value(ids, i); 9715c87c606SMark Murray name = sk_value(names, i); 9725c87c606SMark Murray BIO_printf(out, "%s: ", name); 9735c87c606SMark Murray 9745c87c606SMark Murray if(!OCSP_resp_find_status(bs, id, &status, &reason, 9755c87c606SMark Murray &rev, &thisupd, &nextupd)) 9765c87c606SMark Murray { 9775c87c606SMark Murray BIO_puts(out, "ERROR: No Status found.\n"); 9785c87c606SMark Murray continue; 9795c87c606SMark Murray } 9805c87c606SMark Murray 9815c87c606SMark Murray /* Check validity: if invalid write to output BIO so we 9825c87c606SMark Murray * know which response this refers to. 9835c87c606SMark Murray */ 9845c87c606SMark Murray if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) 9855c87c606SMark Murray { 9865c87c606SMark Murray BIO_puts(out, "WARNING: Status times invalid.\n"); 9875c87c606SMark Murray ERR_print_errors(out); 9885c87c606SMark Murray } 9895c87c606SMark Murray BIO_printf(out, "%s\n", OCSP_cert_status_str(status)); 9905c87c606SMark Murray 9915c87c606SMark Murray BIO_puts(out, "\tThis Update: "); 9925c87c606SMark Murray ASN1_GENERALIZEDTIME_print(out, thisupd); 9935c87c606SMark Murray BIO_puts(out, "\n"); 9945c87c606SMark Murray 9955c87c606SMark Murray if(nextupd) 9965c87c606SMark Murray { 9975c87c606SMark Murray BIO_puts(out, "\tNext Update: "); 9985c87c606SMark Murray ASN1_GENERALIZEDTIME_print(out, nextupd); 9995c87c606SMark Murray BIO_puts(out, "\n"); 10005c87c606SMark Murray } 10015c87c606SMark Murray 10025c87c606SMark Murray if (status != V_OCSP_CERTSTATUS_REVOKED) 10035c87c606SMark Murray continue; 10045c87c606SMark Murray 10055c87c606SMark Murray if (reason != -1) 10065c87c606SMark Murray BIO_printf(out, "\tReason: %s\n", 10075c87c606SMark Murray OCSP_crl_reason_str(reason)); 10085c87c606SMark Murray 10095c87c606SMark Murray BIO_puts(out, "\tRevocation Time: "); 10105c87c606SMark Murray ASN1_GENERALIZEDTIME_print(out, rev); 10115c87c606SMark Murray BIO_puts(out, "\n"); 10125c87c606SMark Murray } 10135c87c606SMark Murray 10145c87c606SMark Murray return 1; 10155c87c606SMark Murray } 10165c87c606SMark Murray 10175c87c606SMark Murray 1018ced566fdSJacques Vidrine static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, CA_DB *db, 10195c87c606SMark Murray X509 *ca, X509 *rcert, EVP_PKEY *rkey, 10205c87c606SMark Murray STACK_OF(X509) *rother, unsigned long flags, 10215c87c606SMark Murray int nmin, int ndays) 10225c87c606SMark Murray { 10235c87c606SMark Murray ASN1_TIME *thisupd = NULL, *nextupd = NULL; 10245c87c606SMark Murray OCSP_CERTID *cid, *ca_id = NULL; 10255c87c606SMark Murray OCSP_BASICRESP *bs = NULL; 10265c87c606SMark Murray int i, id_count, ret = 1; 10275c87c606SMark Murray 10285c87c606SMark Murray 10295c87c606SMark Murray id_count = OCSP_request_onereq_count(req); 10305c87c606SMark Murray 10315c87c606SMark Murray if (id_count <= 0) 10325c87c606SMark Murray { 10335c87c606SMark Murray *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL); 10345c87c606SMark Murray goto end; 10355c87c606SMark Murray } 10365c87c606SMark Murray 10375c87c606SMark Murray ca_id = OCSP_cert_to_id(EVP_sha1(), NULL, ca); 10385c87c606SMark Murray 10395c87c606SMark Murray bs = OCSP_BASICRESP_new(); 10405c87c606SMark Murray thisupd = X509_gmtime_adj(NULL, 0); 10415c87c606SMark Murray if (ndays != -1) 10425c87c606SMark Murray nextupd = X509_gmtime_adj(NULL, nmin * 60 + ndays * 3600 * 24 ); 10435c87c606SMark Murray 10445c87c606SMark Murray /* Examine each certificate id in the request */ 10455c87c606SMark Murray for (i = 0; i < id_count; i++) 10465c87c606SMark Murray { 10475c87c606SMark Murray OCSP_ONEREQ *one; 10485c87c606SMark Murray ASN1_INTEGER *serial; 10495c87c606SMark Murray char **inf; 10505c87c606SMark Murray one = OCSP_request_onereq_get0(req, i); 10515c87c606SMark Murray cid = OCSP_onereq_get0_id(one); 10525c87c606SMark Murray /* Is this request about our CA? */ 10535c87c606SMark Murray if (OCSP_id_issuer_cmp(ca_id, cid)) 10545c87c606SMark Murray { 10555c87c606SMark Murray OCSP_basic_add1_status(bs, cid, 10565c87c606SMark Murray V_OCSP_CERTSTATUS_UNKNOWN, 10575c87c606SMark Murray 0, NULL, 10585c87c606SMark Murray thisupd, nextupd); 10595c87c606SMark Murray continue; 10605c87c606SMark Murray } 10615c87c606SMark Murray OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid); 10625c87c606SMark Murray inf = lookup_serial(db, serial); 10635c87c606SMark Murray if (!inf) 10645c87c606SMark Murray OCSP_basic_add1_status(bs, cid, 10655c87c606SMark Murray V_OCSP_CERTSTATUS_UNKNOWN, 10665c87c606SMark Murray 0, NULL, 10675c87c606SMark Murray thisupd, nextupd); 10685c87c606SMark Murray else if (inf[DB_type][0] == DB_TYPE_VAL) 10695c87c606SMark Murray OCSP_basic_add1_status(bs, cid, 10705c87c606SMark Murray V_OCSP_CERTSTATUS_GOOD, 10715c87c606SMark Murray 0, NULL, 10725c87c606SMark Murray thisupd, nextupd); 10735c87c606SMark Murray else if (inf[DB_type][0] == DB_TYPE_REV) 10745c87c606SMark Murray { 10755c87c606SMark Murray ASN1_OBJECT *inst = NULL; 10765c87c606SMark Murray ASN1_TIME *revtm = NULL; 10775c87c606SMark Murray ASN1_GENERALIZEDTIME *invtm = NULL; 10785c87c606SMark Murray OCSP_SINGLERESP *single; 10795c87c606SMark Murray int reason = -1; 10805c87c606SMark Murray unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]); 10815c87c606SMark Murray single = OCSP_basic_add1_status(bs, cid, 10825c87c606SMark Murray V_OCSP_CERTSTATUS_REVOKED, 10835c87c606SMark Murray reason, revtm, 10845c87c606SMark Murray thisupd, nextupd); 10855c87c606SMark Murray if (invtm) 10865c87c606SMark Murray OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date, invtm, 0, 0); 10875c87c606SMark Murray else if (inst) 10885c87c606SMark Murray OCSP_SINGLERESP_add1_ext_i2d(single, NID_hold_instruction_code, inst, 0, 0); 10895c87c606SMark Murray ASN1_OBJECT_free(inst); 10905c87c606SMark Murray ASN1_TIME_free(revtm); 10915c87c606SMark Murray ASN1_GENERALIZEDTIME_free(invtm); 10925c87c606SMark Murray } 10935c87c606SMark Murray } 10945c87c606SMark Murray 10955c87c606SMark Murray OCSP_copy_nonce(bs, req); 10965c87c606SMark Murray 10975c87c606SMark Murray OCSP_basic_sign(bs, rcert, rkey, EVP_sha1(), rother, flags); 10985c87c606SMark Murray 10995c87c606SMark Murray *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs); 11005c87c606SMark Murray 11015c87c606SMark Murray end: 11025c87c606SMark Murray ASN1_TIME_free(thisupd); 11035c87c606SMark Murray ASN1_TIME_free(nextupd); 11045c87c606SMark Murray OCSP_CERTID_free(ca_id); 11055c87c606SMark Murray OCSP_BASICRESP_free(bs); 11065c87c606SMark Murray return ret; 11075c87c606SMark Murray 11085c87c606SMark Murray } 11095c87c606SMark Murray 1110ced566fdSJacques Vidrine static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser) 11115c87c606SMark Murray { 11125c87c606SMark Murray int i; 11135c87c606SMark Murray BIGNUM *bn = NULL; 11145c87c606SMark Murray char *itmp, *row[DB_NUMBER],**rrow; 11155c87c606SMark Murray for (i = 0; i < DB_NUMBER; i++) row[i] = NULL; 11165c87c606SMark Murray bn = ASN1_INTEGER_to_BN(ser,NULL); 11175c87c606SMark Murray if (BN_is_zero(bn)) 11185c87c606SMark Murray itmp = BUF_strdup("00"); 11195c87c606SMark Murray else 11205c87c606SMark Murray itmp = BN_bn2hex(bn); 11215c87c606SMark Murray row[DB_serial] = itmp; 11225c87c606SMark Murray BN_free(bn); 1123ced566fdSJacques Vidrine rrow=TXT_DB_get_by_index(db->db,DB_serial,row); 11245c87c606SMark Murray OPENSSL_free(itmp); 11255c87c606SMark Murray return rrow; 11265c87c606SMark Murray } 11275c87c606SMark Murray 11285c87c606SMark Murray /* Quick and dirty OCSP server: read in and parse input request */ 11295c87c606SMark Murray 11305c87c606SMark Murray static BIO *init_responder(char *port) 11315c87c606SMark Murray { 11325c87c606SMark Murray BIO *acbio = NULL, *bufbio = NULL; 11335c87c606SMark Murray bufbio = BIO_new(BIO_f_buffer()); 11345c87c606SMark Murray if (!bufbio) 11355c87c606SMark Murray goto err; 1136fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_SOCK 11375c87c606SMark Murray acbio = BIO_new_accept(port); 1138fceca8a3SJacques Vidrine #else 1139fceca8a3SJacques Vidrine BIO_printf(bio_err, "Error setting up accept BIO - sockets not supported.\n"); 1140fceca8a3SJacques Vidrine #endif 11415c87c606SMark Murray if (!acbio) 11425c87c606SMark Murray goto err; 11435c87c606SMark Murray BIO_set_accept_bios(acbio, bufbio); 11445c87c606SMark Murray bufbio = NULL; 11455c87c606SMark Murray 11465c87c606SMark Murray if (BIO_do_accept(acbio) <= 0) 11475c87c606SMark Murray { 11485c87c606SMark Murray BIO_printf(bio_err, "Error setting up accept BIO\n"); 11495c87c606SMark Murray ERR_print_errors(bio_err); 11505c87c606SMark Murray goto err; 11515c87c606SMark Murray } 11525c87c606SMark Murray 11535c87c606SMark Murray return acbio; 11545c87c606SMark Murray 11555c87c606SMark Murray err: 11565c87c606SMark Murray BIO_free_all(acbio); 11575c87c606SMark Murray BIO_free(bufbio); 11585c87c606SMark Murray return NULL; 11595c87c606SMark Murray } 11605c87c606SMark Murray 11615c87c606SMark Murray static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, char *port) 11625c87c606SMark Murray { 11635c87c606SMark Murray int have_post = 0, len; 11645c87c606SMark Murray OCSP_REQUEST *req = NULL; 11655c87c606SMark Murray char inbuf[1024]; 11665c87c606SMark Murray BIO *cbio = NULL; 11675c87c606SMark Murray 11685c87c606SMark Murray if (BIO_do_accept(acbio) <= 0) 11695c87c606SMark Murray { 11705c87c606SMark Murray BIO_printf(bio_err, "Error accepting connection\n"); 11715c87c606SMark Murray ERR_print_errors(bio_err); 11725c87c606SMark Murray return 0; 11735c87c606SMark Murray } 11745c87c606SMark Murray 11755c87c606SMark Murray cbio = BIO_pop(acbio); 11765c87c606SMark Murray *pcbio = cbio; 11775c87c606SMark Murray 11785c87c606SMark Murray for(;;) 11795c87c606SMark Murray { 11805c87c606SMark Murray len = BIO_gets(cbio, inbuf, sizeof inbuf); 11815c87c606SMark Murray if (len <= 0) 11825c87c606SMark Murray return 1; 11835c87c606SMark Murray /* Look for "POST" signalling start of query */ 11845c87c606SMark Murray if (!have_post) 11855c87c606SMark Murray { 11865c87c606SMark Murray if(strncmp(inbuf, "POST", 4)) 11875c87c606SMark Murray { 11885c87c606SMark Murray BIO_printf(bio_err, "Invalid request\n"); 11895c87c606SMark Murray return 1; 11905c87c606SMark Murray } 11915c87c606SMark Murray have_post = 1; 11925c87c606SMark Murray } 11935c87c606SMark Murray /* Look for end of headers */ 11945c87c606SMark Murray if ((inbuf[0] == '\r') || (inbuf[0] == '\n')) 11955c87c606SMark Murray break; 11965c87c606SMark Murray } 11975c87c606SMark Murray 11985c87c606SMark Murray /* Try to read OCSP request */ 11995c87c606SMark Murray 12005c87c606SMark Murray req = d2i_OCSP_REQUEST_bio(cbio, NULL); 12015c87c606SMark Murray 12025c87c606SMark Murray if (!req) 12035c87c606SMark Murray { 12045c87c606SMark Murray BIO_printf(bio_err, "Error parsing OCSP request\n"); 12055c87c606SMark Murray ERR_print_errors(bio_err); 12065c87c606SMark Murray } 12075c87c606SMark Murray 12085c87c606SMark Murray *preq = req; 12095c87c606SMark Murray 12105c87c606SMark Murray return 1; 12115c87c606SMark Murray 12125c87c606SMark Murray } 12135c87c606SMark Murray 12145c87c606SMark Murray static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp) 12155c87c606SMark Murray { 12165c87c606SMark Murray char http_resp[] = 12175c87c606SMark Murray "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n" 12185c87c606SMark Murray "Content-Length: %d\r\n\r\n"; 12195c87c606SMark Murray if (!cbio) 12205c87c606SMark Murray return 0; 12215c87c606SMark Murray BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL)); 12225c87c606SMark Murray i2d_OCSP_RESPONSE_bio(cbio, resp); 12235c87c606SMark Murray BIO_flush(cbio); 12245c87c606SMark Murray return 1; 12255c87c606SMark Murray } 12265c87c606SMark Murray 1227fceca8a3SJacques Vidrine #endif 1228