dirmngr: First take on ntbtls cert verification.
[gnupg.git] / dirmngr / http.c
1 /* http.c  -  HTTP protocol handler
2  * Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, 2009, 2010,
3  *               2011 Free Software Foundation, Inc.
4  * Copyright (C) 2014 Werner Koch
5  * Copyright (C) 2015-2017 g10 Code GmbH
6  *
7  * This file is part of GnuPG.
8  *
9  * This file is free software; you can redistribute it and/or modify
10  * it under the terms of either
11  *
12  *   - the GNU Lesser General Public License as published by the Free
13  *     Software Foundation; either version 3 of the License, or (at
14  *     your option) any later version.
15  *
16  * or
17  *
18  *   - the GNU General Public License as published by the Free
19  *     Software Foundation; either version 2 of the License, or (at
20  *     your option) any later version.
21  *
22  * or both in parallel, as here.
23  *
24  * This file is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, see <https://www.gnu.org/licenses/>.
31  */
32
33 /* Simple HTTP client implementation.  We try to keep the code as
34    self-contained as possible.  There are some contraints however:
35
36   - estream is required.  We now require estream because it provides a
37     very useful and portable asprintf implementation and the fopencookie
38     function.
39   - stpcpy is required
40   - fixme: list other requirements.
41
42
43   - With HTTP_USE_NTBTLS or HTTP_USE_GNUTLS support for https is
44     provided (this also requires estream).
45
46   - With HTTP_NO_WSASTARTUP the socket initialization is not done
47     under Windows.  This is useful if the socket layer has already
48     been initialized elsewhere.  This also avoids the installation of
49     an exit handler to cleanup the socket layer.
50 */
51
52 #ifdef HAVE_CONFIG_H
53 # include <config.h>
54 #endif
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <stdarg.h>
58 #include <string.h>
59 #include <ctype.h>
60 #include <errno.h>
61 #include <unistd.h>
62
63 #ifdef HAVE_W32_SYSTEM
64 # ifdef HAVE_WINSOCK2_H
65 #  include <winsock2.h>
66 # endif
67 # include <windows.h>
68 #else /*!HAVE_W32_SYSTEM*/
69 # include <sys/types.h>
70 # include <sys/socket.h>
71 # include <sys/time.h>
72 # include <time.h>
73 # include <netinet/in.h>
74 # include <arpa/inet.h>
75 # include <netdb.h>
76 #endif /*!HAVE_W32_SYSTEM*/
77
78 #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth.  */
79 # undef USE_NPTH
80 #endif
81
82 #ifdef USE_NPTH
83 # include <npth.h>
84 #endif
85
86 #if defined (HTTP_USE_GNUTLS) && defined (HTTP_USE_NTBTLS)
87 # error Both, HTTP_USE_GNUTLS and HTTP_USE_NTBTLS, are defined.
88 #endif
89
90 #ifdef HTTP_USE_NTBTLS
91 # include <ntbtls.h>
92 #elif HTTP_USE_GNUTLS
93 # include <gnutls/gnutls.h>
94 # include <gnutls/x509.h>
95 #endif /*HTTP_USE_GNUTLS*/
96
97 #include <assuan.h>  /* We need the socket wrapper.  */
98
99 #include "util.h"
100 #include "i18n.h"
101 #include "dns-stuff.h"
102 #include "http.h"
103
104
105 #ifdef USE_NPTH
106 # define my_select(a,b,c,d,e)  npth_select ((a), (b), (c), (d), (e))
107 # define my_accept(a,b,c)      npth_accept ((a), (b), (c))
108 #else
109 # define my_select(a,b,c,d,e)  select ((a), (b), (c), (d), (e))
110 # define my_accept(a,b,c)      accept ((a), (b), (c))
111 #endif
112
113 #ifdef HAVE_W32_SYSTEM
114 #define sock_close(a)  closesocket(a)
115 #else
116 #define sock_close(a)  close(a)
117 #endif
118
119 #ifndef EAGAIN
120 #define EAGAIN  EWOULDBLOCK
121 #endif
122 #ifndef INADDR_NONE  /* Slowaris is missing that.  */
123 #define INADDR_NONE  ((unsigned long)(-1))
124 #endif /*INADDR_NONE*/
125
126 #define HTTP_PROXY_ENV           "http_proxy"
127 #define MAX_LINELEN 20000  /* Max. length of a HTTP header line. */
128 #define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz"   \
129                         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"   \
130                         "01234567890@"                 \
131                         "!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~"
132
133 #if HTTP_USE_NTBTLS
134 typedef ntbtls_t         tls_session_t;
135 # define USE_TLS 1
136 #elif HTTP_USE_GNUTLS
137 typedef gnutls_session_t tls_session_t;
138 # define USE_TLS 1
139 #else
140 typedef void *tls_session_t;
141 # undef USE_TLS
142 #endif
143
144 static gpg_err_code_t do_parse_uri (parsed_uri_t uri, int only_local_part,
145                                     int no_scheme_check, int force_tls);
146 static gpg_error_t parse_uri (parsed_uri_t *ret_uri, const char *uri,
147                               int no_scheme_check, int force_tls);
148 static int remove_escapes (char *string);
149 static int insert_escapes (char *buffer, const char *string,
150                            const char *special);
151 static uri_tuple_t parse_tuple (char *string);
152 static gpg_error_t send_request (http_t hd, const char *httphost,
153                                  const char *auth,const char *proxy,
154                                  const char *srvtag,strlist_t headers);
155 static char *build_rel_path (parsed_uri_t uri);
156 static gpg_error_t parse_response (http_t hd);
157
158 static gpg_error_t connect_server (const char *server, unsigned short port,
159                                    unsigned int flags, const char *srvtag,
160                                    assuan_fd_t *r_sock);
161 static gpg_error_t write_server (int sock, const char *data, size_t length);
162
163 static gpgrt_ssize_t cookie_read (void *cookie, void *buffer, size_t size);
164 static gpgrt_ssize_t cookie_write (void *cookie,
165                                    const void *buffer, size_t size);
166 static int cookie_close (void *cookie);
167
168
169 /* A socket object used to a allow ref counting of sockets.  */
170 struct my_socket_s
171 {
172   assuan_fd_t fd; /* The actual socket - shall never be ASSUAN_INVALID_FD.  */
173   int refcount;   /* Number of references to this socket.  */
174 };
175 typedef struct my_socket_s *my_socket_t;
176
177
178 /* Cookie function structure and cookie object.  */
179 static es_cookie_io_functions_t cookie_functions =
180   {
181     cookie_read,
182     cookie_write,
183     NULL,
184     cookie_close
185   };
186
187 struct cookie_s
188 {
189   /* Socket object or NULL if already closed. */
190   my_socket_t sock;
191
192   /* The session object or NULL if not used. */
193   http_session_t session;
194
195   /* True if TLS is to be used.  */
196   int use_tls;
197
198   /* The remaining content length and a flag telling whether to use
199      the content length.  */
200   uint64_t content_length;
201   unsigned int content_length_valid:1;
202 };
203 typedef struct cookie_s *cookie_t;
204
205 /* The session object. */
206 struct http_session_s
207 {
208   int refcount;    /* Number of references to this object.  */
209 #ifdef HTTP_USE_GNUTLS
210   gnutls_certificate_credentials_t certcred;
211 #endif /*HTTP_USE_GNUTLS*/
212 #ifdef USE_TLS
213   tls_session_t tls_session;
214   struct {
215     int done;      /* Verifciation has been done.  */
216     int rc;        /* TLS verification return code.  */
217     unsigned int status; /* Verification status.  */
218   } verify;
219   char *servername; /* Malloced server name.  */
220 #endif /*USE_TLS*/
221   /* A callback function to log details of TLS certifciates.  */
222   void (*cert_log_cb) (http_session_t, gpg_error_t, const char *,
223                        const void **, size_t *);
224
225   /* The flags passed to the session object.  */
226   unsigned int flags;
227
228   /* A per-session TLS verification callback.  */
229   http_verify_cb_t verify_cb;
230   void *verify_cb_value;
231 };
232
233
234 /* An object to save header lines. */
235 struct header_s
236 {
237   struct header_s *next;
238   char *value;    /* The value of the header (malloced).  */
239   char name[1];   /* The name of the header (canonicalized). */
240 };
241 typedef struct header_s *header_t;
242
243
244 /* Our handle context. */
245 struct http_context_s
246 {
247   unsigned int status_code;
248   my_socket_t sock;
249   unsigned int in_data:1;
250   unsigned int is_http_0_9:1;
251   estream_t fp_read;
252   estream_t fp_write;
253   void *write_cookie;
254   void *read_cookie;
255   http_session_t session;
256   parsed_uri_t uri;
257   http_req_t req_type;
258   char *buffer;          /* Line buffer. */
259   size_t buffer_size;
260   unsigned int flags;
261   header_t headers;      /* Received headers. */
262 };
263
264
265 /* Two flags to enable verbose and debug mode.  Although currently not
266  * set-able a value > 1 for OPT_DEBUG enables debugging of the session
267  * reference counting.  */
268 static int opt_verbose;
269 static int opt_debug;
270
271 /* The global callback for the verification function.  */
272 static gpg_error_t (*tls_callback) (http_t, http_session_t, int);
273
274 /* The list of files with trusted CA certificates.  */
275 static strlist_t tls_ca_certlist;
276
277 /* The global callback for net activity.  */
278 static void (*netactivity_cb)(void);
279
280
281 \f
282 #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
283
284 #if GNUPG_MAJOR_VERSION == 1
285 #define REQ_WINSOCK_MAJOR  1
286 #define REQ_WINSOCK_MINOR  1
287 #else
288 #define REQ_WINSOCK_MAJOR  2
289 #define REQ_WINSOCK_MINOR  2
290 #endif
291
292
293 static void
294 deinit_sockets (void)
295 {
296   WSACleanup();
297 }
298
299 static void
300 init_sockets (void)
301 {
302   static int initialized;
303   static WSADATA wsdata;
304
305   if (initialized)
306     return;
307
308   if ( WSAStartup( MAKEWORD (REQ_WINSOCK_MINOR, REQ_WINSOCK_MAJOR), &wsdata ) )
309     {
310       log_error ("error initializing socket library: ec=%d\n",
311                  (int)WSAGetLastError () );
312       return;
313     }
314   if ( LOBYTE(wsdata.wVersion) != REQ_WINSOCK_MAJOR
315        || HIBYTE(wsdata.wVersion) != REQ_WINSOCK_MINOR )
316     {
317       log_error ("socket library version is %x.%x - but %d.%d needed\n",
318                  LOBYTE(wsdata.wVersion), HIBYTE(wsdata.wVersion),
319                  REQ_WINSOCK_MAJOR, REQ_WINSOCK_MINOR);
320       WSACleanup();
321       return;
322     }
323   atexit ( deinit_sockets );
324   initialized = 1;
325 }
326 #endif /*HAVE_W32_SYSTEM && !HTTP_NO_WSASTARTUP*/
327
328
329 /* Create a new socket object.  Returns NULL and closes FD if not
330    enough memory is available.  */
331 static my_socket_t
332 _my_socket_new (int lnr, assuan_fd_t fd)
333 {
334   my_socket_t so;
335
336   so = xtrymalloc (sizeof *so);
337   if (!so)
338     {
339       int save_errno = errno;
340       assuan_sock_close (fd);
341       gpg_err_set_errno (save_errno);
342       return NULL;
343     }
344   so->fd = fd;
345   so->refcount = 1;
346   if (opt_debug)
347     log_debug ("http.c:%d:socket_new: object %p for fd %d created\n",
348                lnr, so, so->fd);
349   return so;
350 }
351 #define my_socket_new(a) _my_socket_new (__LINE__, (a))
352
353 /* Bump up the reference counter for the socket object SO.  */
354 static my_socket_t
355 _my_socket_ref (int lnr, my_socket_t so)
356 {
357   so->refcount++;
358   if (opt_debug > 1)
359     log_debug ("http.c:%d:socket_ref: object %p for fd %d refcount now %d\n",
360                lnr, so, so->fd, so->refcount);
361   return so;
362 }
363 #define my_socket_ref(a) _my_socket_ref (__LINE__,(a))
364
365
366 /* Bump down the reference counter for the socket object SO.  If SO
367    has no more references, close the socket and release the
368    object.  */
369 static void
370 _my_socket_unref (int lnr, my_socket_t so,
371                   void (*preclose)(void*), void *preclosearg)
372 {
373   if (so)
374     {
375       so->refcount--;
376       if (opt_debug > 1)
377         log_debug ("http.c:%d:socket_unref: object %p for fd %d ref now %d\n",
378                    lnr, so, so->fd, so->refcount);
379
380       if (!so->refcount)
381         {
382           if (preclose)
383             preclose (preclosearg);
384           assuan_sock_close (so->fd);
385           xfree (so);
386         }
387     }
388 }
389 #define my_socket_unref(a,b,c) _my_socket_unref (__LINE__,(a),(b),(c))
390
391
392 #ifdef HTTP_USE_GNUTLS
393 static ssize_t
394 my_gnutls_read (gnutls_transport_ptr_t ptr, void *buffer, size_t size)
395 {
396   my_socket_t sock = ptr;
397 #if USE_NPTH
398   return npth_read (sock->fd, buffer, size);
399 #else
400   return read (sock->fd, buffer, size);
401 #endif
402 }
403 static ssize_t
404 my_gnutls_write (gnutls_transport_ptr_t ptr, const void *buffer, size_t size)
405 {
406   my_socket_t sock = ptr;
407 #if USE_NPTH
408   return npth_write (sock->fd, buffer, size);
409 #else
410   return write (sock->fd, buffer, size);
411 #endif
412 }
413 #endif /*HTTP_USE_GNUTLS*/
414
415
416 #ifdef HTTP_USE_NTBTLS
417 /* Connect the ntbls callback to our generic callback.  */
418 static gpg_error_t
419 my_ntbtls_verify_cb (void *opaque, ntbtls_t tls, unsigned int verify_flags)
420 {
421   http_t hd = opaque;
422   log_assert (hd && hd->session && hd->session->verify_cb);
423   return hd->session->verify_cb (hd->session->verify_cb_value,
424                                  hd, hd->session,
425                                  (hd->flags | hd->session->flags),
426                                  tls);
427 }
428 #endif /*HTTP_USE_NTBTLS*/
429
430
431
432 \f
433 /* This notification function is called by estream whenever stream is
434    closed.  Its purpose is to mark the closing in the handle so
435    that a http_close won't accidentally close the estream.  The function
436    http_close removes this notification so that it won't be called if
437    http_close was used before an es_fclose.  */
438 static void
439 fp_onclose_notification (estream_t stream, void *opaque)
440 {
441   http_t hd = opaque;
442
443   if (hd->fp_read && hd->fp_read == stream)
444     hd->fp_read = NULL;
445   else if (hd->fp_write && hd->fp_write == stream)
446     hd->fp_write = NULL;
447 }
448
449
450 /*
451  * Helper function to create an HTTP header with hex encoded data.  A
452  * new buffer is returned.  This buffer is the concatenation of the
453  * string PREFIX, the hex-encoded DATA of length LEN and the string
454  * SUFFIX.  On error NULL is returned and ERRNO set.
455  */
456 static char *
457 make_header_line (const char *prefix, const char *suffix,
458                   const void *data, size_t len )
459 {
460   static unsigned char bintoasc[] =
461     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
462     "abcdefghijklmnopqrstuvwxyz"
463     "0123456789+/";
464   const unsigned char *s = data;
465   char *buffer, *p;
466
467   buffer = xtrymalloc (strlen (prefix) + (len+2)/3*4 + strlen (suffix) + 1);
468   if (!buffer)
469     return NULL;
470   p = stpcpy (buffer, prefix);
471   for ( ; len >= 3 ; len -= 3, s += 3 )
472     {
473       *p++ = bintoasc[(s[0] >> 2) & 077];
474       *p++ = bintoasc[(((s[0] <<4)&060)|((s[1] >> 4)&017))&077];
475       *p++ = bintoasc[(((s[1]<<2)&074)|((s[2]>>6)&03))&077];
476       *p++ = bintoasc[s[2]&077];
477       *p = 0;
478     }
479   if ( len == 2 )
480     {
481       *p++ = bintoasc[(s[0] >> 2) & 077];
482       *p++ = bintoasc[(((s[0] <<4)&060)|((s[1] >> 4)&017))&077];
483       *p++ = bintoasc[((s[1]<<2)&074)];
484       *p++ = '=';
485     }
486   else if ( len == 1 )
487     {
488       *p++ = bintoasc[(s[0] >> 2) & 077];
489       *p++ = bintoasc[(s[0] <<4)&060];
490       *p++ = '=';
491       *p++ = '=';
492     }
493   *p = 0;
494   strcpy (p, suffix);
495   return buffer;
496 }
497
498
499
500 \f
501 /* Set verbosity and debug mode for this module. */
502 void
503 http_set_verbose (int verbose, int debug)
504 {
505   opt_verbose = verbose;
506   opt_debug = debug;
507 }
508
509
510 /* Register a non-standard global TLS callback function.  If no
511    verification is desired a callback needs to be registered which
512    always returns NULL.  */
513 void
514 http_register_tls_callback (gpg_error_t (*cb)(http_t, http_session_t, int))
515 {
516   tls_callback = cb;
517 }
518
519
520 /* Register a CA certificate for future use.  The certificate is
521    expected to be in FNAME.  PEM format is assume if FNAME has a
522    suffix of ".pem".  If FNAME is NULL the list of CA files is
523    removed.  */
524 void
525 http_register_tls_ca (const char *fname)
526 {
527   strlist_t sl;
528
529   if (!fname)
530     {
531       free_strlist (tls_ca_certlist);
532       tls_ca_certlist = NULL;
533     }
534   else
535     {
536       /* Warn if we can't access right now, but register it anyway in
537          case it becomes accessible later */
538       if (access (fname, F_OK))
539         log_info (_("can't access '%s': %s\n"), fname,
540                   gpg_strerror (gpg_error_from_syserror()));
541       sl = add_to_strlist (&tls_ca_certlist, fname);
542       if (*sl->d && !strcmp (sl->d + strlen (sl->d) - 4, ".pem"))
543         sl->flags = 1;
544     }
545 }
546
547
548 /* Register a callback which is called every time the HTTP mode has
549  * made a successful connection to some server.  */
550 void
551 http_register_netactivity_cb (void (*cb)(void))
552 {
553   netactivity_cb = cb;
554 }
555
556
557 /* Call the netactivity callback if any.  */
558 static void
559 notify_netactivity (void)
560 {
561   if (netactivity_cb)
562     netactivity_cb ();
563 }
564
565
566
567 #ifdef USE_TLS
568 /* Free the TLS session associated with SESS, if any.  */
569 static void
570 close_tls_session (http_session_t sess)
571 {
572   if (sess->tls_session)
573     {
574 # if HTTP_USE_NTBTLS
575       /* FIXME!!
576          Possibly, ntbtls_get_transport and close those streams.
577          Somehow get SOCK to call my_socket_unref.
578       */
579       ntbtls_release (sess->tls_session);
580 # elif HTTP_USE_GNUTLS
581       my_socket_t sock = gnutls_transport_get_ptr (sess->tls_session);
582       my_socket_unref (sock, NULL, NULL);
583       gnutls_deinit (sess->tls_session);
584       if (sess->certcred)
585         gnutls_certificate_free_credentials (sess->certcred);
586 # endif /*HTTP_USE_GNUTLS*/
587       xfree (sess->servername);
588       sess->tls_session = NULL;
589     }
590 }
591 #endif /*USE_TLS*/
592
593
594 /* Release a session.  Take care not to release it while it is being
595    used by a http context object.  */
596 static void
597 session_unref (int lnr, http_session_t sess)
598 {
599   if (!sess)
600     return;
601
602   sess->refcount--;
603   if (opt_debug > 1)
604     log_debug ("http.c:%d:session_unref: sess %p ref now %d\n",
605                lnr, sess, sess->refcount);
606   if (sess->refcount)
607     return;
608
609 #ifdef USE_TLS
610   close_tls_session (sess);
611 #endif /*USE_TLS*/
612
613   xfree (sess);
614 }
615 #define http_session_unref(a) session_unref (__LINE__, (a))
616
617 void
618 http_session_release (http_session_t sess)
619 {
620   http_session_unref (sess);
621 }
622
623
624 /* Create a new session object which is currently used to enable TLS
625  * support.  It may eventually allow reusing existing connections.
626  * Valid values for FLAGS are:
627  *   HTTP_FLAG_TRUST_DEF - Use the CAs set with http_register_tls_ca
628  *   HTTP_FLAG_TRUST_SYS - Also use the CAs defined by the system
629  */
630 gpg_error_t
631 http_session_new (http_session_t *r_session,
632                   const char *intended_hostname, unsigned int flags,
633                   http_verify_cb_t verify_cb, void *verify_cb_value)
634 {
635   gpg_error_t err;
636   http_session_t sess;
637
638   *r_session = NULL;
639
640   sess = xtrycalloc (1, sizeof *sess);
641   if (!sess)
642     return gpg_error_from_syserror ();
643   sess->refcount = 1;
644   sess->flags = flags;
645   sess->verify_cb = verify_cb;
646   sess->verify_cb_value = verify_cb_value;
647
648 #if HTTP_USE_NTBTLS
649   {
650     (void)intended_hostname; /* Not needed because we do not preload
651                               * certificates.  */
652
653     err = ntbtls_new (&sess->tls_session, NTBTLS_CLIENT);
654     if (err)
655       {
656         log_error ("ntbtls_new failed: %s\n", gpg_strerror (err));
657         goto leave;
658       }
659
660   }
661 #elif HTTP_USE_GNUTLS
662   {
663     const char *errpos;
664     int rc;
665     strlist_t sl;
666     int add_system_cas = !!(flags & HTTP_FLAG_TRUST_SYS);
667     int is_hkps_pool;
668
669     rc = gnutls_certificate_allocate_credentials (&sess->certcred);
670     if (rc < 0)
671       {
672         log_error ("gnutls_certificate_allocate_credentials failed: %s\n",
673                    gnutls_strerror (rc));
674         err = gpg_error (GPG_ERR_GENERAL);
675         goto leave;
676       }
677
678     is_hkps_pool = (intended_hostname
679                     && !ascii_strcasecmp (intended_hostname,
680                                           "hkps.pool.sks-keyservers.net"));
681
682     /* If the user has not specified a CA list, and they are looking
683      * for the hkps pool from sks-keyservers.net, then default to
684      * Kristian's certificate authority:  */
685     if (!tls_ca_certlist && is_hkps_pool)
686       {
687         char *pemname = make_filename_try (gnupg_datadir (),
688                                            "sks-keyservers.netCA.pem", NULL);
689         if (!pemname)
690           {
691             err = gpg_error_from_syserror ();
692             log_error ("setting CA from file '%s' failed: %s\n",
693                        pemname, gpg_strerror (err));
694           }
695         else
696           {
697             rc = gnutls_certificate_set_x509_trust_file
698               (sess->certcred, pemname, GNUTLS_X509_FMT_PEM);
699             if (rc < 0)
700               log_info ("setting CA from file '%s' failed: %s\n",
701                         pemname, gnutls_strerror (rc));
702             xfree (pemname);
703           }
704       }
705
706     /* Add configured certificates to the session.  */
707     if ((flags & HTTP_FLAG_TRUST_DEF))
708       {
709         for (sl = tls_ca_certlist; sl; sl = sl->next)
710           {
711             rc = gnutls_certificate_set_x509_trust_file
712               (sess->certcred, sl->d,
713                (sl->flags & 1)? GNUTLS_X509_FMT_PEM : GNUTLS_X509_FMT_DER);
714             if (rc < 0)
715               log_info ("setting CA from file '%s' failed: %s\n",
716                         sl->d, gnutls_strerror (rc));
717           }
718         if (!tls_ca_certlist && !is_hkps_pool)
719           add_system_cas = 1;
720       }
721
722     /* Add system certificates to the session.  */
723     if (add_system_cas)
724       {
725 #if GNUTLS_VERSION_NUMBER >= 0x030014
726         static int shown;
727
728         rc = gnutls_certificate_set_x509_system_trust (sess->certcred);
729         if (rc < 0)
730           log_info ("setting system CAs failed: %s\n", gnutls_strerror (rc));
731         else if (!shown)
732           {
733             shown = 1;
734             log_info ("number of system provided CAs: %d\n", rc);
735           }
736 #endif /* gnutls >= 3.0.20 */
737       }
738
739     rc = gnutls_init (&sess->tls_session, GNUTLS_CLIENT);
740     if (rc < 0)
741       {
742         log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc));
743         err = gpg_error (GPG_ERR_GENERAL);
744         goto leave;
745       }
746     /* A new session has the transport ptr set to (void*(-1), we need
747        it to be NULL.  */
748     gnutls_transport_set_ptr (sess->tls_session, NULL);
749
750     rc = gnutls_priority_set_direct (sess->tls_session,
751                                      "NORMAL",
752                                      &errpos);
753     if (rc < 0)
754       {
755         log_error ("gnutls_priority_set_direct failed at '%s': %s\n",
756                    errpos, gnutls_strerror (rc));
757         err = gpg_error (GPG_ERR_GENERAL);
758         goto leave;
759       }
760
761     rc = gnutls_credentials_set (sess->tls_session,
762                                  GNUTLS_CRD_CERTIFICATE, sess->certcred);
763     if (rc < 0)
764       {
765         log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc));
766         err = gpg_error (GPG_ERR_GENERAL);
767         goto leave;
768       }
769   }
770 #else /*!HTTP_USE_GNUTLS*/
771   {
772     (void)tls_priority;
773   }
774 #endif /*!HTTP_USE_GNUTLS*/
775
776   if (opt_debug > 1)
777     log_debug ("http.c:session_new: sess %p created\n", sess);
778   err = 0;
779
780 #if USE_TLS
781  leave:
782 #endif /*USE_TLS*/
783   if (err)
784     http_session_unref (sess);
785   else
786     *r_session = sess;
787
788   return err;
789 }
790
791
792 /* Increment the reference count for session SESS.  Passing NULL for
793    SESS is allowed. */
794 http_session_t
795 http_session_ref (http_session_t sess)
796 {
797   if (sess)
798     {
799       sess->refcount++;
800       if (opt_debug > 1)
801         log_debug ("http.c:session_ref: sess %p ref now %d\n",
802                    sess, sess->refcount);
803     }
804   return sess;
805 }
806
807
808 void
809 http_session_set_log_cb (http_session_t sess,
810                          void (*cb)(http_session_t, gpg_error_t,
811                                     const char *hostname,
812                                     const void **certs, size_t *certlens))
813 {
814   sess->cert_log_cb = cb;
815 }
816
817
818
819 \f
820 /* Start a HTTP retrieval and on success store at R_HD a context
821    pointer for completing the request and to wait for the response.
822    If HTTPHOST is not NULL it is used for the Host header instead of a
823    Host header derived from the URL. */
824 gpg_error_t
825 http_open (http_t *r_hd, http_req_t reqtype, const char *url,
826            const char *httphost,
827            const char *auth, unsigned int flags, const char *proxy,
828            http_session_t session, const char *srvtag, strlist_t headers)
829 {
830   gpg_error_t err;
831   http_t hd;
832
833   *r_hd = NULL;
834
835   if (!(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST))
836     return gpg_err_make (default_errsource, GPG_ERR_INV_ARG);
837
838   /* Create the handle. */
839   hd = xtrycalloc (1, sizeof *hd);
840   if (!hd)
841     return gpg_error_from_syserror ();
842   hd->req_type = reqtype;
843   hd->flags = flags;
844   hd->session = http_session_ref (session);
845
846   err = parse_uri (&hd->uri, url, 0, !!(flags & HTTP_FLAG_FORCE_TLS));
847   if (!err)
848     err = send_request (hd, httphost, auth, proxy, srvtag, headers);
849
850   if (err)
851     {
852       my_socket_unref (hd->sock, NULL, NULL);
853       if (hd->fp_read)
854         es_fclose (hd->fp_read);
855       if (hd->fp_write)
856         es_fclose (hd->fp_write);
857       http_session_unref (hd->session);
858       xfree (hd);
859     }
860   else
861     *r_hd = hd;
862   return err;
863 }
864
865
866 /* This function is useful to connect to a generic TCP service using
867    this http abstraction layer.  This has the advantage of providing
868    service tags and an estream interface.  */
869 gpg_error_t
870 http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
871                   unsigned int flags, const char *srvtag)
872 {
873   gpg_error_t err = 0;
874   http_t hd;
875   cookie_t cookie;
876
877   *r_hd = NULL;
878
879   if ((flags & HTTP_FLAG_FORCE_TOR))
880     {
881       int mode;
882
883       if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
884         {
885           log_error ("Tor support is not available\n");
886           return gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
887         }
888     }
889
890   /* Create the handle. */
891   hd = xtrycalloc (1, sizeof *hd);
892   if (!hd)
893     return gpg_error_from_syserror ();
894   hd->req_type = HTTP_REQ_OPAQUE;
895   hd->flags = flags;
896
897   /* Connect.  */
898   {
899     assuan_fd_t sock;
900
901     err = connect_server (server, port, hd->flags, srvtag, &sock);
902     if (err)
903       {
904         xfree (hd);
905         return err;
906       }
907     hd->sock = my_socket_new (sock);
908     if (!hd->sock)
909       {
910         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
911         xfree (hd);
912         return err;
913       }
914   }
915
916   /* Setup estreams for reading and writing.  */
917   cookie = xtrycalloc (1, sizeof *cookie);
918   if (!cookie)
919     {
920       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
921       goto leave;
922     }
923   cookie->sock = my_socket_ref (hd->sock);
924   hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
925   if (!hd->fp_write)
926     {
927       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
928       my_socket_unref (cookie->sock, NULL, NULL);
929       xfree (cookie);
930       goto leave;
931     }
932   hd->write_cookie = cookie; /* Cookie now owned by FP_WRITE.  */
933
934   cookie = xtrycalloc (1, sizeof *cookie);
935   if (!cookie)
936     {
937       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
938       goto leave;
939     }
940   cookie->sock = my_socket_ref (hd->sock);
941   hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
942   if (!hd->fp_read)
943     {
944       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
945       my_socket_unref (cookie->sock, NULL, NULL);
946       xfree (cookie);
947       goto leave;
948     }
949   hd->read_cookie = cookie; /* Cookie now owned by FP_READ.  */
950
951   /* Register close notification to interlock the use of es_fclose in
952      http_close and in user code.  */
953   err = es_onclose (hd->fp_write, 1, fp_onclose_notification, hd);
954   if (!err)
955     err = es_onclose (hd->fp_read, 1, fp_onclose_notification, hd);
956
957  leave:
958   if (err)
959     {
960       if (hd->fp_read)
961         es_fclose (hd->fp_read);
962       if (hd->fp_write)
963         es_fclose (hd->fp_write);
964       my_socket_unref (hd->sock, NULL, NULL);
965       xfree (hd);
966     }
967   else
968     *r_hd = hd;
969   return err;
970 }
971
972
973
974
975 void
976 http_start_data (http_t hd)
977 {
978   if (!hd->in_data)
979     {
980       if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
981         log_debug_with_string ("\r\n", "http.c:request-header:");
982       es_fputs ("\r\n", hd->fp_write);
983       es_fflush (hd->fp_write);
984       hd->in_data = 1;
985     }
986   else
987     es_fflush (hd->fp_write);
988 }
989
990
991 gpg_error_t
992 http_wait_response (http_t hd)
993 {
994   gpg_error_t err;
995   cookie_t cookie;
996
997   /* Make sure that we are in the data. */
998   http_start_data (hd);
999
1000   /* Close the write stream.  Note that the reference counted socket
1001      object keeps the actual system socket open.  */
1002   cookie = hd->write_cookie;
1003   if (!cookie)
1004     return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1005
1006   es_fclose (hd->fp_write);
1007   hd->fp_write = NULL;
1008   /* The close has released the cookie and thus we better set it to NULL.  */
1009   hd->write_cookie = NULL;
1010
1011   /* Shutdown one end of the socket is desired.  As per HTTP/1.0 this
1012      is not required but some very old servers (e.g. the original pksd
1013      keyserver didn't worked without it.  */
1014   if ((hd->flags & HTTP_FLAG_SHUTDOWN))
1015     shutdown (hd->sock->fd, 1);
1016   hd->in_data = 0;
1017
1018   /* Create a new cookie and a stream for reading.  */
1019   cookie = xtrycalloc (1, sizeof *cookie);
1020   if (!cookie)
1021     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1022   cookie->sock = my_socket_ref (hd->sock);
1023   cookie->session = http_session_ref (hd->session);
1024   cookie->use_tls = hd->uri->use_tls;
1025
1026   hd->read_cookie = cookie;
1027   hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
1028   if (!hd->fp_read)
1029     {
1030       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1031       my_socket_unref (cookie->sock, NULL, NULL);
1032       http_session_unref (cookie->session);
1033       xfree (cookie);
1034       hd->read_cookie = NULL;
1035       return err;
1036     }
1037
1038   err = parse_response (hd);
1039
1040   if (!err)
1041     err = es_onclose (hd->fp_read, 1, fp_onclose_notification, hd);
1042
1043   return err;
1044 }
1045
1046
1047 /* Convenience function to send a request and wait for the response.
1048    Closes the handle on error.  If PROXY is not NULL, this value will
1049    be used as an HTTP proxy and any enabled $http_proxy gets
1050    ignored. */
1051 gpg_error_t
1052 http_open_document (http_t *r_hd, const char *document,
1053                     const char *auth, unsigned int flags, const char *proxy,
1054                     http_session_t session,
1055                     const char *srvtag, strlist_t headers)
1056 {
1057   gpg_error_t err;
1058
1059   err = http_open (r_hd, HTTP_REQ_GET, document, NULL, auth, flags,
1060                    proxy, session, srvtag, headers);
1061   if (err)
1062     return err;
1063
1064   err = http_wait_response (*r_hd);
1065   if (err)
1066     http_close (*r_hd, 0);
1067
1068   return err;
1069 }
1070
1071
1072 void
1073 http_close (http_t hd, int keep_read_stream)
1074 {
1075   if (!hd)
1076     return;
1077
1078   /* First remove the close notifications for the streams.  */
1079   if (hd->fp_read)
1080     es_onclose (hd->fp_read, 0, fp_onclose_notification, hd);
1081   if (hd->fp_write)
1082     es_onclose (hd->fp_write, 0, fp_onclose_notification, hd);
1083
1084   /* Now we can close the streams.  */
1085   my_socket_unref (hd->sock, NULL, NULL);
1086   if (hd->fp_read && !keep_read_stream)
1087     es_fclose (hd->fp_read);
1088   if (hd->fp_write)
1089     es_fclose (hd->fp_write);
1090   http_session_unref (hd->session);
1091   http_release_parsed_uri (hd->uri);
1092   while (hd->headers)
1093     {
1094       header_t tmp = hd->headers->next;
1095       xfree (hd->headers->value);
1096       xfree (hd->headers);
1097       hd->headers = tmp;
1098     }
1099   xfree (hd->buffer);
1100   xfree (hd);
1101 }
1102
1103
1104 estream_t
1105 http_get_read_ptr (http_t hd)
1106 {
1107   return hd?hd->fp_read:NULL;
1108 }
1109
1110 estream_t
1111 http_get_write_ptr (http_t hd)
1112 {
1113   return hd?hd->fp_write:NULL;
1114 }
1115
1116 unsigned int
1117 http_get_status_code (http_t hd)
1118 {
1119   return hd?hd->status_code:0;
1120 }
1121
1122 /* Return information pertaining to TLS.  If TLS is not in use for HD,
1123    NULL is returned.  WHAT is used ask for specific information:
1124
1125      (NULL) := Only check whether TLS is is use.  Returns an
1126                unspecified string if TLS is in use.  That string may
1127                even be the empty string.
1128  */
1129 const char *
1130 http_get_tls_info (http_t hd, const char *what)
1131 {
1132   (void)what;
1133
1134   if (!hd)
1135     return NULL;
1136
1137   return hd->uri->use_tls? "":NULL;
1138 }
1139
1140
1141 \f
1142 static gpg_error_t
1143 parse_uri (parsed_uri_t *ret_uri, const char *uri,
1144            int no_scheme_check, int force_tls)
1145 {
1146   gpg_err_code_t ec;
1147
1148   *ret_uri = xtrycalloc (1, sizeof **ret_uri + strlen (uri));
1149   if (!*ret_uri)
1150     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1151   strcpy ((*ret_uri)->buffer, uri);
1152   ec = do_parse_uri (*ret_uri, 0, no_scheme_check, force_tls);
1153   if (ec)
1154     {
1155       xfree (*ret_uri);
1156       *ret_uri = NULL;
1157     }
1158   return gpg_err_make (default_errsource, ec);
1159 }
1160
1161
1162 /*
1163  * Parse an URI and put the result into the newly allocated RET_URI.
1164  * On success the caller must use http_release_parsed_uri() to
1165  * releases the resources.  If NO_SCHEME_CHECK is set, the function
1166  * tries to parse the URL in the same way it would do for an HTTP
1167  * style URI.
1168  */
1169 gpg_error_t
1170 http_parse_uri (parsed_uri_t *ret_uri, const char *uri,
1171                 int no_scheme_check)
1172 {
1173   return parse_uri (ret_uri, uri, no_scheme_check, 0);
1174 }
1175
1176
1177 void
1178 http_release_parsed_uri (parsed_uri_t uri)
1179 {
1180   if (uri)
1181     {
1182       uri_tuple_t r, r2;
1183
1184       for (r = uri->query; r; r = r2)
1185         {
1186           r2 = r->next;
1187           xfree (r);
1188         }
1189       xfree (uri);
1190     }
1191 }
1192
1193
1194 static gpg_err_code_t
1195 do_parse_uri (parsed_uri_t uri, int only_local_part,
1196               int no_scheme_check, int force_tls)
1197 {
1198   uri_tuple_t *tail;
1199   char *p, *p2, *p3, *pp;
1200   int n;
1201
1202   p = uri->buffer;
1203   n = strlen (uri->buffer);
1204
1205   /* Initialize all fields to an empty string or an empty list. */
1206   uri->scheme = uri->host = uri->path = p + n;
1207   uri->port = 0;
1208   uri->params = uri->query = NULL;
1209   uri->use_tls = 0;
1210   uri->is_http = 0;
1211   uri->opaque = 0;
1212   uri->v6lit = 0;
1213   uri->onion = 0;
1214   uri->explicit_port = 0;
1215
1216   /* A quick validity check. */
1217   if (strspn (p, VALID_URI_CHARS) != n)
1218     return GPG_ERR_BAD_URI;     /* Invalid characters found. */
1219
1220   if (!only_local_part)
1221     {
1222       /* Find the scheme. */
1223       if (!(p2 = strchr (p, ':')) || p2 == p)
1224         return GPG_ERR_BAD_URI; /* No scheme. */
1225       *p2++ = 0;
1226       for (pp=p; *pp; pp++)
1227        *pp = tolower (*(unsigned char*)pp);
1228       uri->scheme = p;
1229       if (!strcmp (uri->scheme, "http") && !force_tls)
1230         {
1231           uri->port = 80;
1232           uri->is_http = 1;
1233         }
1234       else if (!strcmp (uri->scheme, "hkp") && !force_tls)
1235         {
1236           uri->port = 11371;
1237           uri->is_http = 1;
1238         }
1239 #ifdef USE_TLS
1240       else if (!strcmp (uri->scheme, "https") || !strcmp (uri->scheme,"hkps")
1241                || (force_tls && (!strcmp (uri->scheme, "http")
1242                                  || !strcmp (uri->scheme,"hkp"))))
1243         {
1244           uri->port = 443;
1245           uri->is_http = 1;
1246           uri->use_tls = 1;
1247         }
1248 #endif /*USE_TLS*/
1249       else if (!no_scheme_check)
1250         return GPG_ERR_INV_URI; /* Unsupported scheme */
1251
1252       p = p2;
1253
1254       if (*p == '/' && p[1] == '/' ) /* There seems to be a hostname. */
1255         {
1256           p += 2;
1257           if ((p2 = strchr (p, '/')))
1258             *p2++ = 0;
1259
1260           /* Check for username/password encoding */
1261           if ((p3 = strchr (p, '@')))
1262             {
1263               uri->auth = p;
1264               *p3++ = '\0';
1265               p = p3;
1266             }
1267
1268           for (pp=p; *pp; pp++)
1269             *pp = tolower (*(unsigned char*)pp);
1270
1271           /* Handle an IPv6 literal */
1272           if( *p == '[' && (p3=strchr( p, ']' )) )
1273             {
1274               *p3++ = '\0';
1275               /* worst case, uri->host should have length 0, points to \0 */
1276               uri->host = p + 1;
1277               uri->v6lit = 1;
1278               p = p3;
1279             }
1280           else
1281             uri->host = p;
1282
1283           if ((p3 = strchr (p, ':')))
1284             {
1285               *p3++ = '\0';
1286               uri->port = atoi (p3);
1287               uri->explicit_port = 1;
1288             }
1289
1290           if ((n = remove_escapes (uri->host)) < 0)
1291             return GPG_ERR_BAD_URI;
1292           if (n != strlen (uri->host))
1293             return GPG_ERR_BAD_URI;     /* Hostname incudes a Nul. */
1294           p = p2 ? p2 : NULL;
1295         }
1296       else if (uri->is_http)
1297         return GPG_ERR_INV_URI; /* No Leading double slash for HTTP.  */
1298       else
1299         {
1300           uri->opaque = 1;
1301           uri->path = p;
1302           if (is_onion_address (uri->path))
1303             uri->onion = 1;
1304           return 0;
1305         }
1306
1307     } /* End global URI part. */
1308
1309   /* Parse the pathname part if any.  */
1310   if (p && *p)
1311     {
1312       /* TODO: Here we have to check params. */
1313
1314       /* Do we have a query part? */
1315       if ((p2 = strchr (p, '?')))
1316         *p2++ = 0;
1317
1318       uri->path = p;
1319       if ((n = remove_escapes (p)) < 0)
1320         return GPG_ERR_BAD_URI;
1321       if (n != strlen (p))
1322         return GPG_ERR_BAD_URI; /* Path includes a Nul. */
1323       p = p2 ? p2 : NULL;
1324
1325       /* Parse a query string if any.  */
1326       if (p && *p)
1327         {
1328           tail = &uri->query;
1329           for (;;)
1330             {
1331               uri_tuple_t elem;
1332
1333               if ((p2 = strchr (p, '&')))
1334                 *p2++ = 0;
1335               if (!(elem = parse_tuple (p)))
1336                 return GPG_ERR_BAD_URI;
1337               *tail = elem;
1338               tail = &elem->next;
1339
1340               if (!p2)
1341                 break; /* Ready. */
1342               p = p2;
1343             }
1344         }
1345     }
1346
1347   if (is_onion_address (uri->host))
1348     uri->onion = 1;
1349
1350   return 0;
1351 }
1352
1353
1354 /*
1355  * Remove all %xx escapes; this is done in-place.  Returns: New length
1356  * of the string.
1357  */
1358 static int
1359 remove_escapes (char *string)
1360 {
1361   int n = 0;
1362   unsigned char *p, *s;
1363
1364   for (p = s = (unsigned char*)string; *s; s++)
1365     {
1366       if (*s == '%')
1367         {
1368           if (s[1] && s[2] && isxdigit (s[1]) && isxdigit (s[2]))
1369             {
1370               s++;
1371               *p = *s >= '0' && *s <= '9' ? *s - '0' :
1372                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
1373               *p <<= 4;
1374               s++;
1375               *p |= *s >= '0' && *s <= '9' ? *s - '0' :
1376                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
1377               p++;
1378               n++;
1379             }
1380           else
1381             {
1382               *p++ = *s++;
1383               if (*s)
1384                 *p++ = *s++;
1385               if (*s)
1386                 *p++ = *s++;
1387               if (*s)
1388                 *p = 0;
1389               return -1; /* Bad URI. */
1390             }
1391         }
1392       else
1393         {
1394           *p++ = *s;
1395           n++;
1396         }
1397     }
1398   *p = 0; /* Make sure to keep a string terminator. */
1399   return n;
1400 }
1401
1402
1403 /* If SPECIAL is NULL this function escapes in forms mode.  */
1404 static size_t
1405 escape_data (char *buffer, const void *data, size_t datalen,
1406              const char *special)
1407 {
1408   int forms = !special;
1409   const unsigned char *s;
1410   size_t n = 0;
1411
1412   if (forms)
1413     special = "%;?&=";
1414
1415   for (s = data; datalen; s++, datalen--)
1416     {
1417       if (forms && *s == ' ')
1418         {
1419           if (buffer)
1420             *buffer++ = '+';
1421           n++;
1422         }
1423       else if (forms && *s == '\n')
1424         {
1425           if (buffer)
1426             memcpy (buffer, "%0D%0A", 6);
1427           n += 6;
1428         }
1429       else if (forms && *s == '\r' && datalen > 1 && s[1] == '\n')
1430         {
1431           if (buffer)
1432             memcpy (buffer, "%0D%0A", 6);
1433           n += 6;
1434           s++;
1435           datalen--;
1436         }
1437       else if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
1438         {
1439           if (buffer)
1440             *(unsigned char*)buffer++ = *s;
1441           n++;
1442         }
1443       else
1444         {
1445           if (buffer)
1446             {
1447               snprintf (buffer, 4, "%%%02X", *s);
1448               buffer += 3;
1449             }
1450           n += 3;
1451         }
1452     }
1453   return n;
1454 }
1455
1456
1457 static int
1458 insert_escapes (char *buffer, const char *string,
1459                 const char *special)
1460 {
1461   return escape_data (buffer, string, strlen (string), special);
1462 }
1463
1464
1465 /* Allocate a new string from STRING using standard HTTP escaping as
1466    well as escaping of characters given in SPECIALS.  A common pattern
1467    for SPECIALS is "%;?&=". However it depends on the needs, for
1468    example "+" and "/: often needs to be escaped too.  Returns NULL on
1469    failure and sets ERRNO.  If SPECIAL is NULL a dedicated forms
1470    encoding mode is used. */
1471 char *
1472 http_escape_string (const char *string, const char *specials)
1473 {
1474   int n;
1475   char *buf;
1476
1477   n = insert_escapes (NULL, string, specials);
1478   buf = xtrymalloc (n+1);
1479   if (buf)
1480     {
1481       insert_escapes (buf, string, specials);
1482       buf[n] = 0;
1483     }
1484   return buf;
1485 }
1486
1487 /* Allocate a new string from {DATA,DATALEN} using standard HTTP
1488    escaping as well as escaping of characters given in SPECIALS.  A
1489    common pattern for SPECIALS is "%;?&=".  However it depends on the
1490    needs, for example "+" and "/: often needs to be escaped too.
1491    Returns NULL on failure and sets ERRNO.  If SPECIAL is NULL a
1492    dedicated forms encoding mode is used. */
1493 char *
1494 http_escape_data (const void *data, size_t datalen, const char *specials)
1495 {
1496   int n;
1497   char *buf;
1498
1499   n = escape_data (NULL, data, datalen, specials);
1500   buf = xtrymalloc (n+1);
1501   if (buf)
1502     {
1503       escape_data (buf, data, datalen, specials);
1504       buf[n] = 0;
1505     }
1506   return buf;
1507 }
1508
1509
1510 static uri_tuple_t
1511 parse_tuple (char *string)
1512 {
1513   char *p = string;
1514   char *p2;
1515   int n;
1516   uri_tuple_t tuple;
1517
1518   if ((p2 = strchr (p, '=')))
1519     *p2++ = 0;
1520   if ((n = remove_escapes (p)) < 0)
1521     return NULL; /* Bad URI. */
1522   if (n != strlen (p))
1523     return NULL; /* Name with a Nul in it. */
1524   tuple = xtrycalloc (1, sizeof *tuple);
1525   if (!tuple)
1526     return NULL; /* Out of core. */
1527   tuple->name = p;
1528   if (!p2) /* We have only the name, so we assume an empty value string. */
1529     {
1530       tuple->value = p + strlen (p);
1531       tuple->valuelen = 0;
1532       tuple->no_value = 1; /* Explicitly mark that we have seen no '='. */
1533     }
1534   else /* Name and value. */
1535     {
1536       if ((n = remove_escapes (p2)) < 0)
1537         {
1538           xfree (tuple);
1539           return NULL; /* Bad URI. */
1540         }
1541       tuple->value = p2;
1542       tuple->valuelen = n;
1543     }
1544   return tuple;
1545 }
1546
1547
1548 /* Return true if STRING is likely "hostname:port" or only "hostname".  */
1549 static int
1550 is_hostname_port (const char *string)
1551 {
1552   int colons = 0;
1553
1554   if (!string || !*string)
1555     return 0;
1556   for (; *string; string++)
1557     {
1558       if (*string == ':')
1559         {
1560           if (colons)
1561             return 0;
1562           if (!string[1])
1563             return 0;
1564           colons++;
1565         }
1566       else if (!colons && strchr (" \t\f\n\v_@[]/", *string))
1567         return 0; /* Invalid characters in hostname. */
1568       else if (colons && !digitp (string))
1569         return 0; /* Not a digit in the port.  */
1570     }
1571   return 1;
1572 }
1573
1574
1575 /*
1576  * Send a HTTP request to the server
1577  * Returns 0 if the request was successful
1578  */
1579 static gpg_error_t
1580 send_request (http_t hd, const char *httphost, const char *auth,
1581               const char *proxy, const char *srvtag, strlist_t headers)
1582 {
1583   gpg_error_t err;
1584   const char *server;
1585   char *request, *p;
1586   unsigned short port;
1587   const char *http_proxy = NULL;
1588   char *proxy_authstr = NULL;
1589   char *authstr = NULL;
1590   int sock;
1591
1592   if (hd->uri->use_tls && !hd->session)
1593     {
1594       log_error ("TLS requested but no session object provided\n");
1595       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1596     }
1597 #ifdef USE_TLS
1598   if (hd->uri->use_tls && !hd->session->tls_session)
1599     {
1600       log_error ("TLS requested but no GNUTLS context available\n");
1601       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1602     }
1603 #endif /*USE_TLS*/
1604
1605   if ((hd->flags & HTTP_FLAG_FORCE_TOR))
1606     {
1607       int mode;
1608
1609       if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
1610         {
1611           log_error ("Tor support is not available\n");
1612           return gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1613         }
1614     }
1615
1616   server = *hd->uri->host ? hd->uri->host : "localhost";
1617   port = hd->uri->port ? hd->uri->port : 80;
1618
1619   /* Try to use SNI.  */
1620 #ifdef USE_TLS
1621   if (hd->uri->use_tls)
1622     {
1623 # if HTTP_USE_GNUTLS
1624       int rc;
1625 # endif
1626
1627       xfree (hd->session->servername);
1628       hd->session->servername = xtrystrdup (httphost? httphost : server);
1629       if (!hd->session->servername)
1630         {
1631           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1632           return err;
1633         }
1634
1635 # if HTTP_USE_NTBTLS
1636       err = ntbtls_set_hostname (hd->session->tls_session,
1637                                  hd->session->servername);
1638       if (err)
1639         {
1640           log_info ("ntbtls_set_hostname failed: %s\n", gpg_strerror (err));
1641           return err;
1642         }
1643 # elif HTTP_USE_GNUTLS
1644       rc = gnutls_server_name_set (hd->session->tls_session,
1645                                    GNUTLS_NAME_DNS,
1646                                    hd->session->servername,
1647                                    strlen (hd->session->servername));
1648       if (rc < 0)
1649         log_info ("gnutls_server_name_set failed: %s\n", gnutls_strerror (rc));
1650 # endif /*HTTP_USE_GNUTLS*/
1651     }
1652 #endif /*USE_TLS*/
1653
1654   if ( (proxy && *proxy)
1655        || ( (hd->flags & HTTP_FLAG_TRY_PROXY)
1656             && (http_proxy = getenv (HTTP_PROXY_ENV))
1657             && *http_proxy ))
1658     {
1659       parsed_uri_t uri;
1660
1661       if (proxy)
1662         http_proxy = proxy;
1663
1664       err = parse_uri (&uri, http_proxy, 0, 0);
1665       if (gpg_err_code (err) == GPG_ERR_INV_URI
1666           && is_hostname_port (http_proxy))
1667         {
1668           /* Retry assuming a "hostname:port" string.  */
1669           char *tmpname = strconcat ("http://", http_proxy, NULL);
1670           if (tmpname && !parse_uri (&uri, tmpname, 0, 0))
1671             err = 0;
1672           xfree (tmpname);
1673         }
1674
1675       if (err)
1676         ;
1677       else if (!strcmp (uri->scheme, "http") || !strcmp (uri->scheme, "socks4"))
1678         ;
1679       else if (!strcmp (uri->scheme, "socks5h"))
1680         err = gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1681       else
1682         err = gpg_err_make (default_errsource, GPG_ERR_INV_URI);
1683
1684       if (err)
1685         {
1686           log_error ("invalid HTTP proxy (%s): %s\n",
1687                      http_proxy, gpg_strerror (err));
1688           return gpg_err_make (default_errsource, GPG_ERR_CONFIGURATION);
1689         }
1690
1691       if (uri->auth)
1692         {
1693           remove_escapes (uri->auth);
1694           proxy_authstr = make_header_line ("Proxy-Authorization: Basic ",
1695                                             "\r\n",
1696                                             uri->auth, strlen(uri->auth));
1697           if (!proxy_authstr)
1698             {
1699               err = gpg_err_make (default_errsource,
1700                                   gpg_err_code_from_syserror ());
1701               http_release_parsed_uri (uri);
1702               return err;
1703             }
1704         }
1705
1706       err = connect_server (*uri->host ? uri->host : "localhost",
1707                             uri->port ? uri->port : 80,
1708                             hd->flags, srvtag, &sock);
1709       http_release_parsed_uri (uri);
1710     }
1711   else
1712     {
1713       err = connect_server (server, port, hd->flags, srvtag, &sock);
1714     }
1715
1716   if (err)
1717     {
1718       xfree (proxy_authstr);
1719       return err;
1720     }
1721   hd->sock = my_socket_new (sock);
1722   if (!hd->sock)
1723     {
1724       xfree (proxy_authstr);
1725       return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1726     }
1727
1728
1729 #if HTTP_USE_NTBTLS
1730   if (hd->uri->use_tls)
1731     {
1732       estream_t in, out;
1733
1734       my_socket_ref (hd->sock);
1735
1736       in = es_fdopen_nc (hd->sock->fd, "rb");
1737       if (!in)
1738         {
1739           err = gpg_error_from_syserror ();
1740           xfree (proxy_authstr);
1741           return err;
1742         }
1743
1744       out = es_fdopen_nc (hd->sock->fd, "wb");
1745       if (!out)
1746         {
1747           err = gpg_error_from_syserror ();
1748           es_fclose (in);
1749           xfree (proxy_authstr);
1750           return err;
1751         }
1752
1753       err = ntbtls_set_transport (hd->session->tls_session, in, out);
1754       if (err)
1755         {
1756           log_info ("TLS set_transport failed: %s <%s>\n",
1757                     gpg_strerror (err), gpg_strsource (err));
1758           xfree (proxy_authstr);
1759           return err;
1760         }
1761
1762 #ifdef HTTP_USE_NTBTLS
1763       if (hd->session->verify_cb)
1764         {
1765           err = ntbtls_set_verify_cb (hd->session->tls_session,
1766                                       my_ntbtls_verify_cb, hd);
1767           if (err)
1768             {
1769               log_error ("ntbtls_set_verify_cb failed: %s\n",
1770                          gpg_strerror (err));
1771               xfree (proxy_authstr);
1772               return err;
1773             }
1774         }
1775 #endif /*HTTP_USE_NTBTLS*/
1776
1777       while ((err = ntbtls_handshake (hd->session->tls_session)))
1778         {
1779           switch (err)
1780             {
1781             default:
1782               log_info ("TLS handshake failed: %s <%s>\n",
1783                         gpg_strerror (err), gpg_strsource (err));
1784               xfree (proxy_authstr);
1785               return err;
1786             }
1787         }
1788
1789       hd->session->verify.done = 0;
1790
1791       /* Try the available verify callbacks until one returns success
1792        * or a real error.  Note that NTBTLS does the verification
1793        * during the handshake via   */
1794 #ifdef HTTP_USE_NTBTLS
1795       err = 0; /* Fixme check that the CB has been called.  */
1796 #else
1797       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1798 #endif
1799
1800       if (hd->session->verify_cb
1801           && gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR
1802           && gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
1803         err = hd->session->verify_cb (hd->session->verify_cb_value,
1804                                       hd, hd->session,
1805                                       (hd->flags | hd->session->flags),
1806                                       hd->session->tls_session);
1807
1808       if (tls_callback
1809           && gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR
1810           && gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
1811         err = tls_callback (hd, hd->session, 0);
1812
1813       if (gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR
1814           && gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
1815         err = http_verify_server_credentials (hd->session);
1816
1817       if (err)
1818         {
1819           log_info ("TLS connection authentication failed: %s <%s>\n",
1820                     gpg_strerror (err), gpg_strsource (err));
1821           xfree (proxy_authstr);
1822           return err;
1823         }
1824
1825     }
1826 #elif HTTP_USE_GNUTLS
1827   if (hd->uri->use_tls)
1828     {
1829       int rc;
1830
1831       my_socket_ref (hd->sock);
1832       gnutls_transport_set_ptr (hd->session->tls_session, hd->sock);
1833       gnutls_transport_set_pull_function (hd->session->tls_session,
1834                                           my_gnutls_read);
1835       gnutls_transport_set_push_function (hd->session->tls_session,
1836                                           my_gnutls_write);
1837
1838       do
1839         {
1840           rc = gnutls_handshake (hd->session->tls_session);
1841         }
1842       while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
1843       if (rc < 0)
1844         {
1845           if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED
1846               || rc == GNUTLS_E_FATAL_ALERT_RECEIVED)
1847             {
1848               gnutls_alert_description_t alertno;
1849               const char *alertstr;
1850
1851               alertno = gnutls_alert_get (hd->session->tls_session);
1852               alertstr = gnutls_alert_get_name (alertno);
1853               log_info ("TLS handshake failed: %s (alert %d)\n",
1854                         alertstr, (int)alertno);
1855               if (alertno == GNUTLS_A_UNRECOGNIZED_NAME && server)
1856                 log_info ("  (sent server name '%s')\n", server);
1857             }
1858           else
1859             log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
1860           xfree (proxy_authstr);
1861           return gpg_err_make (default_errsource, GPG_ERR_NETWORK);
1862         }
1863
1864       hd->session->verify.done = 0;
1865       if (tls_callback)
1866         err = tls_callback (hd, hd->session, 0);
1867       else
1868         err = http_verify_server_credentials (hd->session);
1869       if (err)
1870         {
1871           log_info ("TLS connection authentication failed: %s\n",
1872                     gpg_strerror (err));
1873           xfree (proxy_authstr);
1874           return err;
1875         }
1876     }
1877 #endif /*HTTP_USE_GNUTLS*/
1878
1879   if (auth || hd->uri->auth)
1880     {
1881       char *myauth;
1882
1883       if (auth)
1884         {
1885           myauth = xtrystrdup (auth);
1886           if (!myauth)
1887             {
1888               xfree (proxy_authstr);
1889               return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1890             }
1891           remove_escapes (myauth);
1892         }
1893       else
1894         {
1895           remove_escapes (hd->uri->auth);
1896           myauth = hd->uri->auth;
1897         }
1898
1899       authstr = make_header_line ("Authorization: Basic ", "\r\n",
1900                                   myauth, strlen (myauth));
1901       if (auth)
1902         xfree (myauth);
1903
1904       if (!authstr)
1905         {
1906           xfree (proxy_authstr);
1907           return gpg_err_make (default_errsource,
1908                                gpg_err_code_from_syserror ());
1909         }
1910     }
1911
1912   p = build_rel_path (hd->uri);
1913   if (!p)
1914     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1915
1916   if (http_proxy && *http_proxy)
1917     {
1918       request = es_bsprintf
1919         ("%s %s://%s:%hu%s%s HTTP/1.0\r\n%s%s",
1920          hd->req_type == HTTP_REQ_GET ? "GET" :
1921          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
1922          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
1923          hd->uri->use_tls? "https" : "http",
1924          httphost? httphost : server,
1925          port, *p == '/' ? "" : "/", p,
1926          authstr ? authstr : "",
1927          proxy_authstr ? proxy_authstr : "");
1928     }
1929   else
1930     {
1931       char portstr[35];
1932
1933       if (port == (hd->uri->use_tls? 443 : 80))
1934         *portstr = 0;
1935       else
1936         snprintf (portstr, sizeof portstr, ":%u", port);
1937
1938       request = es_bsprintf
1939         ("%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
1940          hd->req_type == HTTP_REQ_GET ? "GET" :
1941          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
1942          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
1943          *p == '/' ? "" : "/", p,
1944          httphost? httphost : server,
1945          portstr,
1946          authstr? authstr:"");
1947     }
1948   xfree (p);
1949   if (!request)
1950     {
1951       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1952       xfree (authstr);
1953       xfree (proxy_authstr);
1954       return err;
1955     }
1956
1957   if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
1958     log_debug_with_string (request, "http.c:request:");
1959
1960   /* First setup estream so that we can write even the first line
1961      using estream.  This is also required for the sake of gnutls. */
1962   {
1963     cookie_t cookie;
1964
1965     cookie = xtrycalloc (1, sizeof *cookie);
1966     if (!cookie)
1967       {
1968         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1969         goto leave;
1970       }
1971     cookie->sock = my_socket_ref (hd->sock);
1972     hd->write_cookie = cookie;
1973     cookie->use_tls = hd->uri->use_tls;
1974     cookie->session = http_session_ref (hd->session);
1975
1976     hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1977     if (!hd->fp_write)
1978       {
1979         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1980         my_socket_unref (cookie->sock, NULL, NULL);
1981         xfree (cookie);
1982         hd->write_cookie = NULL;
1983       }
1984     else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
1985       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1986     else
1987       err = 0;
1988
1989   if (!err)
1990     {
1991       for (;headers; headers=headers->next)
1992         {
1993           if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
1994             log_debug_with_string (headers->d, "http.c:request-header:");
1995           if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write))
1996               || (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write)))
1997             {
1998               err = gpg_err_make (default_errsource,
1999                                   gpg_err_code_from_syserror ());
2000               break;
2001             }
2002         }
2003     }
2004   }
2005
2006  leave:
2007   es_free (request);
2008   xfree (authstr);
2009   xfree (proxy_authstr);
2010
2011   return err;
2012 }
2013
2014
2015 /*
2016  * Build the relative path from the parsed URI.  Minimal
2017  * implementation.  May return NULL in case of memory failure; errno
2018  * is then set accordingly.
2019  */
2020 static char *
2021 build_rel_path (parsed_uri_t uri)
2022 {
2023   uri_tuple_t r;
2024   char *rel_path, *p;
2025   int n;
2026
2027   /* Count the needed space. */
2028   n = insert_escapes (NULL, uri->path, "%;?&");
2029   /* TODO: build params. */
2030   for (r = uri->query; r; r = r->next)
2031     {
2032       n++; /* '?'/'&' */
2033       n += insert_escapes (NULL, r->name, "%;?&=");
2034       if (!r->no_value)
2035         {
2036           n++; /* '=' */
2037           n += insert_escapes (NULL, r->value, "%;?&=");
2038         }
2039     }
2040   n++;
2041
2042   /* Now allocate and copy. */
2043   p = rel_path = xtrymalloc (n);
2044   if (!p)
2045     return NULL;
2046   n = insert_escapes (p, uri->path, "%;?&");
2047   p += n;
2048   /* TODO: add params. */
2049   for (r = uri->query; r; r = r->next)
2050     {
2051       *p++ = r == uri->query ? '?' : '&';
2052       n = insert_escapes (p, r->name, "%;?&=");
2053       p += n;
2054       if (!r->no_value)
2055         {
2056           *p++ = '=';
2057           /* TODO: Use valuelen. */
2058           n = insert_escapes (p, r->value, "%;?&=");
2059           p += n;
2060         }
2061     }
2062   *p = 0;
2063   return rel_path;
2064 }
2065
2066
2067 /* Transform a header name into a standard capitalized format; e.g.
2068    "Content-Type".  Conversion stops at the colon.  As usual we don't
2069    use the localized versions of ctype.h. */
2070 static void
2071 capitalize_header_name (char *name)
2072 {
2073   int first = 1;
2074
2075   for (; *name && *name != ':'; name++)
2076     {
2077       if (*name == '-')
2078         first = 1;
2079       else if (first)
2080         {
2081           if (*name >= 'a' && *name <= 'z')
2082             *name = *name - 'a' + 'A';
2083           first = 0;
2084         }
2085       else if (*name >= 'A' && *name <= 'Z')
2086         *name = *name - 'A' + 'a';
2087     }
2088 }
2089
2090
2091 /* Store an HTTP header line in LINE away.  Line continuation is
2092    supported as well as merging of headers with the same name. This
2093    function may modify LINE. */
2094 static gpg_err_code_t
2095 store_header (http_t hd, char *line)
2096 {
2097   size_t n;
2098   char *p, *value;
2099   header_t h;
2100
2101   n = strlen (line);
2102   if (n && line[n-1] == '\n')
2103     {
2104       line[--n] = 0;
2105       if (n && line[n-1] == '\r')
2106         line[--n] = 0;
2107     }
2108   if (!n)  /* we are never called to hit this. */
2109     return GPG_ERR_BUG;
2110   if (*line == ' ' || *line == '\t')
2111     {
2112       /* Continuation. This won't happen too often as it is not
2113          recommended.  We use a straightforward implementaion. */
2114       if (!hd->headers)
2115         return GPG_ERR_PROTOCOL_VIOLATION;
2116       n += strlen (hd->headers->value);
2117       p = xtrymalloc (n+1);
2118       if (!p)
2119         return gpg_err_code_from_syserror ();
2120       strcpy (stpcpy (p, hd->headers->value), line);
2121       xfree (hd->headers->value);
2122       hd->headers->value = p;
2123       return 0;
2124     }
2125
2126   capitalize_header_name (line);
2127   p = strchr (line, ':');
2128   if (!p)
2129     return GPG_ERR_PROTOCOL_VIOLATION;
2130   *p++ = 0;
2131   while (*p == ' ' || *p == '\t')
2132     p++;
2133   value = p;
2134
2135   for (h=hd->headers; h; h = h->next)
2136     if ( !strcmp (h->name, line) )
2137       break;
2138   if (h)
2139     {
2140       /* We have already seen a line with that name.  Thus we assume
2141        * it is a comma separated list and merge them.  */
2142       p = strconcat (h->value, ",", value, NULL);
2143       if (!p)
2144         return gpg_err_code_from_syserror ();
2145       xfree (h->value);
2146       h->value = p;
2147       return 0;
2148     }
2149
2150   /* Append a new header. */
2151   h = xtrymalloc (sizeof *h + strlen (line));
2152   if (!h)
2153     return gpg_err_code_from_syserror ();
2154   strcpy (h->name, line);
2155   h->value = xtrymalloc (strlen (value)+1);
2156   if (!h->value)
2157     {
2158       xfree (h);
2159       return gpg_err_code_from_syserror ();
2160     }
2161   strcpy (h->value, value);
2162   h->next = hd->headers;
2163   hd->headers = h;
2164
2165   return 0;
2166 }
2167
2168
2169 /* Return the header NAME from the last response.  The returned value
2170    is valid as along as HD has not been closed and no other request
2171    has been send. If the header was not found, NULL is returned.  NAME
2172    must be canonicalized, that is the first letter of each dash
2173    delimited part must be uppercase and all other letters lowercase.  */
2174 const char *
2175 http_get_header (http_t hd, const char *name)
2176 {
2177   header_t h;
2178
2179   for (h=hd->headers; h; h = h->next)
2180     if ( !strcmp (h->name, name) )
2181       return h->value;
2182   return NULL;
2183 }
2184
2185
2186 /* Return a newly allocated and NULL terminated array with pointers to
2187    header names.  The array must be released with xfree() and its
2188    content is only values as long as no other request has been
2189    send.  */
2190 const char **
2191 http_get_header_names (http_t hd)
2192 {
2193   const char **array;
2194   size_t n;
2195   header_t h;
2196
2197   for (n=0, h = hd->headers; h; h = h->next)
2198     n++;
2199   array = xtrycalloc (n+1, sizeof *array);
2200   if (array)
2201     {
2202       for (n=0, h = hd->headers; h; h = h->next)
2203         array[n++] = h->name;
2204     }
2205
2206   return array;
2207 }
2208
2209
2210 /*
2211  * Parse the response from a server.
2212  * Returns: Errorcode and sets some files in the handle
2213  */
2214 static gpg_err_code_t
2215 parse_response (http_t hd)
2216 {
2217   char *line, *p, *p2;
2218   size_t maxlen, len;
2219   cookie_t cookie = hd->read_cookie;
2220   const char *s;
2221
2222   /* Delete old header lines.  */
2223   while (hd->headers)
2224     {
2225       header_t tmp = hd->headers->next;
2226       xfree (hd->headers->value);
2227       xfree (hd->headers);
2228       hd->headers = tmp;
2229     }
2230
2231   /* Wait for the status line. */
2232   do
2233     {
2234       maxlen = MAX_LINELEN;
2235       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2236       line = hd->buffer;
2237       if (!line)
2238         return gpg_err_code_from_syserror (); /* Out of core. */
2239       if (!maxlen)
2240         return GPG_ERR_TRUNCATED; /* Line has been truncated. */
2241       if (!len)
2242         return GPG_ERR_EOF;
2243
2244       if ((hd->flags & HTTP_FLAG_LOG_RESP))
2245         log_debug_with_string (line, "http.c:response:\n");
2246     }
2247   while (!*line);
2248
2249   if ((p = strchr (line, '/')))
2250     *p++ = 0;
2251   if (!p || strcmp (line, "HTTP"))
2252     return 0; /* Assume http 0.9. */
2253
2254   if ((p2 = strpbrk (p, " \t")))
2255     {
2256       *p2++ = 0;
2257       p2 += strspn (p2, " \t");
2258     }
2259   if (!p2)
2260     return 0; /* Also assume http 0.9. */
2261   p = p2;
2262   /* TODO: Add HTTP version number check. */
2263   if ((p2 = strpbrk (p, " \t")))
2264     *p2++ = 0;
2265   if (!isdigit ((unsigned int)p[0]) || !isdigit ((unsigned int)p[1])
2266       || !isdigit ((unsigned int)p[2]) || p[3])
2267     {
2268       /* Malformed HTTP status code - assume http 0.9. */
2269       hd->is_http_0_9 = 1;
2270       hd->status_code = 200;
2271       return 0;
2272     }
2273   hd->status_code = atoi (p);
2274
2275   /* Skip all the header lines and wait for the empty line. */
2276   do
2277     {
2278       maxlen = MAX_LINELEN;
2279       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2280       line = hd->buffer;
2281       if (!line)
2282         return gpg_err_code_from_syserror (); /* Out of core. */
2283       /* Note, that we can silently ignore truncated lines. */
2284       if (!len)
2285         return GPG_ERR_EOF;
2286       /* Trim line endings of empty lines. */
2287       if ((*line == '\r' && line[1] == '\n') || *line == '\n')
2288         *line = 0;
2289       if ((hd->flags & HTTP_FLAG_LOG_RESP))
2290         log_info ("http.c:RESP: '%.*s'\n",
2291                   (int)strlen(line)-(*line&&line[1]?2:0),line);
2292       if (*line)
2293         {
2294           gpg_err_code_t ec = store_header (hd, line);
2295           if (ec)
2296             return ec;
2297         }
2298     }
2299   while (len && *line);
2300
2301   cookie->content_length_valid = 0;
2302   if (!(hd->flags & HTTP_FLAG_IGNORE_CL))
2303     {
2304       s = http_get_header (hd, "Content-Length");
2305       if (s)
2306         {
2307           cookie->content_length_valid = 1;
2308           cookie->content_length = string_to_u64 (s);
2309         }
2310     }
2311
2312   return 0;
2313 }
2314
2315 #if 0
2316 static int
2317 start_server ()
2318 {
2319   struct sockaddr_in mya;
2320   struct sockaddr_in peer;
2321   int fd, client;
2322   fd_set rfds;
2323   int addrlen;
2324   int i;
2325
2326   if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
2327     {
2328       log_error ("socket() failed: %s\n", strerror (errno));
2329       return -1;
2330     }
2331   i = 1;
2332   if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (byte *) & i, sizeof (i)))
2333     log_info ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno));
2334
2335   mya.sin_family = AF_INET;
2336   memset (&mya.sin_addr, 0, sizeof (mya.sin_addr));
2337   mya.sin_port = htons (11371);
2338
2339   if (bind (fd, (struct sockaddr *) &mya, sizeof (mya)))
2340     {
2341       log_error ("bind to port 11371 failed: %s\n", strerror (errno));
2342       sock_close (fd);
2343       return -1;
2344     }
2345
2346   if (listen (fd, 5))
2347     {
2348       log_error ("listen failed: %s\n", strerror (errno));
2349       sock_close (fd);
2350       return -1;
2351     }
2352
2353   for (;;)
2354     {
2355       FD_ZERO (&rfds);
2356       FD_SET (fd, &rfds);
2357
2358       if (my_select (fd + 1, &rfds, NULL, NULL, NULL) <= 0)
2359         continue;               /* ignore any errors */
2360
2361       if (!FD_ISSET (fd, &rfds))
2362         continue;
2363
2364       addrlen = sizeof peer;
2365       client = my_accept (fd, (struct sockaddr *) &peer, &addrlen);
2366       if (client == -1)
2367         continue;               /* oops */
2368
2369       log_info ("connect from %s\n", inet_ntoa (peer.sin_addr));
2370
2371       fflush (stdout);
2372       fflush (stderr);
2373       if (!fork ())
2374         {
2375           int c;
2376           FILE *fp;
2377
2378           fp = fdopen (client, "r");
2379           while ((c = getc (fp)) != EOF)
2380             putchar (c);
2381           fclose (fp);
2382           exit (0);
2383         }
2384       sock_close (client);
2385     }
2386
2387
2388   return 0;
2389 }
2390 #endif
2391
2392
2393
2394 /* Return true if SOCKS shall be used.  This is the case if tor_mode
2395  * is enabled and the desired address is not the loopback address.
2396  * This function is basically a copy of the same internal fucntion in
2397  * Libassuan.  */
2398 static int
2399 use_socks (struct sockaddr *addr)
2400 {
2401   int mode;
2402
2403   if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
2404     return 0;  /* Not in Tor mode.  */
2405   else if (addr->sa_family == AF_INET6)
2406     {
2407       struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr;
2408       const unsigned char *s;
2409       int i;
2410
2411       s = (unsigned char *)&addr_in6->sin6_addr.s6_addr;
2412       if (s[15] != 1)
2413         return 1;   /* Last octet is not 1 - not the loopback address.  */
2414       for (i=0; i < 15; i++, s++)
2415         if (*s)
2416           return 1; /* Non-zero octet found - not the loopback address.  */
2417
2418       return 0; /* This is the loopback address.  */
2419     }
2420   else if (addr->sa_family == AF_INET)
2421     {
2422       struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
2423
2424       if (*(unsigned char*)&addr_in->sin_addr.s_addr == 127)
2425         return 0; /* Loopback (127.0.0.0/8) */
2426
2427       return 1;
2428     }
2429   else
2430     return 0;
2431 }
2432
2433
2434 /* Wrapper around assuan_sock_new which takes the domain from an
2435  * address parameter.  */
2436 static assuan_fd_t
2437 my_sock_new_for_addr (struct sockaddr *addr, int type, int proto)
2438 {
2439   int domain;
2440
2441   if (use_socks (addr))
2442     {
2443       /* Libassaun always uses 127.0.0.1 to connect to the socks
2444        * server (i.e. the Tor daemon).  */
2445       domain = AF_INET;
2446     }
2447   else
2448     domain = addr->sa_family;
2449
2450   return assuan_sock_new (domain, type, proto);
2451 }
2452
2453
2454 /* Actually connect to a server.  On success 0 is returned and the
2455  * file descriptor for the socket is stored at R_SOCK; on error an
2456  * error code is returned and ASSUAN_INVALID_FD is stored at
2457  * R_SOCK.  */
2458 static gpg_error_t
2459 connect_server (const char *server, unsigned short port,
2460                 unsigned int flags, const char *srvtag, assuan_fd_t *r_sock)
2461 {
2462   gpg_error_t err;
2463   assuan_fd_t sock = ASSUAN_INVALID_FD;
2464   unsigned int srvcount = 0;
2465   int hostfound = 0;
2466   int anyhostaddr = 0;
2467   int srv, connected;
2468   gpg_error_t last_err = 0;
2469   struct srventry *serverlist = NULL;
2470
2471   *r_sock = ASSUAN_INVALID_FD;
2472
2473 #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
2474   init_sockets ();
2475 #endif /*Windows*/
2476
2477   /* Onion addresses require special treatment.  */
2478   if (is_onion_address (server))
2479     {
2480 #ifdef ASSUAN_SOCK_TOR
2481
2482       if (opt_debug)
2483         log_debug ("http.c:connect_server:onion: name='%s' port=%hu\n",
2484                    server, port);
2485       sock = assuan_sock_connect_byname (server, port, 0, NULL,
2486                                          ASSUAN_SOCK_TOR);
2487       if (sock == ASSUAN_INVALID_FD)
2488         {
2489           err = gpg_err_make (default_errsource,
2490                               (errno == EHOSTUNREACH)? GPG_ERR_UNKNOWN_HOST
2491                               : gpg_err_code_from_syserror ());
2492           log_error ("can't connect to '%s': %s\n", server, gpg_strerror (err));
2493           return err;
2494         }
2495
2496       notify_netactivity ();
2497       *r_sock = sock;
2498       return 0;
2499
2500 #else /*!ASSUAN_SOCK_TOR*/
2501
2502       err = gpg_err_make (default_errsource, GPG_ERR_ENETUNREACH);
2503       return ASSUAN_INVALID_FD;
2504
2505 #endif /*!HASSUAN_SOCK_TOR*/
2506     }
2507
2508   /* Do the SRV thing */
2509   if (srvtag)
2510     {
2511       err = get_dns_srv (server, srvtag, NULL, &serverlist, &srvcount);
2512       if (err)
2513         log_info ("getting '%s' SRV for '%s' failed: %s\n",
2514                   srvtag, server, gpg_strerror (err));
2515       /* Note that on error SRVCOUNT is zero.  */
2516       err = 0;
2517     }
2518
2519   if (!serverlist)
2520     {
2521       /* Either we're not using SRV, or the SRV lookup failed.  Make
2522          up a fake SRV record. */
2523       serverlist = xtrycalloc (1, sizeof *serverlist);
2524       if (!serverlist)
2525         return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2526
2527       serverlist->port = port;
2528       strncpy (serverlist->target, server, DIMof (struct srventry, target));
2529       serverlist->target[DIMof (struct srventry, target)-1] = '\0';
2530       srvcount = 1;
2531     }
2532
2533   connected = 0;
2534   for (srv=0; srv < srvcount && !connected; srv++)
2535     {
2536       dns_addrinfo_t aibuf, ai;
2537
2538       if (opt_debug)
2539         log_debug ("http.c:connect_server: trying name='%s' port=%hu\n",
2540                    serverlist[srv].target, port);
2541       err = resolve_dns_name (serverlist[srv].target, port, 0, SOCK_STREAM,
2542                               &aibuf, NULL);
2543       if (err)
2544         {
2545           log_info ("resolving '%s' failed: %s\n",
2546                     serverlist[srv].target, gpg_strerror (err));
2547           last_err = err;
2548           continue; /* Not found - try next one. */
2549         }
2550       hostfound = 1;
2551
2552       for (ai = aibuf; ai && !connected; ai = ai->next)
2553         {
2554           if (ai->family == AF_INET && (flags & HTTP_FLAG_IGNORE_IPv4))
2555             continue;
2556           if (ai->family == AF_INET6 && (flags & HTTP_FLAG_IGNORE_IPv6))
2557             continue;
2558
2559           if (sock != ASSUAN_INVALID_FD)
2560             assuan_sock_close (sock);
2561           sock = my_sock_new_for_addr (ai->addr, ai->socktype, ai->protocol);
2562           if (sock == ASSUAN_INVALID_FD)
2563             {
2564               err = gpg_err_make (default_errsource,
2565                                   gpg_err_code_from_syserror ());
2566               log_error ("error creating socket: %s\n", gpg_strerror (err));
2567               free_dns_addrinfo (aibuf);
2568               xfree (serverlist);
2569               return err;
2570             }
2571
2572           anyhostaddr = 1;
2573           if (assuan_sock_connect (sock, ai->addr, ai->addrlen))
2574             {
2575               last_err = gpg_err_make (default_errsource,
2576                                        gpg_err_code_from_syserror ());
2577             }
2578           else
2579             {
2580               connected = 1;
2581               notify_netactivity ();
2582             }
2583         }
2584       free_dns_addrinfo (aibuf);
2585     }
2586
2587   xfree (serverlist);
2588
2589   if (!connected)
2590     {
2591       if (!hostfound)
2592         log_error ("can't connect to '%s': %s\n",
2593                    server, "host not found");
2594       else if (!anyhostaddr)
2595         log_error ("can't connect to '%s': %s\n",
2596                    server, "no IP address for host");
2597       else
2598         {
2599 #ifdef HAVE_W32_SYSTEM
2600         log_error ("can't connect to '%s': ec=%d\n",
2601                    server, (int)WSAGetLastError());
2602 #else
2603         log_error ("can't connect to '%s': %s\n",
2604                    server, gpg_strerror (last_err));
2605 #endif
2606         }
2607       err = last_err? last_err : gpg_err_make (default_errsource,
2608                                                GPG_ERR_UNKNOWN_HOST);
2609       if (sock != ASSUAN_INVALID_FD)
2610         assuan_sock_close (sock);
2611       return err;
2612     }
2613
2614   *r_sock = sock;
2615   return 0;
2616 }
2617
2618
2619 static gpg_error_t
2620 write_server (int sock, const char *data, size_t length)
2621 {
2622   int nleft;
2623   int nwritten;
2624
2625   nleft = length;
2626   while (nleft > 0)
2627     {
2628 #if defined(HAVE_W32_SYSTEM)
2629 # if defined(USE_NPTH)
2630       npth_unprotect ();
2631 # endif
2632       nwritten = send (sock, data, nleft, 0);
2633 # if defined(USE_NPTH)
2634       npth_protect ();
2635 # endif
2636       if ( nwritten == SOCKET_ERROR )
2637         {
2638           log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
2639           return gpg_error (GPG_ERR_NETWORK);
2640         }
2641 #else /*!HAVE_W32_SYSTEM*/
2642 # ifdef USE_NPTH
2643       nwritten = npth_write (sock, data, nleft);
2644 # else
2645       nwritten = write (sock, data, nleft);
2646 # endif
2647       if (nwritten == -1)
2648         {
2649           if (errno == EINTR)
2650             continue;
2651           if (errno == EAGAIN)
2652             {
2653               struct timeval tv;
2654
2655               tv.tv_sec = 0;
2656               tv.tv_usec = 50000;
2657               my_select (0, NULL, NULL, NULL, &tv);
2658               continue;
2659             }
2660           log_info ("network write failed: %s\n", strerror (errno));
2661           return gpg_error_from_syserror ();
2662         }
2663 #endif /*!HAVE_W32_SYSTEM*/
2664       nleft -= nwritten;
2665       data += nwritten;
2666     }
2667
2668   return 0;
2669 }
2670
2671
2672 \f
2673 /* Read handler for estream.  */
2674 static gpgrt_ssize_t
2675 cookie_read (void *cookie, void *buffer, size_t size)
2676 {
2677   cookie_t c = cookie;
2678   int nread;
2679
2680   if (c->content_length_valid)
2681     {
2682       if (!c->content_length)
2683         return 0; /* EOF */
2684       if (c->content_length < size)
2685         size = c->content_length;
2686     }
2687
2688 #if HTTP_USE_NTBTLS
2689   if (c->use_tls && c->session && c->session->tls_session)
2690     {
2691       estream_t in, out;
2692
2693       ntbtls_get_stream (c->session->tls_session, &in, &out);
2694       nread = es_fread (buffer, 1, size, in);
2695       if (opt_debug)
2696         log_debug ("TLS network read: %d/%zu\n", nread, size);
2697     }
2698   else
2699 #elif HTTP_USE_GNUTLS
2700   if (c->use_tls && c->session && c->session->tls_session)
2701     {
2702     again:
2703       nread = gnutls_record_recv (c->session->tls_session, buffer, size);
2704       if (nread < 0)
2705         {
2706           if (nread == GNUTLS_E_INTERRUPTED)
2707             goto again;
2708           if (nread == GNUTLS_E_AGAIN)
2709             {
2710               struct timeval tv;
2711
2712               tv.tv_sec = 0;
2713               tv.tv_usec = 50000;
2714               my_select (0, NULL, NULL, NULL, &tv);
2715               goto again;
2716             }
2717           if (nread == GNUTLS_E_REHANDSHAKE)
2718             goto again; /* A client is allowed to just ignore this request. */
2719           if (nread == GNUTLS_E_PREMATURE_TERMINATION)
2720             {
2721               /* The server terminated the connection.  Close the TLS
2722                  session, and indicate EOF using a short read.  */
2723               close_tls_session (c->session);
2724               return 0;
2725             }
2726           log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
2727           gpg_err_set_errno (EIO);
2728           return -1;
2729         }
2730     }
2731   else
2732 #endif /*HTTP_USE_GNUTLS*/
2733     {
2734       do
2735         {
2736 #ifdef HAVE_W32_SYSTEM
2737           /* Under Windows we need to use recv for a socket.  */
2738 # if defined(USE_NPTH)
2739           npth_unprotect ();
2740 # endif
2741           nread = recv (c->sock->fd, buffer, size, 0);
2742 # if defined(USE_NPTH)
2743           npth_protect ();
2744 # endif
2745
2746 #else /*!HAVE_W32_SYSTEM*/
2747
2748 # ifdef USE_NPTH
2749           nread = npth_read (c->sock->fd, buffer, size);
2750 # else
2751           nread = read (c->sock->fd, buffer, size);
2752 # endif
2753
2754 #endif /*!HAVE_W32_SYSTEM*/
2755         }
2756       while (nread == -1 && errno == EINTR);
2757     }
2758
2759   if (c->content_length_valid && nread > 0)
2760     {
2761       if (nread < c->content_length)
2762         c->content_length -= nread;
2763       else
2764         c->content_length = 0;
2765     }
2766
2767   return (gpgrt_ssize_t)nread;
2768 }
2769
2770 /* Write handler for estream.  */
2771 static gpgrt_ssize_t
2772 cookie_write (void *cookie, const void *buffer_arg, size_t size)
2773 {
2774   const char *buffer = buffer_arg;
2775   cookie_t c = cookie;
2776   int nwritten = 0;
2777
2778 #if HTTP_USE_NTBTLS
2779   if (c->use_tls && c->session && c->session->tls_session)
2780     {
2781       estream_t in, out;
2782
2783       ntbtls_get_stream (c->session->tls_session, &in, &out);
2784       if (size == 0)
2785         es_fflush (out);
2786       else
2787         nwritten = es_fwrite (buffer, 1, size, out);
2788       if (opt_debug)
2789         log_debug ("TLS network write: %d/%zu\n", nwritten, size);
2790     }
2791   else
2792 #elif HTTP_USE_GNUTLS
2793   if (c->use_tls && c->session && c->session->tls_session)
2794     {
2795       int nleft = size;
2796       while (nleft > 0)
2797         {
2798           nwritten = gnutls_record_send (c->session->tls_session,
2799                                          buffer, nleft);
2800           if (nwritten <= 0)
2801             {
2802               if (nwritten == GNUTLS_E_INTERRUPTED)
2803                 continue;
2804               if (nwritten == GNUTLS_E_AGAIN)
2805                 {
2806                   struct timeval tv;
2807
2808                   tv.tv_sec = 0;
2809                   tv.tv_usec = 50000;
2810                   my_select (0, NULL, NULL, NULL, &tv);
2811                   continue;
2812                 }
2813               log_info ("TLS network write failed: %s\n",
2814                         gnutls_strerror (nwritten));
2815               gpg_err_set_errno (EIO);
2816               return -1;
2817             }
2818           nleft -= nwritten;
2819           buffer += nwritten;
2820         }
2821     }
2822   else
2823 #endif /*HTTP_USE_GNUTLS*/
2824     {
2825       if ( write_server (c->sock->fd, buffer, size) )
2826         {
2827           gpg_err_set_errno (EIO);
2828           nwritten = -1;
2829         }
2830       else
2831         nwritten = size;
2832     }
2833
2834   return (gpgrt_ssize_t)nwritten;
2835 }
2836
2837
2838 #ifdef HTTP_USE_GNUTLS
2839 /* Wrapper for gnutls_bye used by my_socket_unref.  */
2840 static void
2841 send_gnutls_bye (void *opaque)
2842 {
2843   tls_session_t tls_session = opaque;
2844   int ret;
2845
2846  again:
2847   do
2848     ret = gnutls_bye (tls_session, GNUTLS_SHUT_RDWR);
2849   while (ret == GNUTLS_E_INTERRUPTED);
2850   if (ret == GNUTLS_E_AGAIN)
2851     {
2852       struct timeval tv;
2853
2854       tv.tv_sec = 0;
2855       tv.tv_usec = 50000;
2856       my_select (0, NULL, NULL, NULL, &tv);
2857       goto again;
2858     }
2859 }
2860 #endif /*HTTP_USE_GNUTLS*/
2861
2862 /* Close handler for estream.  */
2863 static int
2864 cookie_close (void *cookie)
2865 {
2866   cookie_t c = cookie;
2867
2868   if (!c)
2869     return 0;
2870
2871 #if HTTP_USE_NTBTLS
2872   if (c->use_tls && c->session && c->session->tls_session)
2873     {
2874       /* FIXME!! Possibly call ntbtls_close_notify for close
2875          of write stream.  */
2876       my_socket_unref (c->sock, NULL, NULL);
2877     }
2878   else
2879 #elif HTTP_USE_GNUTLS
2880   if (c->use_tls && c->session && c->session->tls_session)
2881     my_socket_unref (c->sock, send_gnutls_bye, c->session->tls_session);
2882   else
2883 #endif /*HTTP_USE_GNUTLS*/
2884     if (c->sock)
2885       my_socket_unref (c->sock, NULL, NULL);
2886
2887   if (c->session)
2888     http_session_unref (c->session);
2889   xfree (c);
2890   return 0;
2891 }
2892
2893
2894
2895 \f
2896 /* Verify the credentials of the server.  Returns 0 on success and
2897    store the result in the session object.  */
2898 gpg_error_t
2899 http_verify_server_credentials (http_session_t sess)
2900 {
2901 #if HTTP_USE_GNUTLS
2902   static const char const errprefix[] = "TLS verification of peer failed";
2903   int rc;
2904   unsigned int status;
2905   const char *hostname;
2906   const gnutls_datum_t *certlist;
2907   unsigned int certlistlen;
2908   gnutls_x509_crt_t cert;
2909   gpg_error_t err = 0;
2910
2911   sess->verify.done = 1;
2912   sess->verify.status = 0;
2913   sess->verify.rc = GNUTLS_E_CERTIFICATE_ERROR;
2914
2915   if (gnutls_certificate_type_get (sess->tls_session) != GNUTLS_CRT_X509)
2916     {
2917       log_error ("%s: %s\n", errprefix, "not an X.509 certificate");
2918       sess->verify.rc = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
2919       return gpg_error (GPG_ERR_GENERAL);
2920     }
2921
2922   rc = gnutls_certificate_verify_peers2 (sess->tls_session, &status);
2923   if (rc)
2924     {
2925       log_error ("%s: %s\n", errprefix, gnutls_strerror (rc));
2926       if (!err)
2927         err = gpg_error (GPG_ERR_GENERAL);
2928     }
2929   else if (status)
2930     {
2931       log_error ("%s: status=0x%04x\n", errprefix, status);
2932 #if GNUTLS_VERSION_NUMBER >= 0x030104
2933       {
2934         gnutls_datum_t statusdat;
2935
2936         if (!gnutls_certificate_verification_status_print
2937             (status, GNUTLS_CRT_X509, &statusdat, 0))
2938           {
2939             log_info ("%s: %s\n", errprefix, statusdat.data);
2940             gnutls_free (statusdat.data);
2941           }
2942       }
2943 #endif /*gnutls >= 3.1.4*/
2944
2945       sess->verify.status = status;
2946       if (!err)
2947         err = gpg_error (GPG_ERR_GENERAL);
2948     }
2949
2950   hostname = sess->servername;
2951   if (!hostname || !strchr (hostname, '.'))
2952     {
2953       log_error ("%s: %s\n", errprefix, "hostname missing");
2954       if (!err)
2955         err = gpg_error (GPG_ERR_GENERAL);
2956     }
2957
2958   certlist = gnutls_certificate_get_peers (sess->tls_session, &certlistlen);
2959   if (!certlistlen)
2960     {
2961       log_error ("%s: %s\n", errprefix, "server did not send a certificate");
2962       if (!err)
2963         err = gpg_error (GPG_ERR_GENERAL);
2964
2965       /* Need to stop here.  */
2966       if (err)
2967         return err;
2968     }
2969
2970   rc = gnutls_x509_crt_init (&cert);
2971   if (rc < 0)
2972     {
2973       if (!err)
2974         err = gpg_error (GPG_ERR_GENERAL);
2975       if (err)
2976         return err;
2977     }
2978
2979   rc = gnutls_x509_crt_import (cert, &certlist[0], GNUTLS_X509_FMT_DER);
2980   if (rc < 0)
2981     {
2982       log_error ("%s: %s: %s\n", errprefix, "error importing certificate",
2983                  gnutls_strerror (rc));
2984       if (!err)
2985         err = gpg_error (GPG_ERR_GENERAL);
2986     }
2987
2988   if (!gnutls_x509_crt_check_hostname (cert, hostname))
2989     {
2990       log_error ("%s: %s\n", errprefix, "hostname does not match");
2991       if (!err)
2992         err = gpg_error (GPG_ERR_GENERAL);
2993     }
2994
2995   gnutls_x509_crt_deinit (cert);
2996
2997   if (!err)
2998     sess->verify.rc = 0;
2999
3000   if (sess->cert_log_cb)
3001     {
3002       const void *bufarr[10];
3003       size_t buflenarr[10];
3004       size_t n;
3005
3006       for (n = 0; n < certlistlen && n < DIM (bufarr)-1; n++)
3007         {
3008           bufarr[n] = certlist[n].data;
3009           buflenarr[n] = certlist[n].size;
3010         }
3011       bufarr[n] = NULL;
3012       buflenarr[n] = 0;
3013       sess->cert_log_cb (sess, err, hostname, bufarr, buflenarr);
3014     }
3015
3016   return err;
3017 #else /*!HTTP_USE_GNUTLS*/
3018   (void)sess;
3019   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
3020 #endif
3021 }
3022
3023 /* Return the first query variable with the specified key.  If there
3024    is no such variable, return NULL.  */
3025 struct uri_tuple_s *
3026 uri_query_lookup (parsed_uri_t uri, const char *key)
3027 {
3028   struct uri_tuple_s *t;
3029
3030   for (t = uri->query; t; t = t->next)
3031     if (strcmp (t->name, key) == 0)
3032       return t;
3033
3034   return NULL;
3035 }