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