[git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-402-g2def230

by Werner Koch cvs at cvs.gnupg.org
Fri May 2 14:06:25 CEST 2014


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  2def230231abd34f6012df284ab468321ffedc10 (commit)
       via  8412a5825c225c8ff14de3ffaad2e55e040b2eca (commit)
       via  84289e85c72ae58c321dfdb96816700a6b7f7122 (commit)
      from  8416c875a729426eae05ed1ca9f1ebcb933c246a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 2def230231abd34f6012df284ab468321ffedc10
Author: Werner Koch <wk at gnupg.org>
Date:   Fri May 2 14:07:03 2014 +0200

    common: Fix test for openpgp_oid_is_ed25519.
    
    * common/t-openpgp-oid.c (test_openpgp_oid_is_ed25519): Add correct
    value.

diff --git a/common/t-openpgp-oid.c b/common/t-openpgp-oid.c
index d101b75..79e5a70 100644
--- a/common/t-openpgp-oid.c
+++ b/common/t-openpgp-oid.c
@@ -145,10 +145,15 @@ test_openpgp_oid_is_ed25519 (void)
     { 0, "0.0" },
     { 0, "1.3.132.0.35" },
     { 0, "1.3.6.1.4.1.3029.1.5.0" },
-    { 1, "1.3.6.1.4.1.3029.1.5.1" },
+    { 0, "1.3.6.1.4.1.3029.1.5.1" }, /* Used during Libgcrypt development. */
     { 0, "1.3.6.1.4.1.3029.1.5.2" },
     { 0, "1.3.6.1.4.1.3029.1.5.1.0" },
     { 0, "1.3.6.1.4.1.3029.1.5" },
+    { 0, "1.3.6.1.4.1.11591.15.0" },
+    { 1, "1.3.6.1.4.1.11591.15.1" }, /* Your the one we want.  */
+    { 0, "1.3.6.1.4.1.11591.15.2" },
+    { 0, "1.3.6.1.4.1.11591.15.1.0" },
+    { 0, "1.3.6.1.4.1.11591.15" },
     { 0, NULL },
   };
   gpg_error_t err;

commit 8412a5825c225c8ff14de3ffaad2e55e040b2eca
Author: Werner Koch <wk at gnupg.org>
Date:   Fri May 2 10:33:19 2014 +0200

    http: Revamp TLS API.
    
    * configure.ac (NEED_GNUTLS_VERSION): New.
    (HTTP_USE_GNUTLS, LIBGNUTLS_CFLAGS, LIBGNUTLS_LIBS): New ac_subst.
    
    * common/http.h (http_session_t): New.
    * common/http.c: Remove compatibility for gnutls < 3.0.
    (http_session_s): New.
    (cookie_s): Replace gnutls_session_t by http_session_t.
    (tls_callback, tls_ca_certlist): New variables.
    (my_socket_unref): Add preclose args.
    (my_npth_read, my_npth_write): New.
    (make_header_line): Fix bug using int* instead of char*.
    (http_register_tls_callback): New.
    (http_register_tls_ca): New.
    (http_session_new): New.
    (http_session_release): New.
    (http_get_header_names): New.
    (escape_data): Add hack to escape in forms mode.
    (send_request) [HTTP_USE_GNUTLS]: Support SNI.
    (send_request) [HTTP_USE_GNUTLS]: Fix use of make_header_line.
    (send_gnutls_bye): New.
    (cookie_close): Make use of preclose feature.
    (http_verify_server_credentials): New.
    (main) [TEST]: Remove test code.
    * common/t-http.c: New.
    * common/tls-ca.pem: New.
    * common/Makefile.am (tls_sources): New. Move http code to here.
    (libcommontls_a_SOURCES): New.
    (libcommontlsnpth_a_SOURCES): New.
    (EXTRA_DIST): Add tls-ca.pem
    (module_maint_tests): Add t-http.
    (t_http_SOURCES, t_http_CFLAGS, t_http_LDADD): New.
    
    * dirmngr/Makefile.am (dirmngr_LDADD): Add libcommontlsnpth.
    --
    
    This new TLS API for http.c is much more flexible than the crude old
    hack.

diff --git a/am/cmacros.am b/am/cmacros.am
index 6ee4283..4b48560 100644
--- a/am/cmacros.am
+++ b/am/cmacros.am
@@ -75,3 +75,5 @@ resource_objs =
 # Convenience macros
 libcommon = ../common/libcommon.a
 libcommonpth = ../common/libcommonpth.a
+libcommontls = ../common/libcommontls.a
+libcommontlsnpth = ../common/libcommontlsnpth.a
diff --git a/common/Makefile.am b/common/Makefile.am
index f1cf28c..439c29b 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -20,9 +20,10 @@
 
 EXTRA_DIST = mkstrtable.awk exaudit.awk exstatus.awk ChangeLog-2011 \
              audit-events.h status-codes.h README.jnlib ChangeLog.jnlib \
-	     ChangeLog-2011.include w32info-rc.h.in gnupg.ico
+	     ChangeLog-2011.include w32info-rc.h.in gnupg.ico tls-ca.pem
 
-noinst_LIBRARIES = libcommon.a libcommonpth.a libgpgrl.a
+noinst_LIBRARIES = libcommon.a libcommonpth.a libgpgrl.a \
+                   libcommontls.a libcommontlsnpth.a
 if !HAVE_W32CE_SYSTEM
 noinst_LIBRARIES += libsimple-pwquery.a
 endif
@@ -88,7 +89,6 @@ common_sources = \
 	srv.h \
 	dns-cert.c dns-cert.h \
 	pka.c pka.h \
-	http.c http.h \
 	localename.c \
 	session-env.c session-env.h \
 	userids.c userids.h \
@@ -97,6 +97,12 @@ common_sources = \
 	agent-opt.c \
 	helpfile.c
 
+# Sources possible requiring a TLS library are put into a separate
+# conveince library.
+tls_sources = \
+	http.c http.h
+
+
 # To make the code easier to read we have split home some code into
 # separate source files.
 if HAVE_W32_SYSTEM
@@ -126,6 +132,12 @@ libcommonpth_a_SOURCES += srv.c
 endif
 libcommonpth_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS)
 
+libcommontls_a_SOURCES = $(tls_sources)
+libcommontls_a_CFLAGS = $(AM_CFLAGS) $(LIBGNUTLS_CFLAGS) -DWITHOUT_NPTH=1
+
+libcommontlsnpth_a_SOURCES = $(tls_sources)
+libcommontlsnpth_a_CFLAGS = $(AM_CFLAGS) $(LIBGNUTLS_CFLAGS) $(NPTH_CFLAGS)
+
 if !HAVE_W32CE_SYSTEM
 libsimple_pwquery_a_SOURCES = \
 	simple-pwquery.c simple-pwquery.h asshelp.c asshelp.h
@@ -170,11 +182,12 @@ module_tests = t-convert t-percent t-gettime t-sysutils t-sexputil \
 if !HAVE_W32CE_SYSTEM
 module_tests += t-exechelp
 endif
-module_maint_tests = t-helpfile t-b64
+module_maint_tests = t-helpfile t-b64 t-http
 
 
 t_common_ldadd = libcommon.a ../gl/libgnu.a \
-                 $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV)
+                 $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
+	         $(LIBINTL) $(LIBICONV)
 
 # jnlib tests
 t_stringhelp_SOURCES = t-stringhelp.c $(t_jnlib_src)
@@ -203,3 +216,8 @@ t_ssh_utils_LDADD = $(t_common_ldadd)
 t_dns_cert_LDADD = $(t_common_ldadd) $(DNSLIBS)
 t_mapstrings_LDADD = $(t_common_ldadd)
 t_zb32_LDADD = $(t_common_ldadd)
+
+# http tests
+t_http_SOURCES = t-http.c
+t_http_CFLAGS  = $(t_common_cflags) $(LIBGNUTLS_CFLAGS)
+t_http_LDADD   = $(libcommontls) $(t_common_ldadd) $(LIBGNUTLS_LIBS) $(DNSLIBS)
diff --git a/common/http.c b/common/http.c
index 11a7130..e5516e8 100644
--- a/common/http.c
+++ b/common/http.c
@@ -39,8 +39,9 @@
   - fixme: list other requirements.
 
 
-  - With HTTP_USE_GNUTLS support for https is provided (this also
-    requires estream).
+  - With HTTP_USE_GNUTLS or HTTP_USE_POLARSSL support for https is
+    provided (this also requires estream).
+
   - With HTTP_NO_WSASTARTUP the socket initialization is not done
     under Windows.  This is useful if the socket layer has already
     been initialized elsewhere.  This also avoids the installation of
@@ -81,20 +82,19 @@
 # include <npth.h>
 #endif
 
+#if defined (HTTP_USE_GNUTLS) && defined (HTTP_USE_POLARSSL)
+# error Both, HTTP_USE_GNUTLS and HTTP_USE_POLARSSL, are defined.
+#endif
+
 #ifdef HTTP_USE_GNUTLS
 # include <gnutls/gnutls.h>
-/* For non-understandable reasons GNUTLS dropped the _t suffix from
-   all types. yes, ISO-C might be read as this but there are still
-   other name space conflicts and using _t is actually a Good
-   Thing. */
-typedef gnutls_session gnutls_session_t;
-typedef gnutls_transport_ptr gnutls_transport_ptr_t;
+# include <gnutls/x509.h>
 #endif /*HTTP_USE_GNUTLS*/
-
-#ifdef TEST
-# undef USE_DNS_SRV
+#ifdef HTTP_USE_POLARSSL
+# error Support for PolarSSL has not yet been added
 #endif
 
+
 #include "util.h"
 #include "i18n.h"
 #include "http.h"
@@ -204,22 +204,36 @@ struct cookie_s
   /* Socket object or NULL if already closed. */
   my_socket_t sock;
 
-  /* TLS session context or NULL if not used. */
-  gnutls_session_t tls_session;
+  /* The session object or NULL if not used. */
+  http_session_t session;
+
+  /* True if TLS is to be used.  */
+  int use_tls;
 
   /* The remaining content length and a flag telling whether to use
      the content length.  */
   longcounter_t content_length;
   unsigned int content_length_valid:1;
-
-  /* Flag to communicate with the close handler. */
-  unsigned int keep_socket:1;
 };
 typedef struct cookie_s *cookie_t;
 
+/* The session object. */
+struct http_session_s
+{
 #ifdef HTTP_USE_GNUTLS
-static gpg_error_t (*tls_callback) (http_t, gnutls_session_t, int);
-#endif /*HTTP_USE_GNUTLS*/
+  gnutls_certificate_credentials_t certcred;
+  gnutls_session_t tls_session;
+  struct {
+    int done;      /* Verifciation has been done.  */
+    int rc;        /* GnuTLS verification return code.  */
+    unsigned int status; /* Verification status.  */
+  } verify;
+  char *servername; /* Malloced server name.  */
+#else
+  int dummy;
+#endif
+};
+
 
 
 /* An object to save header lines. */
@@ -243,7 +257,7 @@ struct http_context_s
   estream_t fp_write;
   void *write_cookie;
   void *read_cookie;
-  void *tls_context;
+  http_session_t session;
   parsed_uri_t uri;
   http_req_t req_type;
   char *buffer;          /* Line buffer. */
@@ -253,6 +267,12 @@ struct http_context_s
 };
 
 
+/* The global callback for the verification fucntion.  */
+static gpg_error_t (*tls_callback) (http_t, http_session_t, int);
+
+/* The list of files with trusted CA certificates.  */
+static strlist_t tls_ca_certlist;
+
 
 

 #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
@@ -340,7 +360,7 @@ my_socket_ref (my_socket_t so)
    has no more references, close the socket and release the
    object.  */
 static void
-my_socket_unref (my_socket_t so)
+my_socket_unref (my_socket_t so, void (*preclose)(void*), void *preclosearg)
 {
   if (so)
     {
@@ -349,6 +369,8 @@ my_socket_unref (my_socket_t so)
       /*            lnr, so, so->fd, so->refcount); */
       if (!so->refcount)
         {
+          if (preclose)
+            preclose (preclosearg);
           sock_close (so->fd);
           xfree (so);
         }
@@ -357,6 +379,21 @@ my_socket_unref (my_socket_t so)
 /* #define my_socket_unref(a) _my_socket_unref ((a),__LINE__) */
 
 
+#if defined (USE_NPTH) && defined(HTTP_USE_GNUTLS)
+static ssize_t
+my_npth_read (gnutls_transport_ptr_t ptr, void *buffer, size_t size)
+{
+  return npth_read ((int)(unsigned long)ptr, buffer, size);
+}
+static ssize_t
+my_npth_write (gnutls_transport_ptr_t ptr, const void *buffer, size_t size)
+{
+  return npth_write ((int)(unsigned long)ptr, buffer, size);
+}
+#endif /*USE_NPTH && HTTP_USE_GNUTLS*/
+
+
+
 

 /* This notification function is called by estream whenever stream is
    closed.  Its purpose is to mark the closing in the handle so
@@ -383,13 +420,13 @@ fp_onclose_notification (estream_t stream, void *opaque)
  */
 static char *
 make_header_line (const char *prefix, const char *suffix,
-                   const void *data, size_t len )
+                  const void *data, size_t len )
 {
   static unsigned char bintoasc[] =
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     "abcdefghijklmnopqrstuvwxyz"
     "0123456789+/";
-  const unsigned int *s = data;
+  const unsigned char *s = data;
   char *buffer, *p;
 
   buffer = xtrymalloc (strlen (prefix) + (len+2)/3*4 + strlen (suffix) + 1);
@@ -402,6 +439,7 @@ make_header_line (const char *prefix, const char *suffix,
       *p++ = bintoasc[(((s[0] <<4)&060)|((s[1] >> 4)&017))&077];
       *p++ = bintoasc[(((s[1]<<2)&074)|((s[2]>>6)&03))&077];
       *p++ = bintoasc[s[2]&077];
+      *p = 0;
     }
   if ( len == 2 )
     {
@@ -417,6 +455,7 @@ make_header_line (const char *prefix, const char *suffix,
       *p++ = '=';
       *p++ = '=';
     }
+  *p = 0;
   strcpy (p, suffix);
   return buffer;
 }
@@ -424,17 +463,132 @@ make_header_line (const char *prefix, const char *suffix,
 
 
 

+/* Register the global TLS callback fucntion.  */
+void
+http_register_tls_callback (gpg_error_t (*cb)(http_t, http_session_t, int))
+{
+  tls_callback = cb;
+}
+
+
+/* Register a CA certificate for future use.  The certificate is
+   expected to be in FNAME.  PEM format is assume if FNAME has a
+   suffix of ".pem" */
 void
-http_register_tls_callback ( gpg_error_t (*cb) (http_t, void *, int) )
+http_register_tls_ca (const char *fname)
+{
+  strlist_t sl;
+
+  sl = add_to_strlist (&tls_ca_certlist, fname);
+  if (*sl->d && !strcmp (sl->d + strlen (sl->d) - 4, ".pem"))
+    sl->flags = 1;
+}
+
+
+/* Create a new session object which is currently used to enable TLS
+   support.  It may eventually allow reusing existing connections.  */
+gpg_error_t
+http_session_new (http_session_t *r_session, const char *tls_priority)
 {
+  gpg_error_t err;
+  http_session_t sess;
+
+  *r_session = NULL;
+
+  sess = xtrycalloc (1, sizeof *sess);
+  if (!sess)
+    return gpg_error_from_syserror ();
+
 #ifdef HTTP_USE_GNUTLS
-  tls_callback = (gpg_error_t (*) (http_t, gnutls_session_t, int))cb;
-#else
-  (void)cb;
-#endif
+  {
+    const char *errpos;
+    int rc;
+    strlist_t sl;
+
+    rc = gnutls_certificate_allocate_credentials (&sess->certcred);
+    if (rc < 0)
+      {
+        log_error ("gnutls_certificate_allocate_credentials failed: %s\n",
+                   gnutls_strerror (rc));
+        err = gpg_error (GPG_ERR_GENERAL);
+        goto leave;
+      }
+
+    for (sl = tls_ca_certlist; sl; sl = sl->next)
+      {
+        rc = gnutls_certificate_set_x509_trust_file
+          (sess->certcred, sl->d,
+           (sl->flags & 1)? GNUTLS_X509_FMT_PEM : GNUTLS_X509_FMT_DER);
+        if (rc < 0)
+          log_info ("setting CA from file '%s' failed: %s\n",
+                    sl->d, gnutls_strerror (rc));
+      }
+
+    rc = gnutls_init (&sess->tls_session, GNUTLS_CLIENT);
+    if (rc < 0)
+      {
+        log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc));
+        err = gpg_error (GPG_ERR_GENERAL);
+        goto leave;
+      }
+    rc = gnutls_priority_set_direct (sess->tls_session,
+                                     tls_priority? tls_priority : "NORMAL",
+                                     &errpos);
+    if (rc < 0)
+      {
+        log_error ("gnutls_priority_set_direct failed at '%s': %s\n",
+                   errpos, gnutls_strerror (rc));
+        err = gpg_error (GPG_ERR_GENERAL);
+        goto leave;
+      }
+
+    rc = gnutls_credentials_set (sess->tls_session,
+                                 GNUTLS_CRD_CERTIFICATE, sess->certcred);
+    if (rc < 0)
+      {
+        log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc));
+        err = gpg_error (GPG_ERR_GENERAL);
+        goto leave;
+      }
+  }
+
+#else /*!HTTP_USE_GNUTLS*/
+  (void)tls_priority;
+#endif /*!HTTP_USE_GNUTLS*/
+
+  err = 0;
+
+#ifdef HTTP_USE_GNUTLS
+ leave:
+#endif /*HTTP_USE_GNUTLS*/
+  if (err)
+    http_session_release (sess);
+  else
+    *r_session = sess;
+
+  return err;
 }
 
 
+/* Release a session.  Take care not to release it while it is beeing
+   used by a http contect object.  */
+void
+http_session_release (http_session_t sess)
+{
+  if (!sess)
+    return;
+
+#ifdef HTTP_USE_GNUTLS
+  if (sess->tls_session)
+    gnutls_deinit (sess->tls_session);
+  if (sess->certcred)
+    gnutls_certificate_free_credentials (sess->certcred);
+  xfree (sess->servername);
+#endif /*HTTP_USE_GNUTLS*/
+
+  xfree (sess);
+}
+
 
 /* Start a HTTP retrieval and return on success in R_HD a context
    pointer for completing the the request and to wait for the
@@ -442,7 +596,7 @@ http_register_tls_callback ( gpg_error_t (*cb) (http_t, void *, int) )
 gpg_error_t
 http_open (http_t *r_hd, http_req_t reqtype, const char *url,
            const char *auth, unsigned int flags, const char *proxy,
-           void *tls_context, const char *srvtag, strlist_t headers)
+           http_session_t session, const char *srvtag, strlist_t headers)
 {
   gpg_error_t err;
   http_t hd;
@@ -458,7 +612,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
     return gpg_error_from_syserror ();
   hd->req_type = reqtype;
   hd->flags = flags;
-  hd->tls_context = tls_context;
+  hd->session = session;
 
   err = http_parse_uri (&hd->uri, url, 0);
   if (!err)
@@ -466,7 +620,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
 
   if (err)
     {
-      my_socket_unref (hd->sock);
+      my_socket_unref (hd->sock, NULL, NULL);
       if (hd->fp_read)
         es_fclose (hd->fp_read);
       if (hd->fp_write)
@@ -531,7 +685,7 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
   if (!hd->fp_write)
     {
       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
-      my_socket_unref (cookie->sock);
+      my_socket_unref (cookie->sock, NULL, NULL);
       xfree (cookie);
       goto leave;
     }
@@ -548,7 +702,7 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
   if (!hd->fp_read)
     {
       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
-      my_socket_unref (cookie->sock);
+      my_socket_unref (cookie->sock, NULL, NULL);
       xfree (cookie);
       goto leave;
     }
@@ -567,7 +721,7 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
         es_fclose (hd->fp_read);
       if (hd->fp_write)
         es_fclose (hd->fp_write);
-      my_socket_unref (hd->sock);
+      my_socket_unref (hd->sock, NULL, NULL);
       xfree (hd);
     }
   else
@@ -624,15 +778,15 @@ http_wait_response (http_t hd)
   if (!cookie)
     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
   cookie->sock = my_socket_ref (hd->sock);
-  if (hd->uri->use_tls)
-    cookie->tls_session = hd->tls_context;
+  cookie->session = hd->session;
+  cookie->use_tls = hd->uri->use_tls;
 
   hd->read_cookie = cookie;
   hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
   if (!hd->fp_read)
     {
       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
-      my_socket_unref (cookie->sock);
+      my_socket_unref (cookie->sock, NULL, NULL);
       xfree (cookie);
       hd->read_cookie = NULL;
       return err;
@@ -654,12 +808,13 @@ http_wait_response (http_t hd)
 gpg_error_t
 http_open_document (http_t *r_hd, const char *document,
                     const char *auth, unsigned int flags, const char *proxy,
-                    void *tls_context, const char *srvtag, strlist_t headers)
+                    http_session_t session,
+                    const char *srvtag, strlist_t headers)
 {
   gpg_error_t err;
 
   err = http_open (r_hd, HTTP_REQ_GET, document, auth, flags,
-                   proxy, tls_context, srvtag, headers);
+                   proxy, session, srvtag, headers);
   if (err)
     return err;
 
@@ -684,7 +839,7 @@ http_close (http_t hd, int keep_read_stream)
     es_onclose (hd->fp_write, 0, fp_onclose_notification, hd);
 
   /* Now we can close the streams.  */
-  my_socket_unref (hd->sock);
+  my_socket_unref (hd->sock, NULL, NULL);
   if (hd->fp_read && !keep_read_stream)
     es_fclose (hd->fp_read);
   if (hd->fp_write)
@@ -962,16 +1117,41 @@ remove_escapes (char *string)
 }
 
 
+/* If SPECIAL is NULL this function escapes in forms mode.  */
 static size_t
 escape_data (char *buffer, const void *data, size_t datalen,
              const char *special)
 {
+  int forms = !special;
   const unsigned char *s;
   size_t n = 0;
 
+  if (forms)
+    special = "%;?&=";
+
   for (s = data; datalen; s++, datalen--)
     {
-      if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
+      if (forms && *s == ' ')
+        {
+	  if (buffer)
+	    *buffer++ = '+';
+	  n++;
+        }
+      else if (forms && *s == '\n')
+        {
+	  if (buffer)
+	    memcpy (buffer, "%0D%0A", 6);
+	  n += 6;
+        }
+      else if (forms && *s == '\r' && datalen > 1 && s[1] == '\n')
+        {
+	  if (buffer)
+	    memcpy (buffer, "%0D%0A", 6);
+	  n += 6;
+          s++;
+          datalen--;
+        }
+      else if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
 	{
 	  if (buffer)
 	    *(unsigned char*)buffer++ = *s;
@@ -1003,7 +1183,8 @@ insert_escapes (char *buffer, const char *string,
    well as escaping of characters given in SPECIALS.  A common pattern
    for SPECIALS is "%;?&=". However it depends on the needs, for
    example "+" and "/: often needs to be escaped too.  Returns NULL on
-   failure and sets ERRNO. */
+   failure and sets ERRNO.  If SPECIAL is NULL a dedicated forms
+   encoding mode is used. */
 char *
 http_escape_string (const char *string, const char *specials)
 {
@@ -1024,7 +1205,8 @@ http_escape_string (const char *string, const char *specials)
    escaping as well as escaping of characters given in SPECIALS.  A
    common pattern for SPECIALS is "%;?&=".  However it depends on the
    needs, for example "+" and "/: often needs to be escaped too.
-   Returns NULL on failure and sets ERRNO. */
+   Returns NULL on failure and sets ERRNO.  If SPECIAL is NULL a
+   dedicated forms encoding mode is used. */
 char *
 http_escape_data (const void *data, size_t datalen, const char *specials)
 {
@@ -1042,7 +1224,6 @@ http_escape_data (const void *data, size_t datalen, const char *specials)
 }
 
 
-
 static uri_tuple_t
 parse_tuple (char *string)
 {
@@ -1089,7 +1270,6 @@ static gpg_error_t
 send_request (http_t hd, const char *auth,
 	      const char *proxy, const char *srvtag, strlist_t headers)
 {
-  gnutls_session_t tls_session;
   gpg_error_t err;
   const char *server;
   char *request, *p;
@@ -1100,16 +1280,44 @@ send_request (http_t hd, const char *auth,
   int sock;
   int hnf;
 
-  tls_session = hd->tls_context;
-  if (hd->uri->use_tls && !tls_session)
+  if (hd->uri->use_tls && !hd->session)
     {
-      log_error ("TLS requested but no GNUTLS context provided\n");
+      log_error ("TLS requested but no session object provided\n");
       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
     }
+#ifdef HTTP_USE_GNUTLS
+  if (hd->uri->use_tls && !hd->session->tls_session)
+    {
+      log_error ("TLS requested but no GNUTLS context available\n");
+      return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
+    }
+#endif /*HTTP_USE_GNUTLS*/
 
   server = *hd->uri->host ? hd->uri->host : "localhost";
   port = hd->uri->port ? hd->uri->port : 80;
 
+  /* Try to use SNI.  */
+#ifdef HTTP_USE_GNUTLS
+  if (hd->uri->use_tls)
+    {
+      int rc;
+
+      xfree (hd->session->servername);
+      hd->session->servername = xtrystrdup (server);
+      if (!hd->session->servername)
+        {
+          err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
+          return err;
+        }
+
+      rc = gnutls_server_name_set (hd->session->tls_session,
+                                   GNUTLS_NAME_DNS,
+                                   server, strlen (server));
+      if (rc < 0)
+        log_info ("gnutls_server_name_set failed: %s\n", gnutls_strerror (rc));
+    }
+#endif /*HTTP_USE_GNUTLS*/
+
   if ( (proxy && *proxy)
        || ( (hd->flags & HTTP_FLAG_TRY_PROXY)
             && (http_proxy = getenv (HTTP_PROXY_ENV))
@@ -1179,11 +1387,22 @@ send_request (http_t hd, const char *auth,
       int rc;
 
       my_socket_ref (hd->sock);
-      gnutls_transport_set_ptr (tls_session,
+#if GNUTLS_VERSION_NUMBER >= 0x030109
+      gnutls_transport_set_int (hd->session->tls_session, hd->sock->fd);
+#else
+      gnutls_transport_set_ptr (hd->session->tls_session,
                                 (gnutls_transport_ptr_t)(hd->sock->fd));
+#endif
+#ifdef USE_NPTH
+      gnutls_transport_set_pull_function (hd->session->tls_session,
+                                          my_npth_read);
+      gnutls_transport_set_push_function (hd->session->tls_session,
+                                          my_npth_write);
+#endif
+
       do
         {
-          rc = gnutls_handshake (tls_session);
+          rc = gnutls_handshake (hd->session->tls_session);
         }
       while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
       if (rc < 0)
@@ -1195,7 +1414,8 @@ send_request (http_t hd, const char *auth,
 
       if (tls_callback)
         {
-          err = tls_callback (hd, tls_session, 0);
+          hd->session->verify.done = 0;
+          err = tls_callback (hd, hd->session, 0);
           if (err)
             {
               log_info ("TLS connection authentication failed: %s\n",
@@ -1227,7 +1447,7 @@ send_request (http_t hd, const char *auth,
           myauth = hd->uri->auth;
         }
 
-      authstr = make_header_line ("Authorization: Basic %s", "\r\n",
+      authstr = make_header_line ("Authorization: Basic ", "\r\n",
                                   myauth, strlen (myauth));
       if (auth)
         xfree (myauth);
@@ -1281,6 +1501,7 @@ send_request (http_t hd, const char *auth,
       return err;
     }
 
+  /* log_debug ("request:\n%s\nEND request\n", request); */
 
   /* First setup estream so that we can write even the first line
      using estream.  This is also required for the sake of gnutls. */
@@ -1295,14 +1516,14 @@ send_request (http_t hd, const char *auth,
       }
     cookie->sock = my_socket_ref (hd->sock);
     hd->write_cookie = cookie;
-    if (hd->uri->use_tls)
-      cookie->tls_session = tls_session;
+    cookie->use_tls = hd->uri->use_tls;
+    cookie->session = hd->session;
 
     hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
     if (!hd->fp_write)
       {
         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
-        my_socket_unref (cookie->sock);
+        my_socket_unref (cookie->sock, NULL, NULL);
         xfree (cookie);
         hd->write_cookie = NULL;
       }
@@ -1491,8 +1712,8 @@ store_header (http_t hd, char *line)
 
 
 /* Return the header NAME from the last response.  The returned value
-   is valid as along as HD has not been closed and no othe request has
-   been send. If the header was not found, NULL is returned.  Name
+   is valid as along as HD has not been closed and no other request
+   has been send. If the header was not found, NULL is returned.  NAME
    must be canonicalized, that is the first letter of each dash
    delimited part must be uppercase and all other letters lowercase.  */
 const char *
@@ -1507,6 +1728,29 @@ http_get_header (http_t hd, const char *name)
 }
 
 
+/* Return a newly allocated and NULL terminated array with pointers to
+   header names.  The array must be released with xfree() and its
+   content is only values as long as no other request has been
+   send.  */
+const char **
+http_get_header_names (http_t hd)
+{
+  const char **array;
+  size_t n;
+  header_t h;
+
+  for (n=0, h = hd->headers; h; h = h->next)
+    n++;
+  array = xtrycalloc (n+1, sizeof *array);
+  if (array)
+    {
+      for (n=0, h = hd->headers; h; h = h->next)
+        array[n++] = h->name;
+    }
+
+  return array;
+}
+
 
 /*
  * Parse the response from a server.
@@ -1960,10 +2204,10 @@ cookie_read (void *cookie, void *buffer, size_t size)
     }
 
 #ifdef HTTP_USE_GNUTLS
-  if (c->tls_session)
+  if (c->use_tls && c->session && c->session->tls_session)
     {
     again:
-      nread = gnutls_record_recv (c->tls_session, buffer, size);
+      nread = gnutls_record_recv (c->session->tls_session, buffer, size);
       if (nread < 0)
         {
           if (nread == GNUTLS_E_INTERRUPTED)
@@ -2014,18 +2258,20 @@ cookie_read (void *cookie, void *buffer, size_t size)
 
 /* Write handler for estream.  */
 static ssize_t
-cookie_write (void *cookie, const void *buffer, size_t size)
+cookie_write (void *cookie, const void *buffer_arg, size_t size)
 {
+  const char *buffer = buffer_arg;
   cookie_t c = cookie;
   int nwritten = 0;
 
 #ifdef HTTP_USE_GNUTLS
-  if (c->tls_session)
+  if (c->use_tls && c->session && c->session->tls_session)
     {
       int nleft = size;
       while (nleft > 0)
         {
-          nwritten = gnutls_record_send (c->tls_session, buffer, nleft);
+          nwritten = gnutls_record_send (c->session->tls_session,
+                                         buffer, nleft);
           if (nwritten <= 0)
             {
               if (nwritten == GNUTLS_E_INTERRUPTED)
@@ -2063,6 +2309,18 @@ cookie_write (void *cookie, const void *buffer, size_t size)
   return nwritten;
 }
 
+
+#ifdef HTTP_USE_GNUTLS
+/* Wrapper for gnutls_bye used by my_socket_unref.  */
+static void
+send_gnutls_bye (void *opaque)
+{
+  gnutls_session_t tls_session = opaque;
+
+  gnutls_bye (tls_session, GNUTLS_SHUT_RDWR);
+}
+#endif /*HTTP_USE_GNUTLS*/
+
 /* Close handler for estream.  */
 static int
 cookie_close (void *cookie)
@@ -2073,182 +2331,117 @@ cookie_close (void *cookie)
     return 0;
 
 #ifdef HTTP_USE_GNUTLS
-  if (c->tls_session && !c->keep_socket)
-    {
-      gnutls_bye (c->tls_session, GNUTLS_SHUT_RDWR);
-      my_socket_unref (c->sock);
-    }
+  if (c->use_tls && c->session && c->session->tls_session)
+    my_socket_unref (c->sock, send_gnutls_bye, c->session->tls_session);
+  else
 #endif /*HTTP_USE_GNUTLS*/
-  if (c->sock && !c->keep_socket)
-    my_socket_unref (c->sock);
+    if (c->sock)
+      my_socket_unref (c->sock, NULL, NULL);
 
   xfree (c);
   return 0;
 }
 
 
-

-/**** Test code ****/
-#ifdef TEST
 
-#ifdef HTTP_USE_GNUTLS
-static gpg_error_t
-verify_callback (http_t hd, void *tls_context, int reserved)
+

+/* Verify the credentials of the server.  Returns 0 on success and
+   store the result in the session object.  */
+gpg_error_t
+http_verify_server_credentials (http_session_t sess)
 {
-  log_info ("verification of certificates skipped\n");
-  return 0;
-}
-#endif /*HTTP_USE_GNUTLS*/
+#ifdef HTTP_USE_GNUTLS
+  static const char const errprefix[] = "TLS verification of peer failed";
+  int rc;
+  unsigned int status;
+  const char *hostname;
+  const gnutls_datum_t *certlist;
+  unsigned int certlistlen;
+  gnutls_x509_crt_t cert;
 
+  sess->verify.done = 1;
+  sess->verify.status = 0;
+  sess->verify.rc = GNUTLS_E_CERTIFICATE_ERROR;
 
-/* static void */
-/* my_gnutls_log (int level, const char *text) */
-/* { */
-/*   fprintf (stderr, "gnutls:L%d: %s", level, text); */
-/* } */
+  if (gnutls_certificate_type_get (sess->tls_session) != GNUTLS_CRT_X509)
+    {
+      log_error ("%s: %s\n", errprefix, "not an X.509 certificate");
+      sess->verify.rc = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
+      return gpg_error (GPG_ERR_GENERAL);
+    }
 
-int
-main (int argc, char **argv)
-{
-  int rc;
-  parsed_uri_t uri;
-  uri_tuple_t r;
-  http_t hd;
-  int c;
-  gnutls_session_t tls_session = NULL;
-#ifdef HTTP_USE_GNUTLS
-  gnutls_certificate_credentials certcred;
-  const int certprio[] = { GNUTLS_CRT_X509, 0 };
-#endif /*HTTP_USE_GNUTLS*/
-  header_t hdr;
+  rc = gnutls_certificate_verify_peers2 (sess->tls_session, &status);
+  if (rc)
+    {
+      log_error ("%s: %s\n", errprefix, gnutls_strerror (rc));
+      return gpg_error (GPG_ERR_GENERAL);
+    }
+  if (status)
+    {
+      log_error ("%s: status=0x%04x\n", errprefix, status);
+      sess->verify.status = status;
+      return gpg_error (GPG_ERR_GENERAL);
+    }
 
-  es_init ();
-  log_set_prefix ("http-test", 1 | 4);
-  if (argc == 1)
+  hostname = sess->servername;
+  if (!hostname || !strchr (hostname, '.'))
     {
-      /*start_server (); */
-      return 0;
+      log_error ("%s: %s\n", errprefix, "hostname missing");
+      return gpg_error (GPG_ERR_GENERAL);
     }
 
-  if (argc != 2)
+  certlist = gnutls_certificate_get_peers (sess->tls_session, &certlistlen);
+  if (!certlistlen)
     {
-      fprintf (stderr, "usage: http-test uri\n");
-      return 1;
+      log_error ("%s: %s\n", errprefix, "server did not send a certificate");
+      return gpg_error (GPG_ERR_GENERAL);
     }
-  argc--;
-  argv++;
 
-#ifdef HTTP_USE_GNUTLS
-  rc = gnutls_global_init ();
-  if (rc)
-    log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc));
-  rc = gnutls_certificate_allocate_credentials (&certcred);
-  if (rc)
-    log_error ("gnutls_certificate_allocate_credentials failed: %s\n",
-               gnutls_strerror (rc));
-/*   rc = gnutls_certificate_set_x509_trust_file */
-/*     (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */
-/*   if (rc) */
-/*     log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */
-/*                gnutls_strerror (rc)); */
-  rc = gnutls_init (&tls_session, GNUTLS_CLIENT);
-  if (rc)
-    log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc));
-  rc = gnutls_set_default_priority (tls_session);
-  if (rc)
-    log_error ("gnutls_set_default_priority failed: %s\n",
-               gnutls_strerror (rc));
-  rc = gnutls_certificate_type_set_priority (tls_session, certprio);
-  if (rc)
-    log_error ("gnutls_certificate_type_set_priority failed: %s\n",
-               gnutls_strerror (rc));
-  rc = gnutls_credentials_set (tls_session, GNUTLS_CRD_CERTIFICATE, certcred);
-  if (rc)
-    log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc));
-/*   gnutls_global_set_log_function (my_gnutls_log); */
-/*   gnutls_global_set_log_level (4); */
+  /* log_debug ("Server sent %u certs\n", certlistlen); */
+  /* { */
+  /*   int i; */
+  /*   char fname[50]; */
+  /*   FILE *fp; */
 
-  http_register_tls_callback (verify_callback);
-#endif /*HTTP_USE_GNUTLS*/
+  /*   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 = http_parse_uri (&uri, *argv, 1);
-  if (rc)
+  rc = gnutls_x509_crt_init (&cert);
+  if (rc < 0)
     {
-      log_error ("'%s': %s\n", *argv, gpg_strerror (rc));
-      return 1;
+      return gpg_error (GPG_ERR_GENERAL);
     }
 
-  printf ("Scheme: %s\n", uri->scheme);
-  if (uri->opaque)
-    printf ("Value : %s\n", uri->path);
-  else
+  rc = gnutls_x509_crt_import (cert, &certlist[0], GNUTLS_X509_FMT_DER);
+  if (rc < 0)
     {
-      printf ("Auth  : %s\n", uri->auth? uri->auth:"[none]");
-      printf ("Host  : %s\n", uri->host);
-      printf ("Port  : %u\n", uri->port);
-      printf ("Path  : %s\n", uri->path);
-      for (r = uri->params; r; r = r->next)
-        {
-          printf ("Params: %s", r->name);
-          if (!r->no_value)
-            {
-              printf ("=%s", r->value);
-              if (strlen (r->value) != r->valuelen)
-                printf (" [real length=%d]", (int) r->valuelen);
-            }
-          putchar ('\n');
-        }
-      for (r = uri->query; r; r = r->next)
-        {
-          printf ("Query : %s", r->name);
-          if (!r->no_value)
-            {
-              printf ("=%s", r->value);
-              if (strlen (r->value) != r->valuelen)
-                printf (" [real length=%d]", (int) r->valuelen);
-            }
-          putchar ('\n');
-        }
+      log_error ("%s: %s: %s\n", errprefix, "error importing certificate",
+                 gnutls_strerror (rc));
+      gnutls_x509_crt_deinit (cert);
+      return gpg_error (GPG_ERR_GENERAL);
     }
-  http_release_parsed_uri (uri);
-  uri = NULL;
 
-  rc = http_open_document (&hd, *argv, NULL, 0, NULL, tls_session, NULL, NULL);
-  if (rc)
-    {
-      log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc));
-      return 1;
-    }
-  log_info ("open_http_document succeeded; status=%u\n",
-            http_get_status_code (hd));
-  for (hdr = hd->headers; hdr; hdr = hdr->next)
-    printf ("HDR: %s: %s\n", hdr->name, hdr->value);
-  switch (http_get_status_code (hd))
+  if (!gnutls_x509_crt_check_hostname (cert, hostname))
     {
-    case 200:
-      while ((c = es_getc (http_get_read_ptr (hd))) != EOF)
-        putchar (c);
-      break;
-    case 301:
-    case 302:
-      printf ("Redirected to '%s'\n", http_get_header (hd, "Location"));
-      break;
+      log_error ("%s: %s\n", errprefix, "hostname does not match");
+      gnutls_x509_crt_deinit (cert);
+      return gpg_error (GPG_ERR_GENERAL);
     }
-  http_close (hd, 0);
-
-#ifdef HTTP_USE_GNUTLS
-  gnutls_deinit (tls_session);
-  gnutls_certificate_free_credentials (certcred);
-  gnutls_global_deinit ();
-#endif /*HTTP_USE_GNUTLS*/
 
-  return 0;
+  gnutls_x509_crt_deinit (cert);
+  sess->verify.rc = 0;
+  return 0;  /* Verification succeeded.  */
+#else /*!HTTP_USE_GNUTLS*/
+  (void)sess;
+  return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+#endif
 }
-#endif /*TEST*/
-
-
-/*
-Local Variables:
-compile-command: "gcc -I.. -I../gl -DTEST -DHAVE_CONFIG_H -Wall -O2 -g -o http-test http.c -L. -lcommon -lgcrypt -lpth -lgnutls"
-End:
-*/
diff --git a/common/http.h b/common/http.h
index 224128b..e38fadc 100644
--- a/common/http.h
+++ b/common/http.h
@@ -82,10 +82,20 @@ enum
     HTTP_FLAG_IGNORE_IPv6 = 128  /* Do not use IPv6.  */
   };
 
+
+struct http_session_s;
+typedef struct http_session_s *http_session_t;
+
 struct http_context_s;
 typedef struct http_context_s *http_t;
 
-void http_register_tls_callback (gpg_error_t (*cb) (http_t, void *, int));
+void http_register_tls_callback (gpg_error_t (*cb)(http_t,http_session_t,int));
+void http_register_tls_ca (const char *fname);
+
+gpg_error_t http_session_new (http_session_t *r_session,
+                              const char *tls_priority);
+void http_session_release (http_session_t sess);
+
 
 gpg_error_t http_parse_uri (parsed_uri_t *ret_uri, const char *uri,
                             int no_scheme_check);
@@ -101,7 +111,7 @@ gpg_error_t http_open (http_t *r_hd, http_req_t reqtype,
                        const char *auth,
                        unsigned int flags,
                        const char *proxy,
-                       void *tls_context,
+                       http_session_t session,
                        const char *srvtag,
                        strlist_t headers);
 
@@ -116,7 +126,7 @@ gpg_error_t http_open_document (http_t *r_hd,
                                 const char *auth,
                                 unsigned int flags,
                                 const char *proxy,
-                                void *tls_context,
+                                http_session_t session,
                                 const char *srvtag,
                                 strlist_t headers);
 
@@ -124,6 +134,8 @@ estream_t http_get_read_ptr (http_t hd);
 estream_t http_get_write_ptr (http_t hd);
 unsigned int http_get_status_code (http_t hd);
 const char *http_get_header (http_t hd, const char *name);
+const char **http_get_header_names (http_t hd);
+gpg_error_t http_verify_server_credentials (http_session_t sess);
 
 char *http_escape_string (const char *string, const char *specials);
 char *http_escape_data (const void *data, size_t datalen, const char *specials);
diff --git a/common/t-http.c b/common/t-http.c
new file mode 100644
index 0000000..f515287
--- /dev/null
+++ b/common/t-http.c
@@ -0,0 +1,269 @@
+/* t-http.c
+ * Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, 2009, 2010,
+ *               2011 Free Software Foundation, Inc.
+ * Copyright (C) 2014 Werner Koch
+ *
+ * This file is part of GnuPG.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either
+ *
+ *   - the GNU Lesser General Public License as published by the Free
+ *     Software Foundation; either version 3 of the License, or (at
+ *     your option) any later version.
+ *
+ * or
+ *
+ *   - the GNU General Public License as published by the Free
+ *     Software Foundation; either version 2 of the License, or (at
+ *     your option) any later version.
+ *
+ * or both in parallel, as here.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "util.h"
+#include "logging.h"
+#include "http.h"
+
+
+#ifdef HTTP_USE_GNUTLS
+# include <gnutls/gnutls.h>  /* For init, logging, and deinit.  */
+#endif /*HTTP_USE_GNUTLS*/
+
+
+
+/* static void */
+/* read_dh_params (const char *fname) */
+/* { */
+/*   gpg_error_t err; */
+/*   int rc; */
+/*   FILE *fp; */
+/*   struct stat st; */
+/*   char *buf; */
+/*   size_t buflen; */
+/*   gnutls_datum_t datum; */
+
+/*   fp = fopen (fname, "rb"); */
+/*   if (!fp) */
+/*     { */
+/*       err = gpg_error_from_syserror (); */
+/*       log_fatal ("can't open '%s': %s\n", fname, gpg_strerror (err)); */
+/*     } */
+
+/*   if (fstat (fileno(fp), &st)) */
+/*     { */
+/*       err = gpg_error_from_syserror (); */
+/*       log_fatal ("can't stat '%s': %s\n", fname, gpg_strerror (err)); */
+/*     } */
+
+/*   buflen = st.st_size; */
+/*   buf = xmalloc (buflen+1); */
+/*   if (fread (buf, buflen, 1, fp) != 1) */
+/*     { */
+/*       err = gpg_error_from_syserror (); */
+/*       log_fatal ("error reading '%s': %s\n", fname, gpg_strerror (err)); */
+/*     } */
+/*   fclose (fp); */
+
+/*   datum.size = buflen; */
+/*   datum.data = buf; */
+
+/*   rc = gnutls_dh_params_import_pkcs3 (dh_params, &datum, GNUTLS_X509_FMT_PEM); */
+/*   if (rc < 0) */
+/*     log_fatal ("gnutls_dh_param_import failed: %s\n", gnutls_strerror (rc)); */
+
+/*   xfree (buf); */
+/* } */
+
+
+
+static gpg_error_t
+verify_callback (http_t hd, http_session_t session, int reserved)
+{
+  (void)hd;
+  (void)reserved;
+  return http_verify_server_credentials (session);
+}
+
+
+static void
+my_gnutls_log (int level, const char *text)
+{
+  fprintf (stderr, "gnutls:L%d: %s", level, text);
+}
+
+
+/* Prepend FNAME with the srcdir environment variable's value and
+   return an allocated filename. */
+static char *
+prepend_srcdir (const char *fname)
+{
+  static const char *srcdir;
+  char *result;
+
+  if (!srcdir && !(srcdir = getenv ("srcdir")))
+    srcdir = ".";
+
+  result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1);
+  strcpy (result, srcdir);
+  strcat (result, "/");
+  strcat (result, fname);
+  return result;
+}
+
+
+int
+main (int argc, char **argv)
+{
+  gpg_error_t err;
+  int rc;
+  parsed_uri_t uri;
+  uri_tuple_t r;
+  http_t hd;
+  int c;
+  http_session_t session = NULL;
+
+  es_init ();
+  log_set_prefix ("t-http", 1 | 4);
+  if (argc != 2)
+    {
+      fprintf (stderr, "usage: t-http uri\n");
+      return 1;
+    }
+  argc--;
+  argv++;
+
+#ifdef HTTP_USE_GNUTLS
+  rc = gnutls_global_init ();
+  if (rc)
+    log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc));
+
+  http_register_tls_callback (verify_callback);
+  http_register_tls_ca (prepend_srcdir ("tls-ca.pem"));
+
+  err = http_session_new (&session, NULL);
+  if (err)
+    log_error ("http_session_new failed: %s\n", gpg_strerror (err));
+
+  /* rc = gnutls_dh_params_init(&dh_params); */
+  /* if (rc) */
+  /*   log_error ("gnutls_dh_params_init failed: %s\n", gnutls_strerror (rc)); */
+  /* read_dh_params ("dh_param.pem"); */
+
+  /* rc = gnutls_certificate_set_x509_trust_file */
+  /*   (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */
+  /* if (rc) */
+  /*   log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */
+  /*              gnutls_strerror (rc)); */
+
+  /* gnutls_certificate_set_dh_params (certcred, dh_params); */
+
+  gnutls_global_set_log_function (my_gnutls_log);
+  /* gnutls_global_set_log_level (2); */
+
+#endif /*HTTP_USE_GNUTLS*/
+
+  rc = http_parse_uri (&uri, *argv, 1);
+  if (rc)
+    {
+      log_error ("'%s': %s\n", *argv, gpg_strerror (rc));
+      return 1;
+    }
+
+  printf ("Scheme: %s\n", uri->scheme);
+  if (uri->opaque)
+    printf ("Value : %s\n", uri->path);
+  else
+    {
+      printf ("Auth  : %s\n", uri->auth? uri->auth:"[none]");
+      printf ("Host  : %s\n", uri->host);
+      printf ("Port  : %u\n", uri->port);
+      printf ("Path  : %s\n", uri->path);
+      for (r = uri->params; r; r = r->next)
+        {
+          printf ("Params: %s", r->name);
+          if (!r->no_value)
+            {
+              printf ("=%s", r->value);
+              if (strlen (r->value) != r->valuelen)
+                printf (" [real length=%d]", (int) r->valuelen);
+            }
+          putchar ('\n');
+        }
+      for (r = uri->query; r; r = r->next)
+        {
+          printf ("Query : %s", r->name);
+          if (!r->no_value)
+            {
+              printf ("=%s", r->value);
+              if (strlen (r->value) != r->valuelen)
+                printf (" [real length=%d]", (int) r->valuelen);
+            }
+          putchar ('\n');
+        }
+    }
+  http_release_parsed_uri (uri);
+  uri = NULL;
+
+  rc = http_open_document (&hd, *argv, NULL, 0, NULL, session, NULL, NULL);
+  if (rc)
+    {
+      log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc));
+      return 1;
+    }
+  log_info ("open_http_document succeeded; status=%u\n",
+            http_get_status_code (hd));
+
+  {
+    const char **names;
+    int i;
+
+    names = http_get_header_names (hd);
+    if (!names)
+      log_fatal ("http_get_header_names failed: %s\n",
+                 gpg_strerror (gpg_error_from_syserror ()));
+    for (i = 0; names[i]; i++)
+      printf ("HDR: %s: %s\n", names[i], http_get_header (hd, names[i]));
+    xfree (names);
+  }
+
+  switch (http_get_status_code (hd))
+    {
+    case 200:
+    case 400:
+    case 401:
+    case 403:
+    case 404:
+      while ((c = es_getc (http_get_read_ptr (hd))) != EOF)
+        putchar (c);
+      break;
+    case 301:
+    case 302:
+      printf ("Redirected to '%s'\n", http_get_header (hd, "Location"));
+      break;
+    }
+  http_close (hd, 0);
+
+  http_session_release (session);
+#ifdef HTTP_USE_GNUTLS
+  gnutls_global_deinit ();
+#endif /*HTTP_USE_GNUTLS*/
+
+  return 0;
+}
diff --git a/common/tls-ca.pem b/common/tls-ca.pem
new file mode 100644
index 0000000..c296466
--- /dev/null
+++ b/common/tls-ca.pem
@@ -0,0 +1,30 @@
+Issuer ...: /CN=UTN-USERFirst-Hardware/OU=http:\x2f\x2fwww.usertrust.com/O=The USERTRUST Network/L=Salt Lake City/ST=UT/C=US
+Serial ...: 44BE0C8B500024B411D3362AFE650AFD
+Subject ..: /CN=UTN-USERFirst-Hardware/OU=http:\x2f\x2fwww.usertrust.com/O=The USERTRUST Network/L=Salt Lake City/ST=UT/C=US
+
+-----BEGIN CERTIFICATE-----
+MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB
+lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
+Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
+SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG
+A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe
+MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v
+d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh
+cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn
+0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ
+M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a
+MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd
+oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI
+DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy
+oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0
+dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy
+bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF
+BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
+//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli
+CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE
+CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t
+3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS
+KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA==
+-----END CERTIFICATE-----
diff --git a/configure.ac b/configure.ac
index 19c9816..21f5fb6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -58,6 +58,8 @@ NEED_KSBA_VERSION=1.2.0
 NEED_NPTH_API=1
 NEED_NPTH_VERSION=0.91
 
+NEED_GNUTLS_VERSION=3.0
+
 
 development_version=mym4_isgit
 PACKAGE=$PACKAGE_NAME
@@ -912,6 +914,26 @@ else
 ***]])
 fi
 
+#
+# Check whether GNUTLS is available
+#
+PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= $NEED_GNUTLS_VERSION],
+                               [have_gnutls=yes],
+                               [have_gnutls=no])
+if test "$have_gnutls" = "yes"; then
+  AC_SUBST([LIBGNUTLS_CFLAGS])
+  AC_SUBST([LIBGNUTLS_LIBS])
+  AC_DEFINE(HTTP_USE_GNUTLS, 1, [Enable GNUTLS support in http.c])
+else
+  tmp=$(echo "$LIBGNUTLS_PKG_ERRORS" | tr '\n' '\v' | sed 's/\v/\n*** /g')
+  AC_MSG_WARN([[
+***
+*** Building without GNUTLS - no TLS access to keyservers.
+***
+*** $tmp]])
+fi
+
+
 
 AC_MSG_NOTICE([checking for networking options])
 
@@ -1867,6 +1889,8 @@ echo "
         Use standard socket: $use_standard_socket
         Dirmngr auto start:  $dirmngr_auto_start
         Readline support:    $gnupg_cv_have_readline
+        DNS SRV support:     $use_dns_srv
+        TLS support:         $have_gnutls
 "
 if test x"$use_regex" != xyes ; then
 echo "
diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am
index 7c43165..b5bef45 100644
--- a/dirmngr/Makefile.am
+++ b/dirmngr/Makefile.am
@@ -60,8 +60,10 @@ dirmngr_SOURCES += ldap-wrapper-ce.c  dirmngr_ldap.c
 endif
 
 
-dirmngr_LDADD = $(libcommonpth) ../gl/libgnu.a $(DNSLIBS) $(LIBASSUAN_LIBS) \
-	$(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(NPTH_LIBS) $(LIBINTL) $(LIBICONV)
+dirmngr_LDADD = $(libcommontlsnpth) $(libcommonpth) \
+        ../gl/libgnu.a $(DNSLIBS) $(LIBASSUAN_LIBS) \
+	$(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(NPTH_LIBS) \
+	$(LIBGNUTLS_LIBS) $(LIBINTL) $(LIBICONV)
 if !USE_LDAPWRAPPER
 dirmngr_LDADD += $(LDAPLIBS)
 endif
@@ -79,8 +81,7 @@ endif
 dirmngr_client_SOURCES = dirmngr-client.c
 dirmngr_client_LDADD = $(libcommon) no-libgcrypt.o \
 	                ../gl/libgnu.a $(LIBASSUAN_LIBS) \
-	               $(GPG_ERROR_LIBS) $(LIBINTL) \
-                       $(LIBICONV)
+	               $(GPG_ERROR_LIBS) $(NETLIBS) $(LIBINTL) $(LIBICONV)
 dirmngr_client_LDFLAGS = $(extra_bin_ldflags)
 
 

commit 84289e85c72ae58c321dfdb96816700a6b7f7122
Author: Werner Koch <wk at gnupg.org>
Date:   Fri May 2 08:06:10 2014 +0200

    common: Cleanup the use of USE_NPTH and HAVE_NPTH macros.
    
    * configure.ac (HAVE_NPTH): New ac_define.
    * common/estream.c: Use USE_NPTH instead of HAVE_NPTH.
    * common/http.c: Ditto.  Replace remaining calls to pth by npth calls.
    (connect_server): Remove useless _().
    * common/exechelp-posix.c, common/exechelp-w32.c
    * common/exechelp-w32ce.c: Use HAVE_PTH to include npth.h.
    * common/init.c (_init_common_subsystems): Remove call to pth_init.
    * common/sysutils.c (gnupg_sleep): Use npth_sleep.
    * scd/ccid-driver.c (my_sleep): Ditto.
    --
    
    USE_NPTH is used in case were we may build with and without nPth.  The
    missing definition HAVE_NPTH didn't allowed us to build outher sources
    with nPTh support.

diff --git a/common/estream.c b/common/estream.c
index 34726a3..3f924ab 100644
--- a/common/estream.c
+++ b/common/estream.c
@@ -162,7 +162,7 @@ typedef void (*func_free_t) (void *mem);
 

 /* Primitive system I/O.  */
 
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
 # define ESTREAM_SYS_READ  do_npth_read
 # define ESTREAM_SYS_WRITE do_npth_write
 # define ESTREAM_SYS_YIELD() npth_usleep (0)
@@ -197,7 +197,7 @@ struct estream_internal
   unsigned char buffer[BUFFER_BLOCK_SIZE];
   unsigned char unread_buffer[BUFFER_UNREAD_SIZE];
 
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
   npth_mutex_t lock;		 /* Lock. */
 #endif
 
@@ -242,7 +242,7 @@ static int custom_std_fds[3];
 static unsigned char custom_std_fds_valid[3];
 
 /* A lock object for the estream list and the custom_std_fds array.  */
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
 static npth_mutex_t estream_list_lock;
 #endif
 
@@ -358,7 +358,7 @@ map_w32_to_errno (DWORD w32_err)
 static int
 init_stream_lock (estream_t ES__RESTRICT stream)
 {
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
   int rc;
 
   if (!stream->intern->samethread)
@@ -380,7 +380,7 @@ init_stream_lock (estream_t ES__RESTRICT stream)
 static void
 lock_stream (estream_t ES__RESTRICT stream)
 {
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
   if (!stream->intern->samethread)
     {
       dbg_lock_1 ("enter lock_stream for %p\n", stream);
@@ -396,7 +396,7 @@ lock_stream (estream_t ES__RESTRICT stream)
 static int
 trylock_stream (estream_t ES__RESTRICT stream)
 {
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
   int rc;
 
   if (!stream->intern->samethread)
@@ -418,7 +418,7 @@ trylock_stream (estream_t ES__RESTRICT stream)
 static void
 unlock_stream (estream_t ES__RESTRICT stream)
 {
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
   if (!stream->intern->samethread)
     {
       dbg_lock_1 ("enter unlock_stream for %p\n", stream);
@@ -434,7 +434,7 @@ unlock_stream (estream_t ES__RESTRICT stream)
 static int
 init_list_lock (void)
 {
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
   int rc;
 
   dbg_lock_0 ("enter init_list_lock\n");
@@ -450,7 +450,7 @@ init_list_lock (void)
 static void
 lock_list (void)
 {
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
   dbg_lock_0 ("enter lock_list\n");
   npth_mutex_lock (&estream_list_lock);
   dbg_lock_0 ("leave lock_list\n");
@@ -461,7 +461,7 @@ lock_list (void)
 static void
 unlock_list (void)
 {
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
   dbg_lock_0 ("enter unlock_list\n");
   npth_mutex_unlock (&estream_list_lock);
   dbg_lock_0 ("leave unlock_list\n");
@@ -548,7 +548,7 @@ do_list_remove (estream_t stream, int with_locked_list)
  * write, assuming that we do I/O on a plain file where the operation
  * can't block.  FIXME:  Is this still needed for npth?
  */
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
 static int
 do_npth_read (int fd, void *buffer, size_t size)
 {
@@ -574,7 +574,7 @@ do_npth_write (int fd, const void *buffer, size_t size)
   return npth_write (fd, buffer, size);
 # endif /* !HAVE_W32_SYSTEM*/
 }
-#endif /*HAVE_NPTH*/
+#endif /*USE_NPTH*/
 
 

 
@@ -1125,7 +1125,7 @@ es_func_w32_read (void *cookie, void *buffer, size_t size)
     {
       do
         {
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
           /* Note: Our pth_read actually uses HANDLE!
              FIXME: Check  whether this is the case for npth. */
           bytes_read = npth_read ((int)w32_cookie->hd, buffer, size);
@@ -1171,7 +1171,7 @@ es_func_w32_write (void *cookie, const void *buffer, size_t size)
     {
       do
         {
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
           /* Note: Our pth_write actually uses HANDLE! */
           bytes_written = npth_write ((int)w32_cookie->hd, buffer, size);
 #else
diff --git a/common/exechelp-posix.c b/common/exechelp-posix.c
index 1290cfd..249d38d 100644
--- a/common/exechelp-posix.c
+++ b/common/exechelp-posix.c
@@ -50,7 +50,7 @@
 #undef USE_NPTH
 #endif
 
-#ifdef USE_NPTH
+#ifdef HAVE_NPTH
 #include <npth.h>
 #endif
 #include <sys/wait.h>
diff --git a/common/exechelp-w32.c b/common/exechelp-w32.c
index 61193ed..7bcd79b 100644
--- a/common/exechelp-w32.c
+++ b/common/exechelp-w32.c
@@ -50,7 +50,7 @@
 #undef USE_NPTH
 #endif
 
-#ifdef USE_NPTH
+#ifdef HAVE_NPTH
 #include <npth.h>
 #endif
 
diff --git a/common/exechelp-w32ce.c b/common/exechelp-w32ce.c
index 886d517..cca55c8 100644
--- a/common/exechelp-w32ce.c
+++ b/common/exechelp-w32ce.c
@@ -50,7 +50,7 @@
 #undef USE_NPTH
 #endif
 
-#ifdef USE_NPTH
+#ifdef HAVE_NPTH
 #include <npth.h>
 #endif
 
diff --git a/common/http.c b/common/http.c
index 5410141..11a7130 100644
--- a/common/http.c
+++ b/common/http.c
@@ -74,15 +74,13 @@
 #endif /*!HAVE_W32_SYSTEM*/
 
 #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth.  */
-# undef HAVE_NPTH
 # undef USE_NPTH
 #endif
 
-#ifdef HAVE_NPTH
+#ifdef USE_NPTH
 # include <npth.h>
 #endif
 
-
 #ifdef HTTP_USE_GNUTLS
 # include <gnutls/gnutls.h>
 /* For non-understandable reasons GNUTLS dropped the _t suffix from
@@ -94,7 +92,7 @@ typedef gnutls_transport_ptr gnutls_transport_ptr_t;
 #endif /*HTTP_USE_GNUTLS*/
 
 #ifdef TEST
-#undef USE_DNS_SRV
+# undef USE_DNS_SRV
 #endif
 
 #include "util.h"
@@ -119,10 +117,10 @@ struct srventry
 #endif/*!USE_DNS_SRV*/
 
 
-#ifdef HAVE_NPTH
-# define my_select(a,b,c,d,e)  pth_select ((a), (b), (c), (d), (e))
-# define my_connect(a,b,c)     pth_connect ((a), (b), (c))
-# define my_accept(a,b,c)      pth_accept ((a), (b), (c))
+#ifdef USE_NPTH
+# define my_select(a,b,c,d,e)  npth_select ((a), (b), (c), (d), (e))
+# define my_connect(a,b,c)     npth_connect ((a), (b), (c))
+# define my_accept(a,b,c)      npth_accept ((a), (b), (c))
 #else
 # define my_select(a,b,c,d,e)  select ((a), (b), (c), (d), (e))
 # define my_connect(a,b,c)     connect ((a), (b), (c))
@@ -359,8 +357,9 @@ my_socket_unref (my_socket_t so)
 /* #define my_socket_unref(a) _my_socket_unref ((a),__LINE__) */
 
 
+

 /* This notification function is called by estream whenever stream is
-   closed.  Its purpose is to mark the the closing in the handle so
+   closed.  Its purpose is to mark the closing in the handle so
    that a http_close won't accidentally close the estream.  The function
    http_close removes this notification so that it won't be called if
    http_close was used before an es_fclose.  */
@@ -1835,7 +1834,7 @@ connect_server (const char *server, unsigned short port,
       sock = socket (host->h_addrtype, SOCK_STREAM, 0);
       if (sock == -1)
         {
-          log_error (_("error creating socket: %s\n"), strerror (errno));
+          log_error ("error creating socket: %s\n", strerror (errno));
           xfree (serverlist);
           return -1;
         }
@@ -1879,7 +1878,7 @@ connect_server (const char *server, unsigned short port,
 #ifdef HAVE_W32_SYSTEM
       log_error ("can't connect to '%s': %s%sec=%d\n",
                    server,
-                   hostfound? "":_("host not found"),
+                   hostfound? "":"host not found",
                    hostfound? "":" - ", (int)WSAGetLastError());
 #else
       log_error ("can't connect to '%s': %s\n",
@@ -1906,16 +1905,16 @@ write_server (int sock, const char *data, size_t length)
   nleft = length;
   while (nleft > 0)
     {
-#if defined(HAVE_W32_SYSTEM) && !defined(HAVE_NPTH)
+#if defined(HAVE_W32_SYSTEM) && !defined(USE_NPTH)
       nwritten = send (sock, data, nleft, 0);
       if ( nwritten == SOCKET_ERROR )
         {
           log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
           return gpg_error (GPG_ERR_NETWORK);
         }
-#else /*!HAVE_W32_SYSTEM || HAVE_NPTH*/
-# ifdef HAVE_NPTH
-      nwritten = pth_write (sock, data, nleft);
+#else /*!HAVE_W32_SYSTEM || USE_NPTH*/
+# ifdef USE_NPTH
+      nwritten = npth_write (sock, data, nleft);
 # else
       nwritten = write (sock, data, nleft);
 # endif
@@ -1935,7 +1934,7 @@ write_server (int sock, const char *data, size_t length)
 	  log_info ("network write failed: %s\n", strerror (errno));
 	  return gpg_error_from_syserror ();
 	}
-#endif /*!HAVE_W32_SYSTEM || HAVE_NPTH*/
+#endif /*!HAVE_W32_SYSTEM || USE_NPTH*/
       nleft -= nwritten;
       data += nwritten;
     }
@@ -1990,8 +1989,8 @@ cookie_read (void *cookie, void *buffer, size_t size)
     {
       do
         {
-#ifdef HAVE_NPTH
-          nread = pth_read (c->sock->fd, buffer, size);
+#ifdef USE_NPTH
+          nread = npth_read (c->sock->fd, buffer, size);
 #elif defined(HAVE_W32_SYSTEM)
           /* Under Windows we need to use recv for a socket.  */
           nread = recv (c->sock->fd, buffer, size, 0);
diff --git a/common/init.c b/common/init.c
index 35e623f..91ee912 100644
--- a/common/init.c
+++ b/common/init.c
@@ -156,18 +156,12 @@ _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp)
 #ifdef HAVE_W32_SYSTEM
   /* For W32 we need to initialize the socket layer.  This is because
      we use recv and send in libassuan as well as at some other
-     places.  If we are building with PTH we let pth_init do it.  We
-     can't do much on error so we ignore them.  An error would anyway
-     later pop up if one of the socket functions is used. */
-# ifdef HAVE_NPTH
-  pth_init ();
-# else
+     places.  */
   {
     WSADATA wsadat;
 
     WSAStartup (0x202, &wsadat);
   }
-# endif /*!HAVE_NPTH*/
 #endif
 
 #ifdef HAVE_W32CE_SYSTEM
diff --git a/common/sysutils.c b/common/sysutils.c
index 95e0f8c..afb12ed 100644
--- a/common/sysutils.c
+++ b/common/sysutils.c
@@ -275,18 +275,8 @@ check_permissions(const char *path,int extension,int checkonly)
 void
 gnupg_sleep (unsigned int seconds)
 {
-#ifdef HAVE_NPTH
-  /* With Pth we force a regular sleep for seconds == 0 so that also
-     the process will give up its timeslot.  */
-  if (!seconds)
-    {
-# ifdef HAVE_W32_SYSTEM
-      Sleep (0);
-# else
-      sleep (0);
-# endif
-    }
-  pth_sleep (seconds);
+#ifdef USE_NPTH
+  npth_sleep (seconds);
 #else
   /* Fixme:  make sure that a sleep won't wake up to early.  */
 # ifdef HAVE_W32_SYSTEM
diff --git a/configure.ac b/configure.ac
index 096e3e1..19c9816 100644
--- a/configure.ac
+++ b/configure.ac
@@ -900,9 +900,10 @@ AC_DEFINE_UNQUOTED(SHRED,
 #
 AM_PATH_NPTH("$NEED_NPTH_API:$NEED_NPTH_VERSION",have_npth=yes,have_npth=no)
 if test "$have_npth" = "yes"; then
-  # We define this macro because some code parts require it.
-  AC_DEFINE(USE_NPTH, 1,
+  AC_DEFINE(HAVE_NPTH, 1,
               [Defined if the New Portable Thread Library is available])
+  AC_DEFINE(USE_NPTH, 1,
+              [Defined if support for nPth is requested and nPth is available])
 else
   AC_MSG_WARN([[
 ***
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index 0ac5aaf..60ac576 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -315,18 +315,8 @@ set_msg_len (unsigned char *msg, unsigned int length)
 static void
 my_sleep (int seconds)
 {
-#ifdef HAVE_NPTH
-  /* With Pth we also call the standard sleep(0) so that the process
-     may give up its timeslot.  */
-  if (!seconds)
-    {
-# ifdef HAVE_W32_SYSTEM
-      Sleep (0);
-# else
-      sleep (0);
-# endif
-    }
-  pth_sleep (seconds);
+#ifdef USE_NPTH
+  npth_sleep (seconds);
 #else
 # ifdef HAVE_W32_SYSTEM
   Sleep (seconds*1000);

-----------------------------------------------------------------------

Summary of changes:
 am/cmacros.am           |    2 +
 common/Makefile.am      |   28 ++-
 common/estream.c        |   28 +--
 common/exechelp-posix.c |    2 +-
 common/exechelp-w32.c   |    2 +-
 common/exechelp-w32ce.c |    2 +-
 common/http.c           |  642 ++++++++++++++++++++++++++++++-----------------
 common/http.h           |   18 +-
 common/init.c           |    8 +-
 common/sysutils.c       |   14 +-
 common/t-http.c         |  269 ++++++++++++++++++++
 common/t-openpgp-oid.c  |    7 +-
 common/tls-ca.pem       |   30 +++
 configure.ac            |   29 ++-
 dirmngr/Makefile.am     |    9 +-
 scd/ccid-driver.c       |   14 +-
 16 files changed, 816 insertions(+), 288 deletions(-)
 create mode 100644 common/t-http.c
 create mode 100644 common/tls-ca.pem


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list