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