http: Add callback to help logging of server certificates.
authorWerner Koch <wk@gnupg.org>
Mon, 19 May 2014 07:47:18 +0000 (09:47 +0200)
committerWerner Koch <wk@gnupg.org>
Mon, 19 May 2014 07:47:18 +0000 (09:47 +0200)
* common/http.c (http_session_s): Add field cert_log_cb.
(http_session_set_log_cb): New.
(http_verify_server_credentials): Call callback.

common/http.c
common/http.h

index 8a1ad67..4fc89d7 100644 (file)
@@ -234,10 +234,12 @@ struct http_session_s
   } verify;
   char *servername; /* Malloced server name.  */
 #endif /*HTTP_USE_GNUTLS*/
+  /* A callback function to log details of TLS certifciates.  */
+  void (*cert_log_cb) (http_session_t, gpg_error_t, const char *,
+                       const void **, size_t *);
 };
 
 
-
 /* An object to save header lines. */
 struct header_s
 {
@@ -644,6 +646,18 @@ http_session_ref (http_session_t sess)
 }
 
 
+void
+http_session_set_log_cb (http_session_t sess,
+                         void (*cb)(http_session_t, gpg_error_t,
+                                    const char *hostname,
+                                    const void **certs, size_t *certlens))
+{
+  sess->cert_log_cb = cb;
+}
+
+
+
+\f
 /* Start a HTTP retrieval and on success store at R_HD a context
    pointer for completing the request and to wait for the response.
    If HTTPHOST is not NULL it is used hor the Host header instead of a
@@ -2497,24 +2511,6 @@ http_verify_server_credentials (http_session_t sess)
         return err;
     }
 
-  /* log_debug ("Server sent %u certs\n", certlistlen); */
-  /* { */
-  /*   int i; */
-  /*   char fname[50]; */
-  /*   FILE *fp; */
-
-  /*   for (i=0; i < certlistlen; i++) */
-  /*     { */
-  /*       snprintf (fname, sizeof fname, "xc_%d.der", i); */
-  /*       fp = fopen (fname, "wb"); */
-  /*       if (!fp) */
-  /*         log_fatal ("Failed to create '%s'\n", fname); */
-  /*       if (fwrite (certlist[i].data, certlist[i].size, 1, fp) != 1) */
-  /*         log_fatal ("Error writing to '%s'\n", fname); */
-  /*       fclose (fp); */
-  /*     } */
-  /* } */
-
   rc = gnutls_x509_crt_init (&cert);
   if (rc < 0)
     {
@@ -2536,14 +2532,31 @@ http_verify_server_credentials (http_session_t sess)
   if (!gnutls_x509_crt_check_hostname (cert, hostname))
     {
       log_error ("%s: %s\n", errprefix, "hostname does not match");
-      log_info ("(expected '%s')\n", hostname);
       if (!err)
         err = gpg_error (GPG_ERR_GENERAL);
     }
 
   gnutls_x509_crt_deinit (cert);
+
   if (!err)
     sess->verify.rc = 0;
+
+  if (sess->cert_log_cb)
+    {
+      const void *bufarr[10];
+      size_t buflenarr[10];
+      size_t n;
+
+      for (n = 0; n < certlistlen && n < DIM (bufarr)-1; n++)
+        {
+          bufarr[n] = certlist[n].data;
+          buflenarr[n] = certlist[n].size;
+        }
+      bufarr[n] = NULL;
+      buflenarr[n] = 0;
+      sess->cert_log_cb (sess, err, hostname, bufarr, buflenarr);
+    }
+
   return err;
 #else /*!HTTP_USE_GNUTLS*/
   (void)sess;
index acfdc0f..416e220 100644 (file)
@@ -98,6 +98,11 @@ gpg_error_t http_session_new (http_session_t *r_session,
 http_session_t http_session_ref (http_session_t sess);
 void http_session_release (http_session_t sess);
 
+void http_session_set_log_cb (http_session_t sess,
+                              void (*cb)(http_session_t, gpg_error_t,
+                                         const char *,
+                                         const void **, size_t *));
+
 
 gpg_error_t http_parse_uri (parsed_uri_t *ret_uri, const char *uri,
                             int no_scheme_check);