dirmngr: Fallback to CRL if no default OCSP responder is configured.
authorWerner Koch <wk@gnupg.org>
Tue, 24 Apr 2018 09:40:51 +0000 (11:40 +0200)
committerWerner Koch <wk@gnupg.org>
Tue, 24 Apr 2018 09:40:51 +0000 (11:40 +0200)
* dirmngr/server.c (cmd_isvalid): Use option second arg to trigger
OCSP checkibng.  Fallback to CRL if no default OCSP responder has been
configured.
* sm/call-dirmngr.c (gpgsm_dirmngr_isvalid): Adjust accordingly.

Signed-off-by: Werner Koch <wk@gnupg.org>
dirmngr/server.c
sm/call-dirmngr.c

index 4315c41..48244d4 100644 (file)
@@ -1105,7 +1105,7 @@ cmd_ldapserver (assuan_context_t ctx, char *line)
 
 static const char hlp_isvalid[] =
   "ISVALID [--only-ocsp] [--force-default-responder]"
-  " <certificate_id>|<certificate_fpr>\n"
+  " <certificate_id> [<certificate_fpr>]\n"
   "\n"
   "This command checks whether the certificate identified by the\n"
   "certificate_id is valid.  This is done by consulting CRLs or\n"
@@ -1117,8 +1117,9 @@ static const char hlp_isvalid[] =
   "delimited by a single dot.  The first part is the SHA-1 hash of the\n"
   "issuer name and the second part the serial number.\n"
   "\n"
-  "Alternatively the certificate's fingerprint may be given in which\n"
-  "case an OCSP request is done before consulting the CRL.\n"
+  "If an OCSP check is desired CERTIFICATE_FPR with the hex encoded\n"
+  "fingerprint of the certificate is required.  In this case an OCSP\n"
+  "request is done before consulting the CRL.\n"
   "\n"
   "If the option --only-ocsp is given, no fallback to a CRL check will\n"
   "be used.\n"
@@ -1130,7 +1131,7 @@ static gpg_error_t
 cmd_isvalid (assuan_context_t ctx, char *line)
 {
   ctrl_t ctrl = assuan_get_pointer (ctx);
-  char *issuerhash, *serialno;
+  char *issuerhash, *serialno, *fpr;
   gpg_error_t err;
   int did_inquire = 0;
   int ocsp_mode = 0;
@@ -1141,25 +1142,36 @@ cmd_isvalid (assuan_context_t ctx, char *line)
   force_default_responder = has_option (line, "--force-default-responder");
   line = skip_options (line);
 
-  issuerhash = xstrdup (line); /* We need to work on a copy of the
-                                  line because that same Assuan
-                                  context may be used for an inquiry.
-                                  That is because Assuan reuses its
-                                  line buffer.
-                                   */
+  /* We need to work on a copy of the line because that same Assuan
+   * context may be used for an inquiry.  That is because Assuan
+   * reuses its line buffer.  */
+  issuerhash = xstrdup (line);
 
   serialno = strchr (issuerhash, '.');
-  if (serialno)
-    *serialno++ = 0;
-  else
+  if (!serialno)
+    {
+      xfree (issuerhash);
+      return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID")));
+    }
+  *serialno++ = 0;
+  if (strlen (issuerhash) != 40)
     {
-      char *endp = strchr (issuerhash, ' ');
+      xfree (issuerhash);
+      return leave_cmd (ctx, PARM_ERROR ("cert ID is too short"));
+    }
+
+  fpr = strchr (serialno, ' ');
+  while (fpr && spacep (fpr))
+    fpr++;
+  if (fpr && *fpr)
+    {
+      char *endp = strchr (fpr, ' ');
       if (endp)
         *endp = 0;
-      if (strlen (issuerhash) != 40)
+      if (strlen (fpr) != 40)
         {
           xfree (issuerhash);
-          return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID")));
+          return leave_cmd (ctx, PARM_ERROR ("fingerprint too short"));
         }
       ocsp_mode = 1;
     }
@@ -1168,17 +1180,24 @@ cmd_isvalid (assuan_context_t ctx, char *line)
  again:
   if (ocsp_mode)
     {
-      /* Note, that we ignore the given issuer hash and instead rely
-         on the current certificate semantics used with this
-         command. */
+      /* Note, that we currently ignore the supplied fingerprint FPR;
+       * instead ocsp_isvalid does an inquire to ask for the cert.
+       * The fingerprint may eventually be used to lookup the
+       * certificate in a local cache.  */
       if (!opt.allow_ocsp)
         err = gpg_error (GPG_ERR_NOT_SUPPORTED);
       else
         err = ocsp_isvalid (ctrl, NULL, NULL, force_default_responder);
-      /* Fixme: If we got no ocsp response and --only-ocsp is not used
-         we should fall back to CRL mode.  Thus we need to clear
-         OCSP_MODE, get the issuerhash and the serialno from the
-         current certificate and jump to again. */
+
+      if (gpg_err_code (err) == GPG_ERR_CONFIGURATION
+          && gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR)
+        {
+          /* No default responder configured - fallback to CRL.  */
+          if (!only_ocsp)
+            log_info ("falling back to CRL check\n");
+          ocsp_mode = 0;
+          goto again;
+        }
     }
   else if (only_ocsp)
     err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
index e943118..3a38bca 100644 (file)
@@ -491,8 +491,8 @@ isvalid_status_cb (void *opaque, const char *line)
 
   Values for USE_OCSP:
      0 = Do CRL check.
-     1 = Do an OCSP check.
-     2 = Do an OCSP check using only the default responder.
+     1 = Do an OCSP check but fallback to CRL unless CRLS are disabled.
+     2 = Do only an OCSP check using only the default responder.
  */
 int
 gpgsm_dirmngr_isvalid (ctrl_t ctrl,
@@ -500,7 +500,7 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
 {
   static int did_options;
   int rc;
-  char *certid;
+  char *certid, *certfpr;
   char line[ASSUAN_LINELENGTH];
   struct inq_certificate_parm_s parm;
   struct isvalid_status_parm_s stparm;
@@ -509,19 +509,13 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
   if (rc)
     return rc;
 
-  if (use_ocsp)
+  certfpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
+  certid = gpgsm_get_certid (cert);
+  if (!certid)
     {
-      certid = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
-    }
-  else
-    {
-      certid = gpgsm_get_certid (cert);
-      if (!certid)
-        {
-          log_error ("error getting the certificate ID\n");
-         release_dirmngr (ctrl);
-          return gpg_error (GPG_ERR_GENERAL);
-        }
+      log_error ("error getting the certificate ID\n");
+      release_dirmngr (ctrl);
+      return gpg_error (GPG_ERR_GENERAL);
     }
 
   if (opt.verbose > 1)
@@ -541,13 +535,8 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
   stparm.seen = 0;
   memset (stparm.fpr, 0, 20);
 
-  /* FIXME: If --disable-crl-checks has been set, we should pass an
-     option to dirmngr, so that no fallback CRL check is done after an
-     ocsp check.  It is not a problem right now as dirmngr does not
-     fallback to CRL checking.  */
-
   /* It is sufficient to send the options only once because we have
-     one connection per process only. */
+   * one connection per process only.  */
   if (!did_options)
     {
       if (opt.force_crl_refresh)
@@ -555,10 +544,14 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
                          NULL, NULL, NULL, NULL, NULL, NULL);
       did_options = 1;
     }
-  snprintf (line, DIM(line), "ISVALID%s %s",
-            use_ocsp == 2? " --only-ocsp --force-default-responder":"",
-            certid);
+  snprintf (line, DIM(line), "ISVALID%s%s %s%s%s",
+            use_ocsp == 2 || opt.no_crl_check ? " --only-ocsp":"",
+            use_ocsp == 2? " --force-default-responder":"",
+            certid,
+            use_ocsp? " ":"",
+            use_ocsp? certfpr:"");
   xfree (certid);
+  xfree (certfpr);
 
   rc = assuan_transact (dirmngr_ctx, line, NULL, NULL,
                         inq_certificate, &parm,