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