chiark / gitweb /
dirmngr: Ignore warning alerts in the GNUTLS handshake.
[gnupg2.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     handshake_again:
1851       do
1852         {
1853           rc = gnutls_handshake (hd->session->tls_session);
1854         }
1855       while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
1856       if (rc < 0)
1857         {
1858           if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED
1859               || rc == GNUTLS_E_FATAL_ALERT_RECEIVED)
1860             {
1861               gnutls_alert_description_t alertno;
1862               const char *alertstr;
1863
1864               alertno = gnutls_alert_get (hd->session->tls_session);
1865               alertstr = gnutls_alert_get_name (alertno);
1866               log_info ("TLS handshake %s: %s (alert %d)\n",
1867                         rc == GNUTLS_E_WARNING_ALERT_RECEIVED
1868                         ? "warning" : "failed",
1869                         alertstr, (int)alertno);
1870               if (alertno == GNUTLS_A_UNRECOGNIZED_NAME && server)
1871                 log_info ("  (sent server name '%s')\n", server);
1872
1873               if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED)
1874                 goto handshake_again;
1875             }
1876           else
1877             log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
1878           xfree (proxy_authstr);
1879           return gpg_err_make (default_errsource, GPG_ERR_NETWORK);
1880         }
1881
1882       hd->session->verify.done = 0;
1883       if (tls_callback)
1884         err = tls_callback (hd, hd->session, 0);
1885       else
1886         err = http_verify_server_credentials (hd->session);
1887       if (err)
1888         {
1889           log_info ("TLS connection authentication failed: %s\n",
1890                     gpg_strerror (err));
1891           xfree (proxy_authstr);
1892           return err;
1893         }
1894     }
1895 #endif /*HTTP_USE_GNUTLS*/
1896
1897   if (auth || hd->uri->auth)
1898     {
1899       char *myauth;
1900
1901       if (auth)
1902         {
1903           myauth = xtrystrdup (auth);
1904           if (!myauth)
1905             {
1906               xfree (proxy_authstr);
1907               return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1908             }
1909           remove_escapes (myauth);
1910         }
1911       else
1912         {
1913           remove_escapes (hd->uri->auth);
1914           myauth = hd->uri->auth;
1915         }
1916
1917       authstr = make_header_line ("Authorization: Basic ", "\r\n",
1918                                   myauth, strlen (myauth));
1919       if (auth)
1920         xfree (myauth);
1921
1922       if (!authstr)
1923         {
1924           xfree (proxy_authstr);
1925           return gpg_err_make (default_errsource,
1926                                gpg_err_code_from_syserror ());
1927         }
1928     }
1929
1930   p = build_rel_path (hd->uri);
1931   if (!p)
1932     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1933
1934   if (http_proxy && *http_proxy)
1935     {
1936       request = es_bsprintf
1937         ("%s %s://%s:%hu%s%s HTTP/1.0\r\n%s%s",
1938          hd->req_type == HTTP_REQ_GET ? "GET" :
1939          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
1940          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
1941          hd->uri->use_tls? "https" : "http",
1942          httphost? httphost : server,
1943          port, *p == '/' ? "" : "/", p,
1944          authstr ? authstr : "",
1945          proxy_authstr ? proxy_authstr : "");
1946     }
1947   else
1948     {
1949       char portstr[35];
1950
1951       if (port == 80)
1952         *portstr = 0;
1953       else
1954         snprintf (portstr, sizeof portstr, ":%u", port);
1955
1956       request = es_bsprintf
1957         ("%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
1958          hd->req_type == HTTP_REQ_GET ? "GET" :
1959          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
1960          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
1961          *p == '/' ? "" : "/", p,
1962          httphost? httphost : server,
1963          portstr,
1964          authstr? authstr:"");
1965     }
1966   xfree (p);
1967   if (!request)
1968     {
1969       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1970       xfree (authstr);
1971       xfree (proxy_authstr);
1972       return err;
1973     }
1974
1975   if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
1976     log_debug_with_string (request, "http.c:request:");
1977
1978   /* First setup estream so that we can write even the first line
1979      using estream.  This is also required for the sake of gnutls. */
1980   {
1981     cookie_t cookie;
1982
1983     cookie = xtrycalloc (1, sizeof *cookie);
1984     if (!cookie)
1985       {
1986         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1987         goto leave;
1988       }
1989     cookie->sock = my_socket_ref (hd->sock);
1990     hd->write_cookie = cookie;
1991     cookie->use_tls = hd->uri->use_tls;
1992     cookie->session = http_session_ref (hd->session);
1993
1994     hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1995     if (!hd->fp_write)
1996       {
1997         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1998         my_socket_unref (cookie->sock, NULL, NULL);
1999         xfree (cookie);
2000         hd->write_cookie = NULL;
2001       }
2002     else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
2003       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2004     else
2005       err = 0;
2006
2007   if (!err)
2008     {
2009       for (;headers; headers=headers->next)
2010         {
2011           if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
2012             log_debug_with_string (headers->d, "http.c:request-header:");
2013           if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write))
2014               || (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write)))
2015             {
2016               err = gpg_err_make (default_errsource,
2017                                   gpg_err_code_from_syserror ());
2018               break;
2019             }
2020         }
2021     }
2022   }
2023
2024  leave:
2025   es_free (request);
2026   xfree (authstr);
2027   xfree (proxy_authstr);
2028
2029   return err;
2030 }
2031
2032
2033 /*
2034  * Build the relative path from the parsed URI.  Minimal
2035  * implementation.  May return NULL in case of memory failure; errno
2036  * is then set accordingly.
2037  */
2038 static char *
2039 build_rel_path (parsed_uri_t uri)
2040 {
2041   uri_tuple_t r;
2042   char *rel_path, *p;
2043   int n;
2044
2045   /* Count the needed space. */
2046   n = insert_escapes (NULL, uri->path, "%;?&");
2047   /* TODO: build params. */
2048   for (r = uri->query; r; r = r->next)
2049     {
2050       n++; /* '?'/'&' */
2051       n += insert_escapes (NULL, r->name, "%;?&=");
2052       if (!r->no_value)
2053         {
2054           n++; /* '=' */
2055           n += insert_escapes (NULL, r->value, "%;?&=");
2056         }
2057     }
2058   n++;
2059
2060   /* Now allocate and copy. */
2061   p = rel_path = xtrymalloc (n);
2062   if (!p)
2063     return NULL;
2064   n = insert_escapes (p, uri->path, "%;?&");
2065   p += n;
2066   /* TODO: add params. */
2067   for (r = uri->query; r; r = r->next)
2068     {
2069       *p++ = r == uri->query ? '?' : '&';
2070       n = insert_escapes (p, r->name, "%;?&=");
2071       p += n;
2072       if (!r->no_value)
2073         {
2074           *p++ = '=';
2075           /* TODO: Use valuelen. */
2076           n = insert_escapes (p, r->value, "%;?&=");
2077           p += n;
2078         }
2079     }
2080   *p = 0;
2081   return rel_path;
2082 }
2083
2084
2085 /* Transform a header name into a standard capitalized format; e.g.
2086    "Content-Type".  Conversion stops at the colon.  As usual we don't
2087    use the localized versions of ctype.h. */
2088 static void
2089 capitalize_header_name (char *name)
2090 {
2091   int first = 1;
2092
2093   for (; *name && *name != ':'; name++)
2094     {
2095       if (*name == '-')
2096         first = 1;
2097       else if (first)
2098         {
2099           if (*name >= 'a' && *name <= 'z')
2100             *name = *name - 'a' + 'A';
2101           first = 0;
2102         }
2103       else if (*name >= 'A' && *name <= 'Z')
2104         *name = *name - 'A' + 'a';
2105     }
2106 }
2107
2108
2109 /* Store an HTTP header line in LINE away.  Line continuation is
2110    supported as well as merging of headers with the same name. This
2111    function may modify LINE. */
2112 static gpg_err_code_t
2113 store_header (http_t hd, char *line)
2114 {
2115   size_t n;
2116   char *p, *value;
2117   header_t h;
2118
2119   n = strlen (line);
2120   if (n && line[n-1] == '\n')
2121     {
2122       line[--n] = 0;
2123       if (n && line[n-1] == '\r')
2124         line[--n] = 0;
2125     }
2126   if (!n)  /* we are never called to hit this. */
2127     return GPG_ERR_BUG;
2128   if (*line == ' ' || *line == '\t')
2129     {
2130       /* Continuation. This won't happen too often as it is not
2131          recommended.  We use a straightforward implementaion. */
2132       if (!hd->headers)
2133         return GPG_ERR_PROTOCOL_VIOLATION;
2134       n += strlen (hd->headers->value);
2135       p = xtrymalloc (n+1);
2136       if (!p)
2137         return gpg_err_code_from_syserror ();
2138       strcpy (stpcpy (p, hd->headers->value), line);
2139       xfree (hd->headers->value);
2140       hd->headers->value = p;
2141       return 0;
2142     }
2143
2144   capitalize_header_name (line);
2145   p = strchr (line, ':');
2146   if (!p)
2147     return GPG_ERR_PROTOCOL_VIOLATION;
2148   *p++ = 0;
2149   while (*p == ' ' || *p == '\t')
2150     p++;
2151   value = p;
2152
2153   for (h=hd->headers; h; h = h->next)
2154     if ( !strcmp (h->name, line) )
2155       break;
2156   if (h)
2157     {
2158       /* We have already seen a line with that name.  Thus we assume
2159          it is a comma separated list and merge them.  */
2160       p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1);
2161       if (!p)
2162         return gpg_err_code_from_syserror ();
2163       strcpy (stpcpy (stpcpy (p, h->value), ","), value);
2164       xfree (h->value);
2165       h->value = p;
2166       return 0;
2167     }
2168
2169   /* Append a new header. */
2170   h = xtrymalloc (sizeof *h + strlen (line));
2171   if (!h)
2172     return gpg_err_code_from_syserror ();
2173   strcpy (h->name, line);
2174   h->value = xtrymalloc (strlen (value)+1);
2175   if (!h->value)
2176     {
2177       xfree (h);
2178       return gpg_err_code_from_syserror ();
2179     }
2180   strcpy (h->value, value);
2181   h->next = hd->headers;
2182   hd->headers = h;
2183
2184   return 0;
2185 }
2186
2187
2188 /* Return the header NAME from the last response.  The returned value
2189    is valid as along as HD has not been closed and no other request
2190    has been send. If the header was not found, NULL is returned.  NAME
2191    must be canonicalized, that is the first letter of each dash
2192    delimited part must be uppercase and all other letters lowercase.  */
2193 const char *
2194 http_get_header (http_t hd, const char *name)
2195 {
2196   header_t h;
2197
2198   for (h=hd->headers; h; h = h->next)
2199     if ( !strcmp (h->name, name) )
2200       return h->value;
2201   return NULL;
2202 }
2203
2204
2205 /* Return a newly allocated and NULL terminated array with pointers to
2206    header names.  The array must be released with xfree() and its
2207    content is only values as long as no other request has been
2208    send.  */
2209 const char **
2210 http_get_header_names (http_t hd)
2211 {
2212   const char **array;
2213   size_t n;
2214   header_t h;
2215
2216   for (n=0, h = hd->headers; h; h = h->next)
2217     n++;
2218   array = xtrycalloc (n+1, sizeof *array);
2219   if (array)
2220     {
2221       for (n=0, h = hd->headers; h; h = h->next)
2222         array[n++] = h->name;
2223     }
2224
2225   return array;
2226 }
2227
2228
2229 /*
2230  * Parse the response from a server.
2231  * Returns: Errorcode and sets some files in the handle
2232  */
2233 static gpg_err_code_t
2234 parse_response (http_t hd)
2235 {
2236   char *line, *p, *p2;
2237   size_t maxlen, len;
2238   cookie_t cookie = hd->read_cookie;
2239   const char *s;
2240
2241   /* Delete old header lines.  */
2242   while (hd->headers)
2243     {
2244       header_t tmp = hd->headers->next;
2245       xfree (hd->headers->value);
2246       xfree (hd->headers);
2247       hd->headers = tmp;
2248     }
2249
2250   /* Wait for the status line. */
2251   do
2252     {
2253       maxlen = MAX_LINELEN;
2254       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2255       line = hd->buffer;
2256       if (!line)
2257         return gpg_err_code_from_syserror (); /* Out of core. */
2258       if (!maxlen)
2259         return GPG_ERR_TRUNCATED; /* Line has been truncated. */
2260       if (!len)
2261         return GPG_ERR_EOF;
2262
2263       if ((hd->flags & HTTP_FLAG_LOG_RESP))
2264         log_debug_with_string (line, "http.c:response:\n");
2265     }
2266   while (!*line);
2267
2268   if ((p = strchr (line, '/')))
2269     *p++ = 0;
2270   if (!p || strcmp (line, "HTTP"))
2271     return 0; /* Assume http 0.9. */
2272
2273   if ((p2 = strpbrk (p, " \t")))
2274     {
2275       *p2++ = 0;
2276       p2 += strspn (p2, " \t");
2277     }
2278   if (!p2)
2279     return 0; /* Also assume http 0.9. */
2280   p = p2;
2281   /* TODO: Add HTTP version number check. */
2282   if ((p2 = strpbrk (p, " \t")))
2283     *p2++ = 0;
2284   if (!isdigit ((unsigned int)p[0]) || !isdigit ((unsigned int)p[1])
2285       || !isdigit ((unsigned int)p[2]) || p[3])
2286     {
2287       /* Malformed HTTP status code - assume http 0.9. */
2288       hd->is_http_0_9 = 1;
2289       hd->status_code = 200;
2290       return 0;
2291     }
2292   hd->status_code = atoi (p);
2293
2294   /* Skip all the header lines and wait for the empty line. */
2295   do
2296     {
2297       maxlen = MAX_LINELEN;
2298       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2299       line = hd->buffer;
2300       if (!line)
2301         return gpg_err_code_from_syserror (); /* Out of core. */
2302       /* Note, that we can silently ignore truncated lines. */
2303       if (!len)
2304         return GPG_ERR_EOF;
2305       /* Trim line endings of empty lines. */
2306       if ((*line == '\r' && line[1] == '\n') || *line == '\n')
2307         *line = 0;
2308       if ((hd->flags & HTTP_FLAG_LOG_RESP))
2309         log_info ("http.c:RESP: '%.*s'\n",
2310                   (int)strlen(line)-(*line&&line[1]?2:0),line);
2311       if (*line)
2312         {
2313           gpg_err_code_t ec = store_header (hd, line);
2314           if (ec)
2315             return ec;
2316         }
2317     }
2318   while (len && *line);
2319
2320   cookie->content_length_valid = 0;
2321   if (!(hd->flags & HTTP_FLAG_IGNORE_CL))
2322     {
2323       s = http_get_header (hd, "Content-Length");
2324       if (s)
2325         {
2326           cookie->content_length_valid = 1;
2327           cookie->content_length = string_to_u64 (s);
2328         }
2329     }
2330
2331   return 0;
2332 }
2333
2334 #if 0
2335 static int
2336 start_server ()
2337 {
2338   struct sockaddr_in mya;
2339   struct sockaddr_in peer;
2340   int fd, client;
2341   fd_set rfds;
2342   int addrlen;
2343   int i;
2344
2345   if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
2346     {
2347       log_error ("socket() failed: %s\n", strerror (errno));
2348       return -1;
2349     }
2350   i = 1;
2351   if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (byte *) & i, sizeof (i)))
2352     log_info ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno));
2353
2354   mya.sin_family = AF_INET;
2355   memset (&mya.sin_addr, 0, sizeof (mya.sin_addr));
2356   mya.sin_port = htons (11371);
2357
2358   if (bind (fd, (struct sockaddr *) &mya, sizeof (mya)))
2359     {
2360       log_error ("bind to port 11371 failed: %s\n", strerror (errno));
2361       sock_close (fd);
2362       return -1;
2363     }
2364
2365   if (listen (fd, 5))
2366     {
2367       log_error ("listen failed: %s\n", strerror (errno));
2368       sock_close (fd);
2369       return -1;
2370     }
2371
2372   for (;;)
2373     {
2374       FD_ZERO (&rfds);
2375       FD_SET (fd, &rfds);
2376
2377       if (my_select (fd + 1, &rfds, NULL, NULL, NULL) <= 0)
2378         continue;               /* ignore any errors */
2379
2380       if (!FD_ISSET (fd, &rfds))
2381         continue;
2382
2383       addrlen = sizeof peer;
2384       client = my_accept (fd, (struct sockaddr *) &peer, &addrlen);
2385       if (client == -1)
2386         continue;               /* oops */
2387
2388       log_info ("connect from %s\n", inet_ntoa (peer.sin_addr));
2389
2390       fflush (stdout);
2391       fflush (stderr);
2392       if (!fork ())
2393         {
2394           int c;
2395           FILE *fp;
2396
2397           fp = fdopen (client, "r");
2398           while ((c = getc (fp)) != EOF)
2399             putchar (c);
2400           fclose (fp);
2401           exit (0);
2402         }
2403       sock_close (client);
2404     }
2405
2406
2407   return 0;
2408 }
2409 #endif
2410
2411
2412
2413 /* Return true if SOCKS shall be used.  This is the case if tor_mode
2414  * is enabled and the desired address is not the loopback address.
2415  * This function is basically a copy of the same internal fucntion in
2416  * Libassuan.  */
2417 static int
2418 use_socks (struct sockaddr *addr)
2419 {
2420   int mode;
2421
2422   if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
2423     return 0;  /* Not in Tor mode.  */
2424   else if (addr->sa_family == AF_INET6)
2425     {
2426       struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr;
2427       const unsigned char *s;
2428       int i;
2429
2430       s = (unsigned char *)&addr_in6->sin6_addr.s6_addr;
2431       if (s[15] != 1)
2432         return 1;   /* Last octet is not 1 - not the loopback address.  */
2433       for (i=0; i < 15; i++, s++)
2434         if (*s)
2435           return 1; /* Non-zero octet found - not the loopback address.  */
2436
2437       return 0; /* This is the loopback address.  */
2438     }
2439   else if (addr->sa_family == AF_INET)
2440     {
2441       struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
2442
2443       if (*(unsigned char*)&addr_in->sin_addr.s_addr == 127)
2444         return 0; /* Loopback (127.0.0.0/8) */
2445
2446       return 1;
2447     }
2448   else
2449     return 0;
2450 }
2451
2452
2453 /* Wrapper around assuan_sock_new which takes the domain from an
2454  * address parameter.  */
2455 static assuan_fd_t
2456 my_sock_new_for_addr (struct sockaddr *addr, int type, int proto)
2457 {
2458   int domain;
2459
2460   if (use_socks (addr))
2461     {
2462       /* Libassaun always uses 127.0.0.1 to connect to the socks
2463        * server (i.e. the Tor daemon).  */
2464       domain = AF_INET;
2465     }
2466   else
2467     domain = addr->sa_family;
2468
2469   return assuan_sock_new (domain, type, proto);
2470 }
2471
2472
2473 /* Actually connect to a server.  On success 0 is returned and the
2474  * file descriptor for the socket is stored at R_SOCK; on error an
2475  * error code is returned and ASSUAN_INVALID_FD is stored at
2476  * R_SOCK.  */
2477 static gpg_error_t
2478 connect_server (const char *server, unsigned short port,
2479                 unsigned int flags, const char *srvtag, assuan_fd_t *r_sock)
2480 {
2481   gpg_error_t err;
2482   assuan_fd_t sock = ASSUAN_INVALID_FD;
2483   unsigned int srvcount = 0;
2484   int hostfound = 0;
2485   int anyhostaddr = 0;
2486   int srv, connected;
2487   gpg_error_t last_err = 0;
2488   struct srventry *serverlist = NULL;
2489
2490   *r_sock = ASSUAN_INVALID_FD;
2491
2492 #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
2493   init_sockets ();
2494 #endif /*Windows*/
2495
2496   /* Onion addresses require special treatment.  */
2497   if (is_onion_address (server))
2498     {
2499 #ifdef ASSUAN_SOCK_TOR
2500
2501       if (opt_debug)
2502         log_debug ("http.c:connect_server:onion: name='%s' port=%hu\n",
2503                    server, port);
2504       sock = assuan_sock_connect_byname (server, port, 0, NULL,
2505                                          ASSUAN_SOCK_TOR);
2506       if (sock == ASSUAN_INVALID_FD)
2507         {
2508           err = gpg_err_make (default_errsource,
2509                               (errno == EHOSTUNREACH)? GPG_ERR_UNKNOWN_HOST
2510                               : gpg_err_code_from_syserror ());
2511           log_error ("can't connect to '%s': %s\n", server, gpg_strerror (err));
2512           return err;
2513         }
2514
2515       notify_netactivity ();
2516       *r_sock = sock;
2517       return 0;
2518
2519 #else /*!ASSUAN_SOCK_TOR*/
2520
2521       err = gpg_err_make (default_errsource, GPG_ERR_ENETUNREACH);
2522       return ASSUAN_INVALID_FD;
2523
2524 #endif /*!HASSUAN_SOCK_TOR*/
2525     }
2526
2527   /* Do the SRV thing */
2528   if (srvtag)
2529     {
2530       err = get_dns_srv (server, srvtag, NULL, &serverlist, &srvcount);
2531       if (err)
2532         log_info ("getting '%s' SRV for '%s' failed: %s\n",
2533                   srvtag, server, gpg_strerror (err));
2534       /* Note that on error SRVCOUNT is zero.  */
2535       err = 0;
2536     }
2537
2538   if (!serverlist)
2539     {
2540       /* Either we're not using SRV, or the SRV lookup failed.  Make
2541          up a fake SRV record. */
2542       serverlist = xtrycalloc (1, sizeof *serverlist);
2543       if (!serverlist)
2544         return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2545
2546       serverlist->port = port;
2547       strncpy (serverlist->target, server, DIMof (struct srventry, target));
2548       serverlist->target[DIMof (struct srventry, target)-1] = '\0';
2549       srvcount = 1;
2550     }
2551
2552   connected = 0;
2553   for (srv=0; srv < srvcount && !connected; srv++)
2554     {
2555       dns_addrinfo_t aibuf, ai;
2556
2557       if (opt_debug)
2558         log_debug ("http.c:connect_server: trying name='%s' port=%hu\n",
2559                    serverlist[srv].target, port);
2560       err = resolve_dns_name (serverlist[srv].target, port, 0, SOCK_STREAM,
2561                               &aibuf, NULL);
2562       if (err)
2563         {
2564           log_info ("resolving '%s' failed: %s\n",
2565                     serverlist[srv].target, gpg_strerror (err));
2566           last_err = err;
2567           continue; /* Not found - try next one. */
2568         }
2569       hostfound = 1;
2570
2571       for (ai = aibuf; ai && !connected; ai = ai->next)
2572         {
2573           if (ai->family == AF_INET && (flags & HTTP_FLAG_IGNORE_IPv4))
2574             continue;
2575           if (ai->family == AF_INET6 && (flags & HTTP_FLAG_IGNORE_IPv6))
2576             continue;
2577
2578           if (sock != ASSUAN_INVALID_FD)
2579             assuan_sock_close (sock);
2580           sock = my_sock_new_for_addr (ai->addr, ai->socktype, ai->protocol);
2581           if (sock == ASSUAN_INVALID_FD)
2582             {
2583               err = gpg_err_make (default_errsource,
2584                                   gpg_err_code_from_syserror ());
2585               log_error ("error creating socket: %s\n", gpg_strerror (err));
2586               free_dns_addrinfo (aibuf);
2587               xfree (serverlist);
2588               return err;
2589             }
2590
2591           anyhostaddr = 1;
2592           if (assuan_sock_connect (sock, ai->addr, ai->addrlen))
2593             {
2594               last_err = gpg_err_make (default_errsource,
2595                                        gpg_err_code_from_syserror ());
2596             }
2597           else
2598             {
2599               connected = 1;
2600               notify_netactivity ();
2601             }
2602         }
2603       free_dns_addrinfo (aibuf);
2604     }
2605
2606   xfree (serverlist);
2607
2608   if (!connected)
2609     {
2610       if (!hostfound)
2611         log_error ("can't connect to '%s': %s\n",
2612                    server, "host not found");
2613       else if (!anyhostaddr)
2614         log_error ("can't connect to '%s': %s\n",
2615                    server, "no IP address for host");
2616       else
2617         {
2618 #ifdef HAVE_W32_SYSTEM
2619         log_error ("can't connect to '%s': ec=%d\n",
2620                    server, (int)WSAGetLastError());
2621 #else
2622         log_error ("can't connect to '%s': %s\n",
2623                    server, gpg_strerror (last_err));
2624 #endif
2625         }
2626       err = last_err? last_err : gpg_err_make (default_errsource,
2627                                                GPG_ERR_UNKNOWN_HOST);
2628       if (sock != ASSUAN_INVALID_FD)
2629         assuan_sock_close (sock);
2630       return err;
2631     }
2632
2633   *r_sock = sock;
2634   return 0;
2635 }
2636
2637
2638 static gpg_error_t
2639 write_server (int sock, const char *data, size_t length)
2640 {
2641   int nleft;
2642   int nwritten;
2643
2644   nleft = length;
2645   while (nleft > 0)
2646     {
2647 #if defined(HAVE_W32_SYSTEM)
2648 # if defined(USE_NPTH)
2649       npth_unprotect ();
2650 # endif
2651       nwritten = send (sock, data, nleft, 0);
2652 # if defined(USE_NPTH)
2653       npth_protect ();
2654 # endif
2655       if ( nwritten == SOCKET_ERROR )
2656         {
2657           log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
2658           return gpg_error (GPG_ERR_NETWORK);
2659         }
2660 #else /*!HAVE_W32_SYSTEM*/
2661 # ifdef USE_NPTH
2662       nwritten = npth_write (sock, data, nleft);
2663 # else
2664       nwritten = write (sock, data, nleft);
2665 # endif
2666       if (nwritten == -1)
2667         {
2668           if (errno == EINTR)
2669             continue;
2670           if (errno == EAGAIN)
2671             {
2672               struct timeval tv;
2673
2674               tv.tv_sec = 0;
2675               tv.tv_usec = 50000;
2676               my_select (0, NULL, NULL, NULL, &tv);
2677               continue;
2678             }
2679           log_info ("network write failed: %s\n", strerror (errno));
2680           return gpg_error_from_syserror ();
2681         }
2682 #endif /*!HAVE_W32_SYSTEM*/
2683       nleft -= nwritten;
2684       data += nwritten;
2685     }
2686
2687   return 0;
2688 }
2689
2690
2691 \f
2692 /* Read handler for estream.  */
2693 static gpgrt_ssize_t
2694 cookie_read (void *cookie, void *buffer, size_t size)
2695 {
2696   cookie_t c = cookie;
2697   int nread;
2698
2699   if (c->content_length_valid)
2700     {
2701       if (!c->content_length)
2702         return 0; /* EOF */
2703       if (c->content_length < size)
2704         size = c->content_length;
2705     }
2706
2707 #if HTTP_USE_NTBTLS
2708   if (c->use_tls && c->session && c->session->tls_session)
2709     {
2710       estream_t in, out;
2711
2712       ntbtls_get_stream (c->session->tls_session, &in, &out);
2713       nread = es_fread (buffer, 1, size, in);
2714       if (opt_debug)
2715         log_debug ("TLS network read: %d/%zu\n", nread, size);
2716     }
2717   else
2718 #elif HTTP_USE_GNUTLS
2719   if (c->use_tls && c->session && c->session->tls_session)
2720     {
2721     again:
2722       nread = gnutls_record_recv (c->session->tls_session, buffer, size);
2723       if (nread < 0)
2724         {
2725           if (nread == GNUTLS_E_INTERRUPTED)
2726             goto again;
2727           if (nread == GNUTLS_E_AGAIN)
2728             {
2729               struct timeval tv;
2730
2731               tv.tv_sec = 0;
2732               tv.tv_usec = 50000;
2733               my_select (0, NULL, NULL, NULL, &tv);
2734               goto again;
2735             }
2736           if (nread == GNUTLS_E_REHANDSHAKE)
2737             goto again; /* A client is allowed to just ignore this request. */
2738           if (nread == GNUTLS_E_PREMATURE_TERMINATION)
2739             {
2740               /* The server terminated the connection.  Close the TLS
2741                  session, and indicate EOF using a short read.  */
2742               close_tls_session (c->session);
2743               return 0;
2744             }
2745           log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
2746           gpg_err_set_errno (EIO);
2747           return -1;
2748         }
2749     }
2750   else
2751 #endif /*HTTP_USE_GNUTLS*/
2752     {
2753       do
2754         {
2755 #ifdef HAVE_W32_SYSTEM
2756           /* Under Windows we need to use recv for a socket.  */
2757 # if defined(USE_NPTH)
2758           npth_unprotect ();
2759 # endif
2760           nread = recv (c->sock->fd, buffer, size, 0);
2761 # if defined(USE_NPTH)
2762           npth_protect ();
2763 # endif
2764
2765 #else /*!HAVE_W32_SYSTEM*/
2766
2767 # ifdef USE_NPTH
2768           nread = npth_read (c->sock->fd, buffer, size);
2769 # else
2770           nread = read (c->sock->fd, buffer, size);
2771 # endif
2772
2773 #endif /*!HAVE_W32_SYSTEM*/
2774         }
2775       while (nread == -1 && errno == EINTR);
2776     }
2777
2778   if (c->content_length_valid && nread > 0)
2779     {
2780       if (nread < c->content_length)
2781         c->content_length -= nread;
2782       else
2783         c->content_length = 0;
2784     }
2785
2786   return (gpgrt_ssize_t)nread;
2787 }
2788
2789 /* Write handler for estream.  */
2790 static gpgrt_ssize_t
2791 cookie_write (void *cookie, const void *buffer_arg, size_t size)
2792 {
2793   const char *buffer = buffer_arg;
2794   cookie_t c = cookie;
2795   int nwritten = 0;
2796
2797 #if HTTP_USE_NTBTLS
2798   if (c->use_tls && c->session && c->session->tls_session)
2799     {
2800       estream_t in, out;
2801
2802       ntbtls_get_stream (c->session->tls_session, &in, &out);
2803       if (size == 0)
2804         es_fflush (out);
2805       else
2806         nwritten = es_fwrite (buffer, 1, size, out);
2807       if (opt_debug)
2808         log_debug ("TLS network write: %d/%zu\n", nwritten, size);
2809     }
2810   else
2811 #elif HTTP_USE_GNUTLS
2812   if (c->use_tls && c->session && c->session->tls_session)
2813     {
2814       int nleft = size;
2815       while (nleft > 0)
2816         {
2817           nwritten = gnutls_record_send (c->session->tls_session,
2818                                          buffer, nleft);
2819           if (nwritten <= 0)
2820             {
2821               if (nwritten == GNUTLS_E_INTERRUPTED)
2822                 continue;
2823               if (nwritten == GNUTLS_E_AGAIN)
2824                 {
2825                   struct timeval tv;
2826
2827                   tv.tv_sec = 0;
2828                   tv.tv_usec = 50000;
2829                   my_select (0, NULL, NULL, NULL, &tv);
2830                   continue;
2831                 }
2832               log_info ("TLS network write failed: %s\n",
2833                         gnutls_strerror (nwritten));
2834               gpg_err_set_errno (EIO);
2835               return -1;
2836             }
2837           nleft -= nwritten;
2838           buffer += nwritten;
2839         }
2840     }
2841   else
2842 #endif /*HTTP_USE_GNUTLS*/
2843     {
2844       if ( write_server (c->sock->fd, buffer, size) )
2845         {
2846           gpg_err_set_errno (EIO);
2847           nwritten = -1;
2848         }
2849       else
2850         nwritten = size;
2851     }
2852
2853   return (gpgrt_ssize_t)nwritten;
2854 }
2855
2856
2857 #ifdef HTTP_USE_GNUTLS
2858 /* Wrapper for gnutls_bye used by my_socket_unref.  */
2859 static void
2860 send_gnutls_bye (void *opaque)
2861 {
2862   tls_session_t tls_session = opaque;
2863   int ret;
2864
2865  again:
2866   do
2867     ret = gnutls_bye (tls_session, GNUTLS_SHUT_RDWR);
2868   while (ret == GNUTLS_E_INTERRUPTED);
2869   if (ret == GNUTLS_E_AGAIN)
2870     {
2871       struct timeval tv;
2872
2873       tv.tv_sec = 0;
2874       tv.tv_usec = 50000;
2875       my_select (0, NULL, NULL, NULL, &tv);
2876       goto again;
2877     }
2878 }
2879 #endif /*HTTP_USE_GNUTLS*/
2880
2881 /* Close handler for estream.  */
2882 static int
2883 cookie_close (void *cookie)
2884 {
2885   cookie_t c = cookie;
2886
2887   if (!c)
2888     return 0;
2889
2890 #if HTTP_USE_NTBTLS
2891   if (c->use_tls && c->session && c->session->tls_session)
2892     {
2893       /* FIXME!! Possibly call ntbtls_close_notify for close
2894          of write stream.  */
2895       my_socket_unref (c->sock, NULL, NULL);
2896     }
2897   else
2898 #elif HTTP_USE_GNUTLS
2899   if (c->use_tls && c->session && c->session->tls_session)
2900     my_socket_unref (c->sock, send_gnutls_bye, c->session->tls_session);
2901   else
2902 #endif /*HTTP_USE_GNUTLS*/
2903     if (c->sock)
2904       my_socket_unref (c->sock, NULL, NULL);
2905
2906   if (c->session)
2907     http_session_unref (c->session);
2908   xfree (c);
2909   return 0;
2910 }
2911
2912
2913
2914 \f
2915 /* Verify the credentials of the server.  Returns 0 on success and
2916    store the result in the session object.  */
2917 gpg_error_t
2918 http_verify_server_credentials (http_session_t sess)
2919 {
2920 #if HTTP_USE_NTBTLS
2921   (void)sess;
2922   return 0;  /* FIXME!! */
2923 #elif HTTP_USE_GNUTLS
2924   static const char const errprefix[] = "TLS verification of peer failed";
2925   int rc;
2926   unsigned int status;
2927   const char *hostname;
2928   const gnutls_datum_t *certlist;
2929   unsigned int certlistlen;
2930   gnutls_x509_crt_t cert;
2931   gpg_error_t err = 0;
2932
2933   sess->verify.done = 1;
2934   sess->verify.status = 0;
2935   sess->verify.rc = GNUTLS_E_CERTIFICATE_ERROR;
2936
2937   if (gnutls_certificate_type_get (sess->tls_session) != GNUTLS_CRT_X509)
2938     {
2939       log_error ("%s: %s\n", errprefix, "not an X.509 certificate");
2940       sess->verify.rc = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
2941       return gpg_error (GPG_ERR_GENERAL);
2942     }
2943
2944   rc = gnutls_certificate_verify_peers2 (sess->tls_session, &status);
2945   if (rc)
2946     {
2947       log_error ("%s: %s\n", errprefix, gnutls_strerror (rc));
2948       if (!err)
2949         err = gpg_error (GPG_ERR_GENERAL);
2950     }
2951   else if (status)
2952     {
2953       log_error ("%s: status=0x%04x\n", errprefix, status);
2954 #if GNUTLS_VERSION_NUMBER >= 0x030104
2955       {
2956         gnutls_datum_t statusdat;
2957
2958         if (!gnutls_certificate_verification_status_print
2959             (status, GNUTLS_CRT_X509, &statusdat, 0))
2960           {
2961             log_info ("%s: %s\n", errprefix, statusdat.data);
2962             gnutls_free (statusdat.data);
2963           }
2964       }
2965 #endif /*gnutls >= 3.1.4*/
2966
2967       sess->verify.status = status;
2968       if (!err)
2969         err = gpg_error (GPG_ERR_GENERAL);
2970     }
2971
2972   hostname = sess->servername;
2973   if (!hostname || !strchr (hostname, '.'))
2974     {
2975       log_error ("%s: %s\n", errprefix, "hostname missing");
2976       if (!err)
2977         err = gpg_error (GPG_ERR_GENERAL);
2978     }
2979
2980   certlist = gnutls_certificate_get_peers (sess->tls_session, &certlistlen);
2981   if (!certlistlen)
2982     {
2983       log_error ("%s: %s\n", errprefix, "server did not send a certificate");
2984       if (!err)
2985         err = gpg_error (GPG_ERR_GENERAL);
2986
2987       /* Need to stop here.  */
2988       if (err)
2989         return err;
2990     }
2991
2992   rc = gnutls_x509_crt_init (&cert);
2993   if (rc < 0)
2994     {
2995       if (!err)
2996         err = gpg_error (GPG_ERR_GENERAL);
2997       if (err)
2998         return err;
2999     }
3000
3001   rc = gnutls_x509_crt_import (cert, &certlist[0], GNUTLS_X509_FMT_DER);
3002   if (rc < 0)
3003     {
3004       log_error ("%s: %s: %s\n", errprefix, "error importing certificate",
3005                  gnutls_strerror (rc));
3006       if (!err)
3007         err = gpg_error (GPG_ERR_GENERAL);
3008     }
3009
3010   if (!gnutls_x509_crt_check_hostname (cert, hostname))
3011     {
3012       log_error ("%s: %s\n", errprefix, "hostname does not match");
3013       if (!err)
3014         err = gpg_error (GPG_ERR_GENERAL);
3015     }
3016
3017   gnutls_x509_crt_deinit (cert);
3018
3019   if (!err)
3020     sess->verify.rc = 0;
3021
3022   if (sess->cert_log_cb)
3023     {
3024       const void *bufarr[10];
3025       size_t buflenarr[10];
3026       size_t n;
3027
3028       for (n = 0; n < certlistlen && n < DIM (bufarr)-1; n++)
3029         {
3030           bufarr[n] = certlist[n].data;
3031           buflenarr[n] = certlist[n].size;
3032         }
3033       bufarr[n] = NULL;
3034       buflenarr[n] = 0;
3035       sess->cert_log_cb (sess, err, hostname, bufarr, buflenarr);
3036     }
3037
3038   return err;
3039 #else /*!HTTP_USE_GNUTLS*/
3040   (void)sess;
3041   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
3042 #endif
3043 }
3044
3045 /* Return the first query variable with the specified key.  If there
3046    is no such variable, return NULL.  */
3047 struct uri_tuple_s *
3048 uri_query_lookup (parsed_uri_t uri, const char *key)
3049 {
3050   struct uri_tuple_s *t;
3051
3052   for (t = uri->query; t; t = t->next)
3053     if (strcmp (t->name, key) == 0)
3054       return t;
3055
3056   return NULL;
3057 }