Main Page | Class List | Directories | File List | Class Members | File Members

ocsp.c

Go to the documentation of this file.
00001 /* ocsp.c */
00002 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
00003  * project 2000.
00004  */
00005 /* ====================================================================
00006  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  *
00012  * 1. Redistributions of source code must retain the above copyright
00013  *    notice, this list of conditions and the following disclaimer. 
00014  *
00015  * 2. Redistributions in binary form must reproduce the above copyright
00016  *    notice, this list of conditions and the following disclaimer in
00017  *    the documentation and/or other materials provided with the
00018  *    distribution.
00019  *
00020  * 3. All advertising materials mentioning features or use of this
00021  *    software must display the following acknowledgment:
00022  *    "This product includes software developed by the OpenSSL Project
00023  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
00024  *
00025  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
00026  *    endorse or promote products derived from this software without
00027  *    prior written permission. For written permission, please contact
00028  *    licensing@OpenSSL.org.
00029  *
00030  * 5. Products derived from this software may not be called "OpenSSL"
00031  *    nor may "OpenSSL" appear in their names without prior written
00032  *    permission of the OpenSSL Project.
00033  *
00034  * 6. Redistributions of any form whatsoever must retain the following
00035  *    acknowledgment:
00036  *    "This product includes software developed by the OpenSSL Project
00037  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
00038  *
00039  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
00040  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00041  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00042  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
00043  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00044  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00045  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00046  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00047  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00048  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00049  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00050  * OF THE POSSIBILITY OF SUCH DAMAGE.
00051  * ====================================================================
00052  *
00053  * This product includes cryptographic software written by Eric Young
00054  * (eay@cryptsoft.com).  This product includes software written by Tim
00055  * Hudson (tjh@cryptsoft.com).
00056  *
00057  */
00058 #ifndef OPENSSL_NO_OCSP
00059 
00060 #include <stdio.h>
00061 #include <string.h>
00062 #include "apps.h"
00063 #include <openssl/pem.h>
00064 #include <openssl/ocsp.h>
00065 #include <openssl/err.h>
00066 #include <openssl/ssl.h>
00067 #include <openssl/bn.h>
00068 
00069 /* Maximum leeway in validity period: default 5 minutes */
00070 #define MAX_VALIDITY_PERIOD     (5 * 60)
00071 
00072 static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
00073                                 STACK_OF(OCSP_CERTID) *ids);
00074 static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer,
00075                                 STACK_OF(OCSP_CERTID) *ids);
00076 static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
00077                                 STACK *names, STACK_OF(OCSP_CERTID) *ids,
00078                                 long nsec, long maxage);
00079 
00080 static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, CA_DB *db,
00081                         X509 *ca, X509 *rcert, EVP_PKEY *rkey,
00082                         STACK_OF(X509) *rother, unsigned long flags,
00083                         int nmin, int ndays);
00084 
00085 static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser);
00086 static BIO *init_responder(char *port);
00087 static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, char *port);
00088 static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp);
00089 
00090 #undef PROG
00091 #define PROG ocsp_main
00092 
00093 int MAIN(int, char **);
00094 
00095 int MAIN(int argc, char **argv)
00096         {
00097         ENGINE *e = NULL;
00098         char **args;
00099         char *host = NULL, *port = NULL, *path = "/";
00100         char *reqin = NULL, *respin = NULL;
00101         char *reqout = NULL, *respout = NULL;
00102         char *signfile = NULL, *keyfile = NULL;
00103         char *rsignfile = NULL, *rkeyfile = NULL;
00104         char *outfile = NULL;
00105         int add_nonce = 1, noverify = 0, use_ssl = -1;
00106         OCSP_REQUEST *req = NULL;
00107         OCSP_RESPONSE *resp = NULL;
00108         OCSP_BASICRESP *bs = NULL;
00109         X509 *issuer = NULL, *cert = NULL;
00110         X509 *signer = NULL, *rsigner = NULL;
00111         EVP_PKEY *key = NULL, *rkey = NULL;
00112         BIO *acbio = NULL, *cbio = NULL;
00113         BIO *derbio = NULL;
00114         BIO *out = NULL;
00115         int req_text = 0, resp_text = 0;
00116         long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
00117         char *CAfile = NULL, *CApath = NULL;
00118         X509_STORE *store = NULL;
00119         SSL_CTX *ctx = NULL;
00120         STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL;
00121         char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
00122         unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
00123         int ret = 1;
00124         int accept_count = -1;
00125         int badarg = 0;
00126         int i;
00127         int ignore_err = 0;
00128         STACK *reqnames = NULL;
00129         STACK_OF(OCSP_CERTID) *ids = NULL;
00130 
00131         X509 *rca_cert = NULL;
00132         char *ridx_filename = NULL;
00133         char *rca_filename = NULL;
00134         CA_DB *rdb = NULL;
00135         int nmin = 0, ndays = -1;
00136 
00137         if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
00138 
00139         if (!load_config(bio_err, NULL))
00140                 goto end;
00141         SSL_load_error_strings();
00142         args = argv + 1;
00143         reqnames = sk_new_null();
00144         ids = sk_OCSP_CERTID_new_null();
00145         while (!badarg && *args && *args[0] == '-')
00146                 {
00147                 if (!strcmp(*args, "-out"))
00148                         {
00149                         if (args[1])
00150                                 {
00151                                 args++;
00152                                 outfile = *args;
00153                                 }
00154                         else badarg = 1;
00155                         }
00156                 else if (!strcmp(*args, "-url"))
00157                         {
00158                         if (args[1])
00159                                 {
00160                                 args++;
00161                                 if (!OCSP_parse_url(*args, &host, &port, &path, &use_ssl))
00162                                         {
00163                                         BIO_printf(bio_err, "Error parsing URL\n");
00164                                         badarg = 1;
00165                                         }
00166                                 }
00167                         else badarg = 1;
00168                         }
00169                 else if (!strcmp(*args, "-host"))
00170                         {
00171                         if (args[1])
00172                                 {
00173                                 args++;
00174                                 host = *args;
00175                                 }
00176                         else badarg = 1;
00177                         }
00178                 else if (!strcmp(*args, "-port"))
00179                         {
00180                         if (args[1])
00181                                 {
00182                                 args++;
00183                                 port = *args;
00184                                 }
00185                         else badarg = 1;
00186                         }
00187                 else if (!strcmp(*args, "-ignore_err"))
00188                         ignore_err = 1;
00189                 else if (!strcmp(*args, "-noverify"))
00190                         noverify = 1;
00191                 else if (!strcmp(*args, "-nonce"))
00192                         add_nonce = 2;
00193                 else if (!strcmp(*args, "-no_nonce"))
00194                         add_nonce = 0;
00195                 else if (!strcmp(*args, "-resp_no_certs"))
00196                         rflags |= OCSP_NOCERTS;
00197                 else if (!strcmp(*args, "-resp_key_id"))
00198                         rflags |= OCSP_RESPID_KEY;
00199                 else if (!strcmp(*args, "-no_certs"))
00200                         sign_flags |= OCSP_NOCERTS;
00201                 else if (!strcmp(*args, "-no_signature_verify"))
00202                         verify_flags |= OCSP_NOSIGS;
00203                 else if (!strcmp(*args, "-no_cert_verify"))
00204                         verify_flags |= OCSP_NOVERIFY;
00205                 else if (!strcmp(*args, "-no_chain"))
00206                         verify_flags |= OCSP_NOCHAIN;
00207                 else if (!strcmp(*args, "-no_cert_checks"))
00208                         verify_flags |= OCSP_NOCHECKS;
00209                 else if (!strcmp(*args, "-no_explicit"))
00210                         verify_flags |= OCSP_NOEXPLICIT;
00211                 else if (!strcmp(*args, "-trust_other"))
00212                         verify_flags |= OCSP_TRUSTOTHER;
00213                 else if (!strcmp(*args, "-no_intern"))
00214                         verify_flags |= OCSP_NOINTERN;
00215                 else if (!strcmp(*args, "-text"))
00216                         {
00217                         req_text = 1;
00218                         resp_text = 1;
00219                         }
00220                 else if (!strcmp(*args, "-req_text"))
00221                         req_text = 1;
00222                 else if (!strcmp(*args, "-resp_text"))
00223                         resp_text = 1;
00224                 else if (!strcmp(*args, "-reqin"))
00225                         {
00226                         if (args[1])
00227                                 {
00228                                 args++;
00229                                 reqin = *args;
00230                                 }
00231                         else badarg = 1;
00232                         }
00233                 else if (!strcmp(*args, "-respin"))
00234                         {
00235                         if (args[1])
00236                                 {
00237                                 args++;
00238                                 respin = *args;
00239                                 }
00240                         else badarg = 1;
00241                         }
00242                 else if (!strcmp(*args, "-signer"))
00243                         {
00244                         if (args[1])
00245                                 {
00246                                 args++;
00247                                 signfile = *args;
00248                                 }
00249                         else badarg = 1;
00250                         }
00251                 else if (!strcmp (*args, "-VAfile"))
00252                         {
00253                         if (args[1])
00254                                 {
00255                                 args++;
00256                                 verify_certfile = *args;
00257                                 verify_flags |= OCSP_TRUSTOTHER;
00258                                 }
00259                         else badarg = 1;
00260                         }
00261                 else if (!strcmp(*args, "-sign_other"))
00262                         {
00263                         if (args[1])
00264                                 {
00265                                 args++;
00266                                 sign_certfile = *args;
00267                                 }
00268                         else badarg = 1;
00269                         }
00270                 else if (!strcmp(*args, "-verify_other"))
00271                         {
00272                         if (args[1])
00273                                 {
00274                                 args++;
00275                                 verify_certfile = *args;
00276                                 }
00277                         else badarg = 1;
00278                         }
00279                 else if (!strcmp (*args, "-CAfile"))
00280                         {
00281                         if (args[1])
00282                                 {
00283                                 args++;
00284                                 CAfile = *args;
00285                                 }
00286                         else badarg = 1;
00287                         }
00288                 else if (!strcmp (*args, "-CApath"))
00289                         {
00290                         if (args[1])
00291                                 {
00292                                 args++;
00293                                 CApath = *args;
00294                                 }
00295                         else badarg = 1;
00296                         }
00297                 else if (!strcmp (*args, "-validity_period"))
00298                         {
00299                         if (args[1])
00300                                 {
00301                                 args++;
00302                                 nsec = atol(*args);
00303                                 if (nsec < 0)
00304                                         {
00305                                         BIO_printf(bio_err,
00306                                                 "Illegal validity period %s\n",
00307                                                 *args);
00308                                         badarg = 1;
00309                                         }
00310                                 }
00311                         else badarg = 1;
00312                         }
00313                 else if (!strcmp (*args, "-status_age"))
00314                         {
00315                         if (args[1])
00316                                 {
00317                                 args++;
00318                                 maxage = atol(*args);
00319                                 if (maxage < 0)
00320                                         {
00321                                         BIO_printf(bio_err,
00322                                                 "Illegal validity age %s\n",
00323                                                 *args);
00324                                         badarg = 1;
00325                                         }
00326                                 }
00327                         else badarg = 1;
00328                         }
00329                  else if (!strcmp(*args, "-signkey"))
00330                         {
00331                         if (args[1])
00332                                 {
00333                                 args++;
00334                                 keyfile = *args;
00335                                 }
00336                         else badarg = 1;
00337                         }
00338                 else if (!strcmp(*args, "-reqout"))
00339                         {
00340                         if (args[1])
00341                                 {
00342                                 args++;
00343                                 reqout = *args;
00344                                 }
00345                         else badarg = 1;
00346                         }
00347                 else if (!strcmp(*args, "-respout"))
00348                         {
00349                         if (args[1])
00350                                 {
00351                                 args++;
00352                                 respout = *args;
00353                                 }
00354                         else badarg = 1;
00355                         }
00356                  else if (!strcmp(*args, "-path"))
00357                         {
00358                         if (args[1])
00359                                 {
00360                                 args++;
00361                                 path = *args;
00362                                 }
00363                         else badarg = 1;
00364                         }
00365                 else if (!strcmp(*args, "-issuer"))
00366                         {
00367                         if (args[1])
00368                                 {
00369                                 args++;
00370                                 X509_free(issuer);
00371                                 issuer = load_cert(bio_err, *args, FORMAT_PEM,
00372                                         NULL, e, "issuer certificate");
00373                                 if(!issuer) goto end;
00374                                 }
00375                         else badarg = 1;
00376                         }
00377                 else if (!strcmp (*args, "-cert"))
00378                         {
00379                         if (args[1])
00380                                 {
00381                                 args++;
00382                                 X509_free(cert);
00383                                 cert = load_cert(bio_err, *args, FORMAT_PEM,
00384                                         NULL, e, "certificate");
00385                                 if(!cert) goto end;
00386                                 if(!add_ocsp_cert(&req, cert, issuer, ids))
00387                                         goto end;
00388                                 if(!sk_push(reqnames, *args))
00389                                         goto end;
00390                                 }
00391                         else badarg = 1;
00392                         }
00393                 else if (!strcmp(*args, "-serial"))
00394                         {
00395                         if (args[1])
00396                                 {
00397                                 args++;
00398                                 if(!add_ocsp_serial(&req, *args, issuer, ids))
00399                                         goto end;
00400                                 if(!sk_push(reqnames, *args))
00401                                         goto end;
00402                                 }
00403                         else badarg = 1;
00404                         }
00405                 else if (!strcmp(*args, "-index"))
00406                         {
00407                         if (args[1])
00408                                 {
00409                                 args++;
00410                                 ridx_filename = *args;
00411                                 }
00412                         else badarg = 1;
00413                         }
00414                 else if (!strcmp(*args, "-CA"))
00415                         {
00416                         if (args[1])
00417                                 {
00418                                 args++;
00419                                 rca_filename = *args;
00420                                 }
00421                         else badarg = 1;
00422                         }
00423                 else if (!strcmp (*args, "-nmin"))
00424                         {
00425                         if (args[1])
00426                                 {
00427                                 args++;
00428                                 nmin = atol(*args);
00429                                 if (nmin < 0)
00430                                         {
00431                                         BIO_printf(bio_err,
00432                                                 "Illegal update period %s\n",
00433                                                 *args);
00434                                         badarg = 1;
00435                                         }
00436                                 }
00437                                 if (ndays == -1)
00438                                         ndays = 0;
00439                         else badarg = 1;
00440                         }
00441                 else if (!strcmp (*args, "-nrequest"))
00442                         {
00443                         if (args[1])
00444                                 {
00445                                 args++;
00446                                 accept_count = atol(*args);
00447                                 if (accept_count < 0)
00448                                         {
00449                                         BIO_printf(bio_err,
00450                                                 "Illegal accept count %s\n",
00451                                                 *args);
00452                                         badarg = 1;
00453                                         }
00454                                 }
00455                         else badarg = 1;
00456                         }
00457                 else if (!strcmp (*args, "-ndays"))
00458                         {
00459                         if (args[1])
00460                                 {
00461                                 args++;
00462                                 ndays = atol(*args);
00463                                 if (ndays < 0)
00464                                         {
00465                                         BIO_printf(bio_err,
00466                                                 "Illegal update period %s\n",
00467                                                 *args);
00468                                         badarg = 1;
00469                                         }
00470                                 }
00471                         else badarg = 1;
00472                         }
00473                 else if (!strcmp(*args, "-rsigner"))
00474                         {
00475                         if (args[1])
00476                                 {
00477                                 args++;
00478                                 rsignfile = *args;
00479                                 }
00480                         else badarg = 1;
00481                         }
00482                 else if (!strcmp(*args, "-rkey"))
00483                         {
00484                         if (args[1])
00485                                 {
00486                                 args++;
00487                                 rkeyfile = *args;
00488                                 }
00489                         else badarg = 1;
00490                         }
00491                 else if (!strcmp(*args, "-rother"))
00492                         {
00493                         if (args[1])
00494                                 {
00495                                 args++;
00496                                 rcertfile = *args;
00497                                 }
00498                         else badarg = 1;
00499                         }
00500                 else badarg = 1;
00501                 args++;
00502                 }
00503 
00504         /* Have we anything to do? */
00505         if (!req && !reqin && !respin && !(port && ridx_filename)) badarg = 1;
00506 
00507         if (badarg)
00508                 {
00509                 BIO_printf (bio_err, "OCSP utility\n");
00510                 BIO_printf (bio_err, "Usage ocsp [options]\n");
00511                 BIO_printf (bio_err, "where options are\n");
00512                 BIO_printf (bio_err, "-out file          output filename\n");
00513                 BIO_printf (bio_err, "-issuer file       issuer certificate\n");
00514                 BIO_printf (bio_err, "-cert file         certificate to check\n");
00515                 BIO_printf (bio_err, "-serial n          serial number to check\n");
00516                 BIO_printf (bio_err, "-signer file       certificate to sign OCSP request with\n");
00517                 BIO_printf (bio_err, "-signkey file      private key to sign OCSP request with\n");
00518                 BIO_printf (bio_err, "-sign_other file   additional certificates to include in signed request\n");
00519                 BIO_printf (bio_err, "-no_certs          don't include any certificates in signed request\n");
00520                 BIO_printf (bio_err, "-req_text          print text form of request\n");
00521                 BIO_printf (bio_err, "-resp_text         print text form of response\n");
00522                 BIO_printf (bio_err, "-text              print text form of request and response\n");
00523                 BIO_printf (bio_err, "-reqout file       write DER encoded OCSP request to \"file\"\n");
00524                 BIO_printf (bio_err, "-respout file      write DER encoded OCSP reponse to \"file\"\n");
00525                 BIO_printf (bio_err, "-reqin file        read DER encoded OCSP request from \"file\"\n");
00526                 BIO_printf (bio_err, "-respin file       read DER encoded OCSP reponse from \"file\"\n");
00527                 BIO_printf (bio_err, "-nonce             add OCSP nonce to request\n");
00528                 BIO_printf (bio_err, "-no_nonce          don't add OCSP nonce to request\n");
00529                 BIO_printf (bio_err, "-url URL           OCSP responder URL\n");
00530                 BIO_printf (bio_err, "-host host:n       send OCSP request to host on port n\n");
00531                 BIO_printf (bio_err, "-path              path to use in OCSP request\n");
00532                 BIO_printf (bio_err, "-CApath dir        trusted certificates directory\n");
00533                 BIO_printf (bio_err, "-CAfile file       trusted certificates file\n");
00534                 BIO_printf (bio_err, "-VAfile file       validator certificates file\n");
00535                 BIO_printf (bio_err, "-validity_period n maximum validity discrepancy in seconds\n");
00536                 BIO_printf (bio_err, "-status_age n      maximum status age in seconds\n");
00537                 BIO_printf (bio_err, "-noverify          don't verify response at all\n");
00538                 BIO_printf (bio_err, "-verify_other file additional certificates to search for signer\n");
00539                 BIO_printf (bio_err, "-trust_other       don't verify additional certificates\n");
00540                 BIO_printf (bio_err, "-no_intern         don't search certificates contained in response for signer\n");
00541                 BIO_printf (bio_err, "-no_signature_verify don't check signature on response\n");
00542                 BIO_printf (bio_err, "-no_cert_verify    don't check signing certificate\n");
00543                 BIO_printf (bio_err, "-no_chain          don't chain verify response\n");
00544                 BIO_printf (bio_err, "-no_cert_checks    don't do additional checks on signing certificate\n");
00545                 BIO_printf (bio_err, "-port num          port to run responder on\n");
00546                 BIO_printf (bio_err, "-index file        certificate status index file\n");
00547                 BIO_printf (bio_err, "-CA file           CA certificate\n");
00548                 BIO_printf (bio_err, "-rsigner file      responder certificate to sign responses with\n");
00549                 BIO_printf (bio_err, "-rkey file         responder key to sign responses with\n");
00550                 BIO_printf (bio_err, "-rother file       other certificates to include in response\n");
00551                 BIO_printf (bio_err, "-resp_no_certs     don't include any certificates in response\n");
00552                 BIO_printf (bio_err, "-nmin n            number of minutes before next update\n");
00553                 BIO_printf (bio_err, "-ndays n           number of days before next update\n");
00554                 BIO_printf (bio_err, "-resp_key_id       identify reponse by signing certificate key ID\n");
00555                 BIO_printf (bio_err, "-nrequest n        number of requests to accept (default unlimited)\n");
00556                 goto end;
00557                 }
00558 
00559         if(outfile) out = BIO_new_file(outfile, "w");
00560         else out = BIO_new_fp(stdout, BIO_NOCLOSE);
00561 
00562         if(!out)
00563                 {
00564                 BIO_printf(bio_err, "Error opening output file\n");
00565                 goto end;
00566                 }
00567 
00568         if (!req && (add_nonce != 2)) add_nonce = 0;
00569 
00570         if (!req && reqin)
00571                 {
00572                 derbio = BIO_new_file(reqin, "rb");
00573                 if (!derbio)
00574                         {
00575                         BIO_printf(bio_err, "Error Opening OCSP request file\n");
00576                         goto end;
00577                         }
00578                 req = d2i_OCSP_REQUEST_bio(derbio, NULL);
00579                 BIO_free(derbio);
00580                 if(!req)
00581                         {
00582                         BIO_printf(bio_err, "Error reading OCSP request\n");
00583                         goto end;
00584                         }
00585                 }
00586 
00587         if (!req && port)
00588                 {
00589                 acbio = init_responder(port);
00590                 if (!acbio)
00591                         goto end;
00592                 }
00593 
00594         if (rsignfile && !rdb)
00595                 {
00596                 if (!rkeyfile) rkeyfile = rsignfile;
00597                 rsigner = load_cert(bio_err, rsignfile, FORMAT_PEM,
00598                         NULL, e, "responder certificate");
00599                 if (!rsigner)
00600                         {
00601                         BIO_printf(bio_err, "Error loading responder certificate\n");
00602                         goto end;
00603                         }
00604                 rca_cert = load_cert(bio_err, rca_filename, FORMAT_PEM,
00605                         NULL, e, "CA certificate");
00606                 if (rcertfile)
00607                         {
00608                         rother = load_certs(bio_err, rcertfile, FORMAT_PEM,
00609                                 NULL, e, "responder other certificates");
00610                         if (!rother) goto end;
00611                         }
00612                 rkey = load_key(bio_err, rkeyfile, FORMAT_PEM, 0, NULL, NULL,
00613                         "responder private key");
00614                 if (!rkey)
00615                         goto end;
00616                 }
00617         if(acbio)
00618                 BIO_printf(bio_err, "Waiting for OCSP client connections...\n");
00619 
00620         redo_accept:
00621 
00622         if (acbio)
00623                 {
00624                 if (!do_responder(&req, &cbio, acbio, port))
00625                         goto end;
00626                 if (!req)
00627                         {
00628                         resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL);
00629                         send_ocsp_response(cbio, resp);
00630                         goto done_resp;
00631                         }
00632                 }
00633 
00634         if (!req && (signfile || reqout || host || add_nonce || ridx_filename))
00635                 {
00636                 BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
00637                 goto end;
00638                 }
00639 
00640         if (req && add_nonce) OCSP_request_add1_nonce(req, NULL, -1);
00641 
00642         if (signfile)
00643                 {
00644                 if (!keyfile) keyfile = signfile;
00645                 signer = load_cert(bio_err, signfile, FORMAT_PEM,
00646                         NULL, e, "signer certificate");
00647                 if (!signer)
00648                         {
00649                         BIO_printf(bio_err, "Error loading signer certificate\n");
00650                         goto end;
00651                         }
00652                 if (sign_certfile)
00653                         {
00654                         sign_other = load_certs(bio_err, sign_certfile, FORMAT_PEM,
00655                                 NULL, e, "signer certificates");
00656                         if (!sign_other) goto end;
00657                         }
00658                 key = load_key(bio_err, keyfile, FORMAT_PEM, 0, NULL, NULL,
00659                         "signer private key");
00660                 if (!key)
00661                         goto end;
00662                 if (!OCSP_request_sign(req, signer, key, EVP_sha1(), sign_other, sign_flags))
00663                         {
00664                         BIO_printf(bio_err, "Error signing OCSP request\n");
00665                         goto end;
00666                         }
00667                 }
00668 
00669         if (req_text && req) OCSP_REQUEST_print(out, req, 0);
00670 
00671         if (reqout)
00672                 {
00673                 derbio = BIO_new_file(reqout, "wb");
00674                 if(!derbio)
00675                         {
00676                         BIO_printf(bio_err, "Error opening file %s\n", reqout);
00677                         goto end;
00678                         }
00679                 i2d_OCSP_REQUEST_bio(derbio, req);
00680                 BIO_free(derbio);
00681                 }
00682 
00683         if (ridx_filename && (!rkey || !rsigner || !rca_cert))
00684                 {
00685                 BIO_printf(bio_err, "Need a responder certificate, key and CA for this operation!\n");
00686                 goto end;
00687                 }
00688 
00689         if (ridx_filename && !rdb)
00690                 {
00691                 rdb = load_index(ridx_filename, NULL);
00692                 if (!rdb) goto end;
00693                 if (!index_index(rdb)) goto end;
00694                 }
00695 
00696         if (rdb)
00697                 {
00698                 i = make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey, rother, rflags, nmin, ndays);
00699                 if (cbio)
00700                         send_ocsp_response(cbio, resp);
00701                 }
00702         else if (host)
00703                 {
00704 #ifndef OPENSSL_NO_SOCK
00705                 cbio = BIO_new_connect(host);
00706 #else
00707                 BIO_printf(bio_err, "Error creating connect BIO - sockets not supported.\n");
00708                 goto end;
00709 #endif
00710                 if (!cbio)
00711                         {
00712                         BIO_printf(bio_err, "Error creating connect BIO\n");
00713                         goto end;
00714                         }
00715                 if (port) BIO_set_conn_port(cbio, port);
00716                 if (use_ssl == 1)
00717                         {
00718                         BIO *sbio;
00719 #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
00720                         ctx = SSL_CTX_new(SSLv23_client_method());
00721 #elif !defined(OPENSSL_NO_SSL3)
00722                         ctx = SSL_CTX_new(SSLv3_client_method());
00723 #elif !defined(OPENSSL_NO_SSL2)
00724                         ctx = SSL_CTX_new(SSLv2_client_method());
00725 #else
00726                         BIO_printf(bio_err, "SSL is disabled\n");
00727                         goto end;
00728 #endif
00729                         SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
00730                         sbio = BIO_new_ssl(ctx, 1);
00731                         cbio = BIO_push(sbio, cbio);
00732                         }
00733                 if (BIO_do_connect(cbio) <= 0)
00734                         {
00735                         BIO_printf(bio_err, "Error connecting BIO\n");
00736                         goto end;
00737                         }
00738                 resp = OCSP_sendreq_bio(cbio, path, req);
00739                 BIO_free_all(cbio);
00740                 cbio = NULL;
00741                 if (!resp)
00742                         {
00743                         BIO_printf(bio_err, "Error querying OCSP responsder\n");
00744                         goto end;
00745                         }
00746                 }
00747         else if (respin)
00748                 {
00749                 derbio = BIO_new_file(respin, "rb");
00750                 if (!derbio)
00751                         {
00752                         BIO_printf(bio_err, "Error Opening OCSP response file\n");
00753                         goto end;
00754                         }
00755                 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
00756                 BIO_free(derbio);
00757                 if(!resp)
00758                         {
00759                         BIO_printf(bio_err, "Error reading OCSP response\n");
00760                         goto end;
00761                         }
00762         
00763                 }
00764         else
00765                 {
00766                 ret = 0;
00767                 goto end;
00768                 }
00769 
00770         done_resp:
00771 
00772         if (respout)
00773                 {
00774                 derbio = BIO_new_file(respout, "wb");
00775                 if(!derbio)
00776                         {
00777                         BIO_printf(bio_err, "Error opening file %s\n", respout);
00778                         goto end;
00779                         }
00780                 i2d_OCSP_RESPONSE_bio(derbio, resp);
00781                 BIO_free(derbio);
00782                 }
00783 
00784         i = OCSP_response_status(resp);
00785 
00786         if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL)
00787                 {
00788                 BIO_printf(out, "Responder Error: %s (%d)\n",
00789                                 OCSP_response_status_str(i), i);
00790                 if (ignore_err)
00791                         goto redo_accept;
00792                 ret = 0;
00793                 goto end;
00794                 }
00795 
00796         if (resp_text) OCSP_RESPONSE_print(out, resp, 0);
00797 
00798         /* If running as responder don't verify our own response */
00799         if (cbio)
00800                 {
00801                 if (accept_count > 0)
00802                         accept_count--;
00803                 /* Redo if more connections needed */
00804                 if (accept_count)
00805                         {
00806                         BIO_free_all(cbio);
00807                         cbio = NULL;
00808                         OCSP_REQUEST_free(req);
00809                         req = NULL;
00810                         OCSP_RESPONSE_free(resp);
00811                         resp = NULL;
00812                         goto redo_accept;
00813                         }
00814                 goto end;
00815                 }
00816 
00817         if (!store)
00818                 store = setup_verify(bio_err, CAfile, CApath);
00819         if (!store)
00820                 goto end;
00821         if (verify_certfile)
00822                 {
00823                 verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM,
00824                         NULL, e, "validator certificate");
00825                 if (!verify_other) goto end;
00826                 }
00827 
00828         bs = OCSP_response_get1_basic(resp);
00829 
00830         if (!bs)
00831                 {
00832                 BIO_printf(bio_err, "Error parsing response\n");
00833                 goto end;
00834                 }
00835 
00836         if (!noverify)
00837                 {
00838                 if (req && ((i = OCSP_check_nonce(req, bs)) <= 0))
00839                         {
00840                         if (i == -1)
00841                                 BIO_printf(bio_err, "WARNING: no nonce in response\n");
00842                         else
00843                                 {
00844                                 BIO_printf(bio_err, "Nonce Verify error\n");
00845                                 goto end;
00846                                 }
00847                         }
00848 
00849                 i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
00850                 if (i < 0) i = OCSP_basic_verify(bs, NULL, store, 0);
00851 
00852                 if(i <= 0)
00853                         {
00854                         BIO_printf(bio_err, "Response Verify Failure\n");
00855                         ERR_print_errors(bio_err);
00856                         }
00857                 else
00858                         BIO_printf(bio_err, "Response verify OK\n");
00859 
00860                 }
00861 
00862         if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage))
00863                 goto end;
00864 
00865         ret = 0;
00866 
00867 end:
00868         ERR_print_errors(bio_err);
00869         X509_free(signer);
00870         X509_STORE_free(store);
00871         EVP_PKEY_free(key);
00872         EVP_PKEY_free(rkey);
00873         X509_free(issuer);
00874         X509_free(cert);
00875         X509_free(rsigner);
00876         X509_free(rca_cert);
00877         free_index(rdb);
00878         BIO_free_all(cbio);
00879         BIO_free_all(acbio);
00880         BIO_free(out);
00881         OCSP_REQUEST_free(req);
00882         OCSP_RESPONSE_free(resp);
00883         OCSP_BASICRESP_free(bs);
00884         sk_free(reqnames);
00885         sk_OCSP_CERTID_free(ids);
00886         sk_X509_pop_free(sign_other, X509_free);
00887         sk_X509_pop_free(verify_other, X509_free);
00888 
00889         if (use_ssl != -1)
00890                 {
00891                 OPENSSL_free(host);
00892                 OPENSSL_free(port);
00893                 OPENSSL_free(path);
00894                 SSL_CTX_free(ctx);
00895                 }
00896 
00897         OPENSSL_EXIT(ret);
00898 }
00899 
00900 static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
00901                                 STACK_OF(OCSP_CERTID) *ids)
00902         {
00903         OCSP_CERTID *id;
00904         if(!issuer)
00905                 {
00906                 BIO_printf(bio_err, "No issuer certificate specified\n");
00907                 return 0;
00908                 }
00909         if(!*req) *req = OCSP_REQUEST_new();
00910         if(!*req) goto err;
00911         id = OCSP_cert_to_id(NULL, cert, issuer);
00912         if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
00913         if(!OCSP_request_add0_id(*req, id)) goto err;
00914         return 1;
00915 
00916         err:
00917         BIO_printf(bio_err, "Error Creating OCSP request\n");
00918         return 0;
00919         }
00920 
00921 static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer,
00922                                 STACK_OF(OCSP_CERTID) *ids)
00923         {
00924         OCSP_CERTID *id;
00925         X509_NAME *iname;
00926         ASN1_BIT_STRING *ikey;
00927         ASN1_INTEGER *sno;
00928         if(!issuer)
00929                 {
00930                 BIO_printf(bio_err, "No issuer certificate specified\n");
00931                 return 0;
00932                 }
00933         if(!*req) *req = OCSP_REQUEST_new();
00934         if(!*req) goto err;
00935         iname = X509_get_subject_name(issuer);
00936         ikey = X509_get0_pubkey_bitstr(issuer);
00937         sno = s2i_ASN1_INTEGER(NULL, serial);
00938         if(!sno)
00939                 {
00940                 BIO_printf(bio_err, "Error converting serial number %s\n", serial);
00941                 return 0;
00942                 }
00943         id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno);
00944         ASN1_INTEGER_free(sno);
00945         if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
00946         if(!OCSP_request_add0_id(*req, id)) goto err;
00947         return 1;
00948 
00949         err:
00950         BIO_printf(bio_err, "Error Creating OCSP request\n");
00951         return 0;
00952         }
00953 
00954 static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
00955                                         STACK *names, STACK_OF(OCSP_CERTID) *ids,
00956                                         long nsec, long maxage)
00957         {
00958         OCSP_CERTID *id;
00959         char *name;
00960         int i;
00961 
00962         int status, reason;
00963 
00964         ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
00965 
00966         if (!bs || !req || !sk_num(names) || !sk_OCSP_CERTID_num(ids))
00967                 return 1;
00968 
00969         for (i = 0; i < sk_OCSP_CERTID_num(ids); i++)
00970                 {
00971                 id = sk_OCSP_CERTID_value(ids, i);
00972                 name = sk_value(names, i);
00973                 BIO_printf(out, "%s: ", name);
00974 
00975                 if(!OCSP_resp_find_status(bs, id, &status, &reason,
00976                                         &rev, &thisupd, &nextupd))
00977                         {
00978                         BIO_puts(out, "ERROR: No Status found.\n");
00979                         continue;
00980                         }
00981 
00982                 /* Check validity: if invalid write to output BIO so we
00983                  * know which response this refers to.
00984                  */
00985                 if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage))
00986                         {
00987                         BIO_puts(out, "WARNING: Status times invalid.\n");
00988                         ERR_print_errors(out);
00989                         }
00990                 BIO_printf(out, "%s\n", OCSP_cert_status_str(status));
00991 
00992                 BIO_puts(out, "\tThis Update: ");
00993                 ASN1_GENERALIZEDTIME_print(out, thisupd);
00994                 BIO_puts(out, "\n");
00995 
00996                 if(nextupd)
00997                         {
00998                         BIO_puts(out, "\tNext Update: ");
00999                         ASN1_GENERALIZEDTIME_print(out, nextupd);
01000                         BIO_puts(out, "\n");
01001                         }
01002 
01003                 if (status != V_OCSP_CERTSTATUS_REVOKED)
01004                         continue;
01005 
01006                 if (reason != -1)
01007                         BIO_printf(out, "\tReason: %s\n",
01008                                 OCSP_crl_reason_str(reason));
01009 
01010                 BIO_puts(out, "\tRevocation Time: ");
01011                 ASN1_GENERALIZEDTIME_print(out, rev);
01012                 BIO_puts(out, "\n");
01013                 }
01014 
01015         return 1;
01016         }
01017 
01018 
01019 static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, CA_DB *db,
01020                         X509 *ca, X509 *rcert, EVP_PKEY *rkey,
01021                         STACK_OF(X509) *rother, unsigned long flags,
01022                         int nmin, int ndays)
01023         {
01024         ASN1_TIME *thisupd = NULL, *nextupd = NULL;
01025         OCSP_CERTID *cid, *ca_id = NULL;
01026         OCSP_BASICRESP *bs = NULL;
01027         int i, id_count, ret = 1;
01028 
01029 
01030         id_count = OCSP_request_onereq_count(req);
01031 
01032         if (id_count <= 0)
01033                 {
01034                 *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL);
01035                 goto end;
01036                 }
01037 
01038         ca_id = OCSP_cert_to_id(EVP_sha1(), NULL, ca);
01039 
01040         bs = OCSP_BASICRESP_new();
01041         thisupd = X509_gmtime_adj(NULL, 0);
01042         if (ndays != -1)
01043                 nextupd = X509_gmtime_adj(NULL, nmin * 60 + ndays * 3600 * 24 );
01044 
01045         /* Examine each certificate id in the request */
01046         for (i = 0; i < id_count; i++)
01047                 {
01048                 OCSP_ONEREQ *one;
01049                 ASN1_INTEGER *serial;
01050                 char **inf;
01051                 one = OCSP_request_onereq_get0(req, i);
01052                 cid = OCSP_onereq_get0_id(one);
01053                 /* Is this request about our CA? */
01054                 if (OCSP_id_issuer_cmp(ca_id, cid))
01055                         {
01056                         OCSP_basic_add1_status(bs, cid,
01057                                                 V_OCSP_CERTSTATUS_UNKNOWN,
01058                                                 0, NULL,
01059                                                 thisupd, nextupd);
01060                         continue;
01061                         }
01062                 OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid);
01063                 inf = lookup_serial(db, serial);
01064                 if (!inf)
01065                         OCSP_basic_add1_status(bs, cid,
01066                                                 V_OCSP_CERTSTATUS_UNKNOWN,
01067                                                 0, NULL,
01068                                                 thisupd, nextupd);
01069                 else if (inf[DB_type][0] == DB_TYPE_VAL)
01070                         OCSP_basic_add1_status(bs, cid,
01071                                                 V_OCSP_CERTSTATUS_GOOD,
01072                                                 0, NULL,
01073                                                 thisupd, nextupd);
01074                 else if (inf[DB_type][0] == DB_TYPE_REV)
01075                         {
01076                         ASN1_OBJECT *inst = NULL;
01077                         ASN1_TIME *revtm = NULL;
01078                         ASN1_GENERALIZEDTIME *invtm = NULL;
01079                         OCSP_SINGLERESP *single;
01080                         int reason = -1;
01081                         unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]);
01082                         single = OCSP_basic_add1_status(bs, cid,
01083                                                 V_OCSP_CERTSTATUS_REVOKED,
01084                                                 reason, revtm,
01085                                                 thisupd, nextupd);
01086                         if (invtm)
01087                                 OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date, invtm, 0, 0);
01088                         else if (inst)
01089                                 OCSP_SINGLERESP_add1_ext_i2d(single, NID_hold_instruction_code, inst, 0, 0);
01090                         ASN1_OBJECT_free(inst);
01091                         ASN1_TIME_free(revtm);
01092                         ASN1_GENERALIZEDTIME_free(invtm);
01093                         }
01094                 }
01095 
01096         OCSP_copy_nonce(bs, req);
01097                 
01098         OCSP_basic_sign(bs, rcert, rkey, EVP_sha1(), rother, flags);
01099 
01100         *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs);
01101 
01102         end:
01103         ASN1_TIME_free(thisupd);
01104         ASN1_TIME_free(nextupd);
01105         OCSP_CERTID_free(ca_id);
01106         OCSP_BASICRESP_free(bs);
01107         return ret;
01108 
01109         }
01110 
01111 static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
01112         {
01113         int i;
01114         BIGNUM *bn = NULL;
01115         char *itmp, *row[DB_NUMBER],**rrow;
01116         for (i = 0; i < DB_NUMBER; i++) row[i] = NULL;
01117         bn = ASN1_INTEGER_to_BN(ser,NULL);
01118         if (BN_is_zero(bn))
01119                 itmp = BUF_strdup("00");
01120         else
01121                 itmp = BN_bn2hex(bn);
01122         row[DB_serial] = itmp;
01123         BN_free(bn);
01124         rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
01125         OPENSSL_free(itmp);
01126         return rrow;
01127         }
01128 
01129 /* Quick and dirty OCSP server: read in and parse input request */
01130 
01131 static BIO *init_responder(char *port)
01132         {
01133         BIO *acbio = NULL, *bufbio = NULL;
01134         bufbio = BIO_new(BIO_f_buffer());
01135         if (!bufbio) 
01136                 goto err;
01137 #ifndef OPENSSL_NO_SOCK
01138         acbio = BIO_new_accept(port);
01139 #else
01140         BIO_printf(bio_err, "Error setting up accept BIO - sockets not supported.\n");
01141 #endif
01142         if (!acbio)
01143                 goto err;
01144         BIO_set_accept_bios(acbio, bufbio);
01145         bufbio = NULL;
01146 
01147         if (BIO_do_accept(acbio) <= 0)
01148                 {
01149                         BIO_printf(bio_err, "Error setting up accept BIO\n");
01150                         ERR_print_errors(bio_err);
01151                         goto err;
01152                 }
01153 
01154         return acbio;
01155 
01156         err:
01157         BIO_free_all(acbio);
01158         BIO_free(bufbio);
01159         return NULL