LCOV - code coverage report
Current view: top level - dirmngr - ocsp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 378 0.0 %
Date: 2015-11-05 17:10:59 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /* ocsp.c - OCSP management
       2             :  *      Copyright (C) 2004, 2007 g10 Code GmbH
       3             :  *
       4             :  * This file is part of DirMngr.
       5             :  *
       6             :  * DirMngr is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 2 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * DirMngr is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program; if not, write to the Free Software
      18             :  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <errno.h>
      25             : #include <assert.h>
      26             : 
      27             : #include "dirmngr.h"
      28             : #include "misc.h"
      29             : #include "http.h"
      30             : #include "validate.h"
      31             : #include "certcache.h"
      32             : #include "ocsp.h"
      33             : 
      34             : /* The maximum size we allow as a response from an OCSP reponder. */
      35             : #define MAX_RESPONSE_SIZE 65536
      36             : 
      37             : 
      38             : static const char oidstr_ocsp[] = "1.3.6.1.5.5.7.48.1";
      39             : 
      40             : 
      41             : /* Telesec attribute used to implement a positive confirmation.
      42             : 
      43             :    CertHash ::= SEQUENCE {
      44             :       HashAlgorithm    AlgorithmIdentifier,
      45             :       certificateHash OCTET STRING }
      46             :  */
      47             : static const char oidstr_certHash[] = "1.3.36.8.3.13";
      48             : 
      49             : 
      50             : 
      51             : 
      52             : /* Read from FP and return a newly allocated buffer in R_BUFFER with the
      53             :    entire data read from FP. */
      54             : static gpg_error_t
      55           0 : read_response (estream_t fp, unsigned char **r_buffer, size_t *r_buflen)
      56             : {
      57             :   gpg_error_t err;
      58             :   unsigned char *buffer;
      59             :   size_t bufsize, nbytes;
      60             : 
      61           0 :   *r_buffer = NULL;
      62           0 :   *r_buflen = 0;
      63             : 
      64           0 :   bufsize = 4096;
      65           0 :   buffer = xtrymalloc (bufsize);
      66           0 :   if (!buffer)
      67           0 :     return gpg_error_from_errno (errno);
      68             : 
      69           0 :   nbytes = 0;
      70             :   for (;;)
      71             :     {
      72             :       unsigned char *tmp;
      73           0 :       size_t nread = 0;
      74             : 
      75           0 :       assert (nbytes < bufsize);
      76           0 :       nread = es_fread (buffer+nbytes, 1, bufsize-nbytes, fp);
      77           0 :       if (nread < bufsize-nbytes && es_ferror (fp))
      78             :         {
      79           0 :           err = gpg_error_from_errno (errno);
      80           0 :           log_error (_("error reading from responder: %s\n"),
      81           0 :                      strerror (errno));
      82           0 :           xfree (buffer);
      83           0 :           return err;
      84             :         }
      85           0 :       if ( !(nread == bufsize-nbytes && !es_feof (fp)))
      86             :         { /* Response succesfully received. */
      87           0 :           nbytes += nread;
      88           0 :           *r_buffer = buffer;
      89           0 :           *r_buflen = nbytes;
      90           0 :           return 0;
      91             :         }
      92             : 
      93           0 :       nbytes += nread;
      94             : 
      95             :       /* Need to enlarge the buffer. */
      96           0 :       if (bufsize >= MAX_RESPONSE_SIZE)
      97             :         {
      98           0 :           log_error (_("response from server too large; limit is %d bytes\n"),
      99             :                      MAX_RESPONSE_SIZE);
     100           0 :           xfree (buffer);
     101           0 :           return gpg_error (GPG_ERR_TOO_LARGE);
     102             :         }
     103             : 
     104           0 :       bufsize += 4096;
     105           0 :       tmp = xtryrealloc (buffer, bufsize);
     106           0 :       if (!tmp)
     107             :         {
     108           0 :           err = gpg_error_from_errno (errno);
     109           0 :           xfree (buffer);
     110           0 :           return err;
     111             :         }
     112           0 :       buffer = tmp;
     113           0 :     }
     114             : }
     115             : 
     116             : 
     117             : /* Construct an OCSP request, send it to the configured OCSP responder
     118             :    and parse the response. On success the OCSP context may be used to
     119             :    further process the reponse. */
     120             : static gpg_error_t
     121           0 : do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md,
     122             :                  const char *url, ksba_cert_t cert, ksba_cert_t issuer_cert)
     123             : {
     124             :   gpg_error_t err;
     125             :   unsigned char *request, *response;
     126             :   size_t requestlen, responselen;
     127             :   http_t http;
     128             :   ksba_ocsp_response_status_t response_status;
     129             :   const char *t;
     130           0 :   int redirects_left = 2;
     131           0 :   char *free_this = NULL;
     132             : 
     133             :   (void)ctrl;
     134             : 
     135           0 :   if (opt.use_tor)
     136             :     {
     137             :       /* For now we do not allow OCSP via Tor due to possible privacy
     138             :          concerns.  Needs further research.  */
     139           0 :       log_error (_("OCSP request not possible due to Tor mode\n"));
     140           0 :       return gpg_error (GPG_ERR_NOT_SUPPORTED);
     141             :     }
     142             : 
     143           0 :   if (opt.disable_http)
     144             :     {
     145           0 :       log_error (_("OCSP request not possible due to disabled HTTP\n"));
     146           0 :       return gpg_error (GPG_ERR_NOT_SUPPORTED);
     147             :     }
     148             : 
     149           0 :   err = ksba_ocsp_add_target (ocsp, cert, issuer_cert);
     150           0 :   if (err)
     151             :     {
     152           0 :       log_error (_("error setting OCSP target: %s\n"), gpg_strerror (err));
     153           0 :       return err;
     154             :     }
     155             : 
     156             :   {
     157             :     size_t n;
     158             :     unsigned char nonce[32];
     159             : 
     160           0 :     n = ksba_ocsp_set_nonce (ocsp, NULL, 0);
     161           0 :     if (n > sizeof nonce)
     162           0 :       n = sizeof nonce;
     163           0 :     gcry_create_nonce (nonce, n);
     164           0 :     ksba_ocsp_set_nonce (ocsp, nonce, n);
     165             :   }
     166             : 
     167           0 :   err = ksba_ocsp_build_request (ocsp, &request, &requestlen);
     168           0 :   if (err)
     169             :     {
     170           0 :       log_error (_("error building OCSP request: %s\n"), gpg_strerror (err));
     171           0 :       return err;
     172             :     }
     173             : 
     174             :  once_more:
     175           0 :   err = http_open (&http, HTTP_REQ_POST, url, NULL, NULL,
     176           0 :                    ((opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
     177           0 :                     | (opt.use_tor? HTTP_FLAG_FORCE_TOR:0)),
     178           0 :                    ctrl->http_proxy, NULL, NULL, NULL);
     179           0 :   if (err)
     180             :     {
     181           0 :       log_error (_("error connecting to '%s': %s\n"), url, gpg_strerror (err));
     182           0 :       xfree (free_this);
     183           0 :       return err;
     184             :     }
     185             : 
     186           0 :   es_fprintf (http_get_write_ptr (http),
     187             :               "Content-Type: application/ocsp-request\r\n"
     188             :               "Content-Length: %lu\r\n",
     189             :               (unsigned long)requestlen );
     190           0 :   http_start_data (http);
     191           0 :   if (es_fwrite (request, requestlen, 1, http_get_write_ptr (http)) != 1)
     192             :     {
     193           0 :       err = gpg_error_from_errno (errno);
     194           0 :       log_error ("error sending request to '%s': %s\n", url, strerror (errno));
     195           0 :       http_close (http, 0);
     196           0 :       xfree (request);
     197           0 :       xfree (free_this);
     198           0 :       return err;
     199             :     }
     200           0 :   xfree (request);
     201           0 :   request = NULL;
     202             : 
     203           0 :   err = http_wait_response (http);
     204           0 :   if (err || http_get_status_code (http) != 200)
     205             :     {
     206           0 :       if (err)
     207           0 :         log_error (_("error reading HTTP response for '%s': %s\n"),
     208             :                    url, gpg_strerror (err));
     209             :       else
     210             :         {
     211           0 :           switch (http_get_status_code (http))
     212             :             {
     213             :             case 301:
     214             :             case 302:
     215             :               {
     216           0 :                 const char *s = http_get_header (http, "Location");
     217             : 
     218           0 :                 log_info (_("URL '%s' redirected to '%s' (%u)\n"),
     219             :                           url, s?s:"[none]", http_get_status_code (http));
     220           0 :                 if (s && *s && redirects_left-- )
     221             :                   {
     222           0 :                     xfree (free_this); url = NULL;
     223           0 :                     free_this = xtrystrdup (s);
     224           0 :                     if (!free_this)
     225           0 :                       err = gpg_error_from_errno (errno);
     226             :                     else
     227             :                       {
     228           0 :                         url = free_this;
     229           0 :                         http_close (http, 0);
     230           0 :                         goto once_more;
     231             :                       }
     232             :                   }
     233             :                 else
     234           0 :                   err = gpg_error (GPG_ERR_NO_DATA);
     235           0 :                 log_error (_("too many redirections\n"));
     236             :               }
     237           0 :               break;
     238             : 
     239             :             default:
     240           0 :               log_error (_("error accessing '%s': http status %u\n"),
     241             :                          url, http_get_status_code (http));
     242           0 :               err = gpg_error (GPG_ERR_NO_DATA);
     243           0 :               break;
     244             :             }
     245             :         }
     246           0 :       http_close (http, 0);
     247           0 :       xfree (free_this);
     248           0 :       return err;
     249             :     }
     250             : 
     251           0 :   err = read_response (http_get_read_ptr (http), &response, &responselen);
     252           0 :   http_close (http, 0);
     253           0 :   if (err)
     254             :     {
     255           0 :       log_error (_("error reading HTTP response for '%s': %s\n"),
     256             :                  url, gpg_strerror (err));
     257           0 :       xfree (free_this);
     258           0 :       return err;
     259             :     }
     260             : 
     261           0 :   err = ksba_ocsp_parse_response (ocsp, response, responselen,
     262             :                                   &response_status);
     263           0 :   if (err)
     264             :     {
     265           0 :       log_error (_("error parsing OCSP response for '%s': %s\n"),
     266             :                  url, gpg_strerror (err));
     267           0 :       xfree (response);
     268           0 :       xfree (free_this);
     269           0 :       return err;
     270             :     }
     271             : 
     272           0 :   switch (response_status)
     273             :     {
     274           0 :     case KSBA_OCSP_RSPSTATUS_SUCCESS:      t = "success"; break;
     275           0 :     case KSBA_OCSP_RSPSTATUS_MALFORMED:    t = "malformed"; break;
     276           0 :     case KSBA_OCSP_RSPSTATUS_INTERNAL:     t = "internal error"; break;
     277           0 :     case KSBA_OCSP_RSPSTATUS_TRYLATER:     t = "try later"; break;
     278           0 :     case KSBA_OCSP_RSPSTATUS_SIGREQUIRED:  t = "must sign request"; break;
     279           0 :     case KSBA_OCSP_RSPSTATUS_UNAUTHORIZED: t = "unauthorized"; break;
     280           0 :     case KSBA_OCSP_RSPSTATUS_REPLAYED:     t = "replay detected"; break;
     281           0 :     case KSBA_OCSP_RSPSTATUS_OTHER:        t = "other (unknown)"; break;
     282           0 :     case KSBA_OCSP_RSPSTATUS_NONE:         t = "no status"; break;
     283           0 :     default:                               t = "[unknown status]"; break;
     284             :     }
     285           0 :   if (response_status == KSBA_OCSP_RSPSTATUS_SUCCESS)
     286             :     {
     287           0 :       if (opt.verbose)
     288           0 :         log_info (_("OCSP responder at '%s' status: %s\n"), url, t);
     289             : 
     290           0 :       err = ksba_ocsp_hash_response (ocsp, response, responselen,
     291             :                                      HASH_FNC, md);
     292           0 :       if (err)
     293           0 :         log_error (_("hashing the OCSP response for '%s' failed: %s\n"),
     294             :                    url, gpg_strerror (err));
     295             :     }
     296             :   else
     297             :     {
     298           0 :       log_error (_("OCSP responder at '%s' status: %s\n"), url, t);
     299           0 :       err = gpg_error (GPG_ERR_GENERAL);
     300             :     }
     301             : 
     302           0 :   xfree (response);
     303           0 :   xfree (free_this);
     304           0 :   return err;
     305             : }
     306             : 
     307             : 
     308             : /* Validate that CERT is indeed valid to sign an OCSP response. If
     309             :    SIGNER_FPR_LIST is not NULL we simply check that CERT matches one
     310             :    of the fingerprints in this list. */
     311             : static gpg_error_t
     312           0 : validate_responder_cert (ctrl_t ctrl, ksba_cert_t cert,
     313             :                          fingerprint_list_t signer_fpr_list)
     314             : {
     315             :   gpg_error_t err;
     316             :   char *fpr;
     317             : 
     318           0 :   if (signer_fpr_list)
     319             :     {
     320           0 :       fpr = get_fingerprint_hexstring (cert);
     321           0 :       for (; signer_fpr_list && strcmp (signer_fpr_list->hexfpr, fpr);
     322           0 :            signer_fpr_list = signer_fpr_list->next)
     323             :         ;
     324           0 :       if (signer_fpr_list)
     325           0 :         err = 0;
     326             :       else
     327             :         {
     328           0 :           log_error (_("not signed by a default OCSP signer's certificate"));
     329           0 :           err = gpg_error (GPG_ERR_BAD_CA_CERT);
     330             :         }
     331           0 :       xfree (fpr);
     332             :     }
     333           0 :   else if (opt.system_daemon)
     334             :     {
     335           0 :       err = validate_cert_chain (ctrl, cert, NULL, VALIDATE_MODE_OCSP, NULL);
     336             :     }
     337             :   else
     338             :     {
     339             :       /* We avoid duplicating the entire certificate validation code
     340             :          from gpgsm here.  Because we have no way calling back to the
     341             :          client and letting it compute the validity, we use the ugly
     342             :          hack of telling the client that the response will only be
     343             :          valid if the certificate given in this status message is
     344             :          valid.
     345             : 
     346             :          Note, that in theory we could simply ask the client via an
     347             :          inquire to validate a certificate but this might involve
     348             :          calling DirMngr again recursivly - we can't do that as of now
     349             :          (neither DirMngr nor gpgsm have the ability for concurrent
     350             :          access to DirMngr.   */
     351             : 
     352             :       /* FIXME: We should cache this certificate locally, so that the next
     353             :          call to dirmngr won't need to look it up - if this works at
     354             :          all. */
     355           0 :       fpr = get_fingerprint_hexstring (cert);
     356           0 :       dirmngr_status (ctrl, "ONLY_VALID_IF_CERT_VALID", fpr, NULL);
     357           0 :       xfree (fpr);
     358           0 :       err = 0;
     359             :     }
     360             : 
     361           0 :   return err;
     362             : }
     363             : 
     364             : 
     365             : /* Helper for check_signature. */
     366             : static int
     367           0 : check_signature_core (ctrl_t ctrl, ksba_cert_t cert, gcry_sexp_t s_sig,
     368             :                       gcry_sexp_t s_hash, fingerprint_list_t signer_fpr_list)
     369             : {
     370             :   gpg_error_t err;
     371             :   ksba_sexp_t pubkey;
     372           0 :   gcry_sexp_t s_pkey = NULL;
     373             : 
     374           0 :   pubkey = ksba_cert_get_public_key (cert);
     375           0 :   if (!pubkey)
     376           0 :     err = gpg_error (GPG_ERR_INV_OBJ);
     377             :   else
     378           0 :     err = canon_sexp_to_gcry (pubkey, &s_pkey);
     379           0 :   xfree (pubkey);
     380           0 :   if (!err)
     381           0 :     err = gcry_pk_verify (s_sig, s_hash, s_pkey);
     382           0 :   if (!err)
     383           0 :     err = validate_responder_cert (ctrl, cert, signer_fpr_list);
     384           0 :   if (!err)
     385             :     {
     386           0 :       gcry_sexp_release (s_pkey);
     387           0 :       return 0; /* Successfully verified the signature. */
     388             :     }
     389             : 
     390             :   /* We simply ignore all errors. */
     391           0 :   gcry_sexp_release (s_pkey);
     392           0 :   return -1;
     393             : }
     394             : 
     395             : 
     396             : /* Check the signature of an OCSP repsonse.  OCSP is the context,
     397             :    S_SIG the signature value and MD the handle of the hash we used for
     398             :    the response.  This function automagically finds the correct public
     399             :    key.  If SIGNER_FPR_LIST is not NULL, the default OCSP reponder has been
     400             :    used and thus the certificate is one of those identified by
     401             :    the fingerprints. */
     402             : static gpg_error_t
     403           0 : check_signature (ctrl_t ctrl,
     404             :                  ksba_ocsp_t ocsp, gcry_sexp_t s_sig, gcry_md_hd_t md,
     405             :                  fingerprint_list_t signer_fpr_list)
     406             : {
     407             :   gpg_error_t err;
     408             :   int algo, cert_idx;
     409             :   gcry_sexp_t s_hash;
     410             :   ksba_cert_t cert;
     411             : 
     412             :   /* Create a suitable S-expression with the hash value of our response. */
     413           0 :   gcry_md_final (md);
     414           0 :   algo = gcry_md_get_algo (md);
     415           0 :   if (algo != GCRY_MD_SHA1 )
     416             :     {
     417           0 :       log_error (_("only SHA-1 is supported for OCSP responses\n"));
     418           0 :       return gpg_error (GPG_ERR_DIGEST_ALGO);
     419             :     }
     420           0 :   err = gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash sha1 %b))",
     421             :                          gcry_md_get_algo_dlen (algo),
     422             :                          gcry_md_read (md, algo));
     423           0 :   if (err)
     424             :     {
     425           0 :       log_error (_("creating S-expression failed: %s\n"), gcry_strerror (err));
     426           0 :       return err;
     427             :     }
     428             : 
     429             :   /* Get rid of old OCSP specific certificate references. */
     430           0 :   release_ctrl_ocsp_certs (ctrl);
     431             : 
     432           0 :   if (signer_fpr_list && !signer_fpr_list->next)
     433             :     {
     434             :       /* There is exactly one signer fingerprint given. Thus we use
     435             :          the default OCSP responder's certificate and instantly know
     436             :          the certificate to use.  */
     437           0 :       cert = get_cert_byhexfpr (signer_fpr_list->hexfpr);
     438           0 :       if (!cert)
     439           0 :         cert = get_cert_local (ctrl, signer_fpr_list->hexfpr);
     440           0 :       if (cert)
     441             :         {
     442           0 :           err = check_signature_core (ctrl, cert, s_sig, s_hash,
     443             :                                       signer_fpr_list);
     444           0 :           ksba_cert_release (cert);
     445           0 :           cert = NULL;
     446           0 :           if (!err)
     447             :             {
     448           0 :               gcry_sexp_release (s_hash);
     449           0 :               return 0; /* Successfully verified the signature. */
     450             :             }
     451             :         }
     452             :     }
     453             :   else
     454             :     {
     455             :       char *name;
     456             :       ksba_sexp_t keyid;
     457             : 
     458             :       /* Put all certificates included in the response into the cache
     459             :          and setup a list of those certificate which will later be
     460             :          preferred used when locating certificates.  */
     461           0 :       for (cert_idx=0; (cert = ksba_ocsp_get_cert (ocsp, cert_idx));
     462           0 :            cert_idx++)
     463             :         {
     464             :           cert_ref_t cref;
     465             : 
     466           0 :           cref = xtrymalloc (sizeof *cref);
     467           0 :           if (!cref)
     468           0 :             log_error (_("allocating list item failed: %s\n"),
     469             :                        gcry_strerror (err));
     470           0 :           else if (!cache_cert_silent (cert, &cref->fpr))
     471             :             {
     472           0 :               cref->next = ctrl->ocsp_certs;
     473           0 :               ctrl->ocsp_certs = cref;
     474             :             }
     475             :           else
     476           0 :             xfree (cref);
     477             :         }
     478             : 
     479             :       /* Get the certificate by means of the responder ID. */
     480           0 :       err = ksba_ocsp_get_responder_id (ocsp, &name, &keyid);
     481           0 :       if (err)
     482             :         {
     483           0 :           log_error (_("error getting responder ID: %s\n"),
     484             :                      gcry_strerror (err));
     485           0 :           return err;
     486             :         }
     487           0 :       cert = find_cert_bysubject (ctrl, name, keyid);
     488           0 :       if (!cert)
     489             :         {
     490           0 :           log_error ("responder certificate ");
     491           0 :           if (name)
     492           0 :             log_printf ("'/%s' ", name);
     493           0 :           if (keyid)
     494             :             {
     495           0 :               log_printf ("{");
     496           0 :               dump_serial (keyid);
     497           0 :               log_printf ("} ");
     498             :             }
     499           0 :           log_printf ("not found\n");
     500             :         }
     501           0 :       ksba_free (name);
     502           0 :       ksba_free (keyid);
     503             : 
     504           0 :       if (cert)
     505             :         {
     506           0 :           err = check_signature_core (ctrl, cert, s_sig, s_hash,
     507             :                                       signer_fpr_list);
     508           0 :           ksba_cert_release (cert);
     509           0 :           if (!err)
     510             :             {
     511           0 :               gcry_sexp_release (s_hash);
     512           0 :               return 0; /* Successfully verified the signature. */
     513             :             }
     514             :         }
     515             :     }
     516             : 
     517           0 :   gcry_sexp_release (s_hash);
     518           0 :   log_error (_("no suitable certificate found to verify the OCSP response\n"));
     519           0 :   return gpg_error (GPG_ERR_NO_PUBKEY);
     520             : }
     521             : 
     522             : 
     523             : /* Check whether the certificate either given by fingerprint CERT_FPR
     524             :    or directly through the CERT object is valid by running an OCSP
     525             :    transaction.  With FORCE_DEFAULT_RESPONDER set only the configured
     526             :    default responder is used. */
     527             : gpg_error_t
     528           0 : ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
     529             :               int force_default_responder)
     530             : {
     531             :   gpg_error_t err;
     532           0 :   ksba_ocsp_t ocsp = NULL;
     533           0 :   ksba_cert_t issuer_cert = NULL;
     534           0 :   ksba_sexp_t sigval = NULL;
     535           0 :   gcry_sexp_t s_sig = NULL;
     536             :   ksba_isotime_t current_time;
     537             :   ksba_isotime_t this_update, next_update, revocation_time, produced_at;
     538             :   ksba_isotime_t tmp_time;
     539             :   ksba_status_t status;
     540             :   ksba_crl_reason_t reason;
     541           0 :   char *url_buffer = NULL;
     542             :   const char *url;
     543           0 :   gcry_md_hd_t md = NULL;
     544             :   int i, idx;
     545             :   char *oid;
     546             :   ksba_name_t name;
     547           0 :   fingerprint_list_t default_signer = NULL;
     548             : 
     549             :   /* Get the certificate.  */
     550           0 :   if (cert)
     551             :     {
     552           0 :       ksba_cert_ref (cert);
     553             : 
     554           0 :       err = find_issuing_cert (ctrl, cert, &issuer_cert);
     555           0 :       if (err)
     556             :         {
     557           0 :           log_error (_("issuer certificate not found: %s\n"),
     558             :                      gpg_strerror (err));
     559           0 :           goto leave;
     560             :         }
     561             :     }
     562             :   else
     563             :     {
     564           0 :       cert = get_cert_local (ctrl, cert_fpr);
     565           0 :       if (!cert)
     566             :         {
     567           0 :           log_error (_("caller did not return the target certificate\n"));
     568           0 :           err = gpg_error (GPG_ERR_GENERAL);
     569           0 :           goto leave;
     570             :         }
     571           0 :       issuer_cert = get_issuing_cert_local (ctrl, NULL);
     572           0 :       if (!issuer_cert)
     573             :         {
     574           0 :           log_error (_("caller did not return the issuing certificate\n"));
     575           0 :           err = gpg_error (GPG_ERR_GENERAL);
     576           0 :           goto leave;
     577             :         }
     578             :     }
     579             : 
     580             :   /* Create an OCSP instance.  */
     581           0 :   err = ksba_ocsp_new (&ocsp);
     582           0 :   if (err)
     583             :     {
     584           0 :       log_error (_("failed to allocate OCSP context: %s\n"),
     585             :                  gpg_strerror (err));
     586           0 :       goto leave;
     587             :     }
     588             : 
     589             : 
     590             : 
     591             :   /* Figure out the OCSP responder to use.
     592             :      1. Try to get the reponder from the certificate.
     593             :         We do only take http and https style URIs into account.
     594             :      2. If this fails use the default responder, if any.
     595             :    */
     596           0 :   url = NULL;
     597           0 :   for (idx=0; !url && !opt.ignore_ocsp_service_url && !force_default_responder
     598           0 :          && !(err=ksba_cert_get_authority_info_access (cert, idx,
     599           0 :                                                        &oid, &name)); idx++)
     600             :     {
     601           0 :       if ( !strcmp (oid, oidstr_ocsp) )
     602             :         {
     603           0 :           for (i=0; !url && ksba_name_enum (name, i); i++)
     604             :             {
     605           0 :               char *p = ksba_name_get_uri (name, i);
     606           0 :               if (p && (!ascii_strncasecmp (p, "http:", 5)
     607           0 :                         || !ascii_strncasecmp (p, "https:", 6)))
     608           0 :                 url = url_buffer = p;
     609             :               else
     610           0 :                 xfree (p);
     611             :             }
     612             :         }
     613           0 :       ksba_name_release (name);
     614           0 :       ksba_free (oid);
     615             :     }
     616           0 :   if (err && gpg_err_code (err) != GPG_ERR_EOF)
     617             :     {
     618           0 :       log_error (_("can't get authorityInfoAccess: %s\n"), gpg_strerror (err));
     619           0 :       goto leave;
     620             :     }
     621           0 :   if (!url)
     622             :     {
     623           0 :       if (!opt.ocsp_responder || !*opt.ocsp_responder)
     624             :         {
     625           0 :           log_info (_("no default OCSP responder defined\n"));
     626           0 :           err = gpg_error (GPG_ERR_CONFIGURATION);
     627           0 :           goto leave;
     628             :         }
     629           0 :       if (!opt.ocsp_signer)
     630             :         {
     631           0 :           log_info (_("no default OCSP signer defined\n"));
     632           0 :           err = gpg_error (GPG_ERR_CONFIGURATION);
     633           0 :           goto leave;
     634             :         }
     635           0 :       url = opt.ocsp_responder;
     636           0 :       default_signer = opt.ocsp_signer;
     637           0 :       if (opt.verbose)
     638           0 :         log_info (_("using default OCSP responder '%s'\n"), url);
     639             :     }
     640             :   else
     641             :     {
     642           0 :       if (opt.verbose)
     643           0 :         log_info (_("using OCSP responder '%s'\n"), url);
     644             :     }
     645             : 
     646             :   /* Ask the OCSP responder. */
     647           0 :   err = gcry_md_open (&md, GCRY_MD_SHA1, 0);
     648           0 :   if (err)
     649             :     {
     650           0 :       log_error (_("failed to establish a hashing context for OCSP: %s\n"),
     651             :                  gpg_strerror (err));
     652           0 :       goto leave;
     653             :     }
     654           0 :   err = do_ocsp_request (ctrl, ocsp, md, url, cert, issuer_cert);
     655           0 :   if (err)
     656           0 :     goto leave;
     657             : 
     658             :   /* We got a useful answer, check that the answer has a valid signature. */
     659           0 :   sigval = ksba_ocsp_get_sig_val (ocsp, produced_at);
     660           0 :   if (!sigval || !*produced_at)
     661             :     {
     662           0 :       err = gpg_error (GPG_ERR_INV_OBJ);
     663           0 :       goto leave;
     664             :     }
     665           0 :   if ( (err = canon_sexp_to_gcry (sigval, &s_sig)) )
     666           0 :     goto leave;
     667           0 :   xfree (sigval);
     668           0 :   sigval = NULL;
     669           0 :   err = check_signature (ctrl, ocsp, s_sig, md, default_signer);
     670           0 :   if (err)
     671           0 :     goto leave;
     672             : 
     673             :   /* We only support one certificate per request.  Check that the
     674             :      answer matches the right certificate. */
     675           0 :   err = ksba_ocsp_get_status (ocsp, cert,
     676             :                               &status, this_update, next_update,
     677             :                               revocation_time, &reason);
     678           0 :   if (err)
     679             :     {
     680           0 :       log_error (_("error getting OCSP status for target certificate: %s\n"),
     681             :                  gpg_strerror (err));
     682           0 :       goto leave;
     683             :     }
     684             : 
     685             :   /* In case the certificate has been revoked, we better invalidate
     686             :      our cached validation status. */
     687           0 :   if (status == KSBA_STATUS_REVOKED)
     688             :     {
     689           0 :       time_t validated_at = 0; /* That is: No cached validation available. */
     690           0 :       err = ksba_cert_set_user_data (cert, "validated_at",
     691             :                                      &validated_at, sizeof (validated_at));
     692           0 :       if (err)
     693             :         {
     694           0 :           log_error ("set_user_data(validated_at) failed: %s\n",
     695             :                      gpg_strerror (err));
     696           0 :           err = 0; /* The certificate is anyway revoked, and that is a
     697             :                       more important message than the failure of our
     698             :                       cache. */
     699             :         }
     700             :     }
     701             : 
     702             : 
     703           0 :   if (opt.verbose)
     704             :     {
     705           0 :       log_info (_("certificate status is: %s  (this=%s  next=%s)\n"),
     706           0 :                 status == KSBA_STATUS_GOOD? _("good"):
     707           0 :                 status == KSBA_STATUS_REVOKED? _("revoked"):
     708           0 :                 status == KSBA_STATUS_UNKNOWN? _("unknown"):
     709           0 :                 status == KSBA_STATUS_NONE? _("none"): "?",
     710             :                 this_update, next_update);
     711           0 :       if (status == KSBA_STATUS_REVOKED)
     712           0 :         log_info (_("certificate has been revoked at: %s due to: %s\n"),
     713             :                   revocation_time,
     714           0 :                   reason == KSBA_CRLREASON_UNSPECIFIED?   "unspecified":
     715           0 :                   reason == KSBA_CRLREASON_KEY_COMPROMISE? "key compromise":
     716           0 :                   reason == KSBA_CRLREASON_CA_COMPROMISE?   "CA compromise":
     717           0 :                   reason == KSBA_CRLREASON_AFFILIATION_CHANGED?
     718           0 :                                                       "affiliation changed":
     719           0 :                   reason == KSBA_CRLREASON_SUPERSEDED?   "superseeded":
     720           0 :                   reason == KSBA_CRLREASON_CESSATION_OF_OPERATION?
     721           0 :                                                   "cessation of operation":
     722           0 :                   reason == KSBA_CRLREASON_CERTIFICATE_HOLD?
     723           0 :                                                   "certificate on hold":
     724           0 :                   reason == KSBA_CRLREASON_REMOVE_FROM_CRL?
     725           0 :                                                   "removed from CRL":
     726           0 :                   reason == KSBA_CRLREASON_PRIVILEGE_WITHDRAWN?
     727           0 :                                                   "privilege withdrawn":
     728           0 :                   reason == KSBA_CRLREASON_AA_COMPROMISE? "AA compromise":
     729           0 :                   reason == KSBA_CRLREASON_OTHER?   "other":"?");
     730             : 
     731             :     }
     732             : 
     733             : 
     734           0 :   if (status == KSBA_STATUS_REVOKED)
     735           0 :     err = gpg_error (GPG_ERR_CERT_REVOKED);
     736           0 :   else if (status == KSBA_STATUS_UNKNOWN)
     737           0 :     err = gpg_error (GPG_ERR_NO_DATA);
     738           0 :   else if (status != KSBA_STATUS_GOOD)
     739           0 :     err = gpg_error (GPG_ERR_GENERAL);
     740             : 
     741             :   /* Allow for some clock skew. */
     742           0 :   gnupg_get_isotime (current_time);
     743           0 :   add_seconds_to_isotime (current_time, opt.ocsp_max_clock_skew);
     744             : 
     745           0 :   if (strcmp (this_update, current_time) > 0 )
     746             :     {
     747           0 :       log_error (_("OCSP responder returned a status in the future\n"));
     748           0 :       log_info ("used now: %s  this_update: %s\n", current_time, this_update);
     749           0 :       if (!err)
     750           0 :         err = gpg_error (GPG_ERR_TIME_CONFLICT);
     751             :     }
     752             : 
     753             :   /* Check that THIS_UPDATE is not too far back in the past. */
     754           0 :   gnupg_copy_time (tmp_time, this_update);
     755           0 :   add_seconds_to_isotime (tmp_time,
     756           0 :                           opt.ocsp_max_period+opt.ocsp_max_clock_skew);
     757           0 :   if (!*tmp_time || strcmp (tmp_time, current_time) < 0 )
     758             :     {
     759           0 :       log_error (_("OCSP responder returned a non-current status\n"));
     760           0 :       log_info ("used now: %s  this_update: %s\n",
     761             :                 current_time, this_update);
     762           0 :       if (!err)
     763           0 :         err = gpg_error (GPG_ERR_TIME_CONFLICT);
     764             :     }
     765             : 
     766             :   /* Check that we are not beyound NEXT_UPDATE  (plus some extra time). */
     767           0 :   if (*next_update)
     768             :     {
     769           0 :       gnupg_copy_time (tmp_time, next_update);
     770           0 :       add_seconds_to_isotime (tmp_time,
     771           0 :                               opt.ocsp_current_period+opt.ocsp_max_clock_skew);
     772           0 :       if (!*tmp_time && strcmp (tmp_time, current_time) < 0 )
     773             :         {
     774           0 :           log_error (_("OCSP responder returned an too old status\n"));
     775           0 :           log_info ("used now: %s  next_update: %s\n",
     776             :                     current_time, next_update);
     777           0 :           if (!err)
     778           0 :             err = gpg_error (GPG_ERR_TIME_CONFLICT);
     779             :         }
     780             :     }
     781             : 
     782             : 
     783             :  leave:
     784           0 :   gcry_md_close (md);
     785           0 :   gcry_sexp_release (s_sig);
     786           0 :   xfree (sigval);
     787           0 :   ksba_cert_release (issuer_cert);
     788           0 :   ksba_cert_release (cert);
     789           0 :   ksba_ocsp_release (ocsp);
     790           0 :   xfree (url_buffer);
     791           0 :   return err;
     792             : }
     793             : 
     794             : 
     795             : /* Release the list of OCSP certificates hold in the CTRL object. */
     796             : void
     797           0 : release_ctrl_ocsp_certs (ctrl_t ctrl)
     798             : {
     799           0 :   while (ctrl->ocsp_certs)
     800             :     {
     801           0 :       cert_ref_t tmp = ctrl->ocsp_certs->next;
     802           0 :       xfree (ctrl->ocsp_certs);
     803           0 :       ctrl->ocsp_certs = tmp;
     804             :     }
     805           0 : }

Generated by: LCOV version 1.11