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