dirmngr,gpg: Better diagnostic in case of bad TLS certificates.
authorWerner Koch <wk@gnupg.org>
Mon, 18 Nov 2019 17:23:04 +0000 (18:23 +0100)
committerWerner Koch <wk@gnupg.org>
Mon, 18 Nov 2019 17:26:55 +0000 (18:26 +0100)
* doc/DETAILS: Specify new status code "NOTE".
* dirmngr/ks-engine-http.c (ks_http_fetch): Print a NOTE status for a
bad TLS certificate.
* g10/call-dirmngr.c (ks_status_cb): Detect this status.
--

For example a

  gpg -v --locate-external-keys dd9jn@posteo.net

now yields

  gpg: Note: server uses an invalid certificate
  gpg: (further info: bad cert for 'posteo.net': \
                      Hostname does not match the certificate)
  gpg: error retrieving 'dd9jn@posteo.net' via WKD: Wrong name
  gpg: error reading key: Wrong name

(without -v the "further info" line is not shown).  Note that even
after years Posteo is not able to provide a valid certificate for
their .net addresses.  Anyway, this help to show the feature.

Signed-off-by: Werner Koch <wk@gnupg.org>
dirmngr/ks-engine-http.c
doc/DETAILS
g10/call-dirmngr.c

index 007bbc9..f55a257 100644 (file)
@@ -78,6 +78,7 @@ ks_http_fetch (ctrl_t ctrl, const char *url, unsigned int flags,
   estream_t fp = NULL;
   char *request_buffer = NULL;
   parsed_uri_t uri = NULL;
+  parsed_uri_t helpuri = NULL;
 
   err = http_parse_uri (&uri, url, 0);
   if (err)
@@ -134,9 +135,25 @@ ks_http_fetch (ctrl_t ctrl, const char *url, unsigned int flags,
     }
   if (err)
     {
-      /* Fixme: After a redirection we show the old host name.  */
       log_error (_("error connecting to '%s': %s\n"),
                  url, gpg_strerror (err));
+      if (gpg_err_code (err) == GPG_ERR_WRONG_NAME
+          && gpg_err_source (err) == GPG_ERR_SOURCE_TLS)
+        {
+          const char *errhostname;
+
+          http_release_parsed_uri (helpuri);
+          if (http_parse_uri (&helpuri, url, 0))
+            errhostname = url; /* On parse error we use the full URL. */
+          else
+            errhostname = helpuri->host? helpuri->host : "?";
+
+          dirmngr_status_printf (ctrl, "NOTE",
+                                 "tls_cert_error %u"
+                                 " bad cert for '%s': %s",
+                                 err, errhostname,
+                                 "Hostname does not match the certificate");
+        }
       goto leave;
     }
 
@@ -203,5 +220,6 @@ ks_http_fetch (ctrl_t ctrl, const char *url, unsigned int flags,
   http_session_release (session);
   xfree (request_buffer);
   http_release_parsed_uri (uri);
+  http_release_parsed_uri (helpuri);
   return err;
 }
index 6e36252..6ce340e 100644 (file)
@@ -1053,10 +1053,14 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
     numerical error code and an underscore; e.g.: "151011327_EOF".
 *** WARNING <location> <error code> [<text>]
     This is a generic warning status message, it might be followed by
-    error location specific data. <error code> and <location>
-    should not contain spaces.  The error code is a either a string
-    commencing with a letter or such a string prefixed with a
-    numerical error code and an underscore; e.g.: "151011327_EOF".
+    error location specific data. <location> and <error code> may not
+    contain spaces.  The <location> may be used to indicate a class of
+    warnings.  The error code is a either a string commencing with a
+    letter or such a string prefixed with a numerical error code and
+    an underscore; e.g.: "151011327_EOF".
+*** NOTE <location> <error code> [<text>]
+    This is a generic info status message the same syntax as for
+    WARNING messages is used.
 *** SUCCESS [<location>]
     Positive confirmation that an operation succeeded.  It is used
     similar to ISO-C's EXIT_SUCCESS.  <location> is optional but if
index 58829c7..88fd97e 100644 (file)
@@ -395,6 +395,7 @@ ks_status_cb (void *opaque, const char *line)
   gpg_error_t err = 0;
   const char *s, *s2;
   const char *warn;
+  int is_note = 0;
 
   if ((s = has_leading_keyword (line, parm->keyword? parm->keyword : "SOURCE")))
     {
@@ -406,7 +407,8 @@ ks_status_cb (void *opaque, const char *line)
             err = gpg_error_from_syserror ();
         }
     }
-  else if ((s = has_leading_keyword (line, "WARNING")))
+  else if ((s = has_leading_keyword (line, "WARNING"))
+           || (is_note = !!(s = has_leading_keyword (line, "NOTE"))))
     {
       if ((s2 = has_leading_keyword (s, "tor_not_running")))
         warn = _("Tor is not running");
@@ -418,12 +420,17 @@ ks_status_cb (void *opaque, const char *line)
         warn = _("unacceptable HTTP redirect from server");
       else if ((s2 = has_leading_keyword (s, "http_redirect_cleanup")))
         warn = _("unacceptable HTTP redirect from server was cleaned up");
+      else if ((s2 = has_leading_keyword (s, "tls_cert_error")))
+        warn = _("server uses an invalid certificate");
       else
         warn = NULL;
 
       if (warn)
         {
-          log_info (_("WARNING: %s\n"), warn);
+          if (is_note)
+            log_info (_("Note: %s\n"), warn);
+          else
+            log_info (_("WARNING: %s\n"), warn);
           if (s2)
             {
               while (*s2 && !spacep (s2))