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