po: Apply removal of dirmngr/ldap-wrapper-ce.c.
[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-2018 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 constraints 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 <fcntl.h>
74 # include <netinet/in.h>
75 # include <arpa/inet.h>
76 # include <netdb.h>
77 #endif /*!HAVE_W32_SYSTEM*/
78
79 #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth.  */
80 # undef USE_NPTH
81 #endif
82
83 #ifdef USE_NPTH
84 # include <npth.h>
85 #endif
86
87 #if defined (HTTP_USE_GNUTLS) && defined (HTTP_USE_NTBTLS)
88 # error Both, HTTP_USE_GNUTLS and HTTP_USE_NTBTLS, are defined.
89 #endif
90
91 #ifdef HTTP_USE_NTBTLS
92 # include <ntbtls.h>
93 #elif HTTP_USE_GNUTLS
94 # include <gnutls/gnutls.h>
95 # include <gnutls/x509.h>
96 #endif /*HTTP_USE_GNUTLS*/
97
98 #include <assuan.h>  /* We need the socket wrapper.  */
99
100 #include "../common/util.h"
101 #include "../common/i18n.h"
102 #include "../common/sysutils.h" /* (gnupg_fd_t) */
103 #include "dns-stuff.h"
104 #include "dirmngr-status.h"    /* (dirmngr_status_printf)  */
105 #include "http.h"
106 #include "http-common.h"
107
108
109 #ifdef USE_NPTH
110 # define my_select(a,b,c,d,e)  npth_select ((a), (b), (c), (d), (e))
111 # define my_accept(a,b,c)      npth_accept ((a), (b), (c))
112 #else
113 # define my_select(a,b,c,d,e)  select ((a), (b), (c), (d), (e))
114 # define my_accept(a,b,c)      accept ((a), (b), (c))
115 #endif
116
117 #ifdef HAVE_W32_SYSTEM
118 #define sock_close(a)  closesocket(a)
119 #else
120 #define sock_close(a)  close(a)
121 #endif
122
123 #ifndef EAGAIN
124 #define EAGAIN  EWOULDBLOCK
125 #endif
126 #ifndef INADDR_NONE  /* Slowaris is missing that.  */
127 #define INADDR_NONE  ((unsigned long)(-1))
128 #endif /*INADDR_NONE*/
129
130 #define HTTP_PROXY_ENV           "http_proxy"
131 #define MAX_LINELEN 20000  /* Max. length of a HTTP header line. */
132 #define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz"   \
133                         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"   \
134                         "01234567890@"                 \
135                         "!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~"
136
137 #if HTTP_USE_NTBTLS
138 typedef ntbtls_t         tls_session_t;
139 # define USE_TLS 1
140 #elif HTTP_USE_GNUTLS
141 typedef gnutls_session_t tls_session_t;
142 # define USE_TLS 1
143 #else
144 typedef void *tls_session_t;
145 # undef USE_TLS
146 #endif
147
148 static gpg_err_code_t do_parse_uri (parsed_uri_t uri, int only_local_part,
149                                     int no_scheme_check, int force_tls);
150 static gpg_error_t parse_uri (parsed_uri_t *ret_uri, const char *uri,
151                               int no_scheme_check, int force_tls);
152 static int remove_escapes (char *string);
153 static int insert_escapes (char *buffer, const char *string,
154                            const char *special);
155 static uri_tuple_t parse_tuple (char *string);
156 static gpg_error_t send_request (ctrl_t ctrl, http_t hd, const char *httphost,
157                                  const char *auth,const char *proxy,
158                                  const char *srvtag, unsigned int timeout,
159                                  strlist_t headers);
160 static char *build_rel_path (parsed_uri_t uri);
161 static gpg_error_t parse_response (http_t hd);
162
163 static gpg_error_t connect_server (ctrl_t ctrl,
164                                    const char *server, unsigned short port,
165                                    unsigned int flags, const char *srvtag,
166                                    unsigned int timeout, assuan_fd_t *r_sock);
167 static gpgrt_ssize_t read_server (assuan_fd_t sock, void *buffer, size_t size);
168 static gpg_error_t write_server (assuan_fd_t sock, const char *data, size_t length);
169
170 static gpgrt_ssize_t cookie_read (void *cookie, void *buffer, size_t size);
171 static gpgrt_ssize_t cookie_write (void *cookie,
172                                    const void *buffer, size_t size);
173 static int cookie_close (void *cookie);
174 #if defined(HAVE_W32_SYSTEM) && defined(HTTP_USE_NTBTLS)
175 static gpgrt_ssize_t simple_cookie_read (void *cookie,
176                                          void *buffer, size_t size);
177 static gpgrt_ssize_t simple_cookie_write (void *cookie,
178                                           const void *buffer, size_t size);
179 #endif
180
181 /* A socket object used to a allow ref counting of sockets.  */
182 struct my_socket_s
183 {
184   assuan_fd_t fd; /* The actual socket - shall never be ASSUAN_INVALID_FD.  */
185   int refcount;   /* Number of references to this socket.  */
186 };
187 typedef struct my_socket_s *my_socket_t;
188
189
190 /* Cookie function structure and cookie object.  */
191 static es_cookie_io_functions_t cookie_functions =
192   {
193     cookie_read,
194     cookie_write,
195     NULL,
196     cookie_close
197   };
198
199
200 struct cookie_s
201 {
202   /* Socket object or NULL if already closed. */
203   my_socket_t sock;
204
205   /* The session object or NULL if not used. */
206   http_session_t session;
207
208   /* True if TLS is to be used.  */
209   int use_tls;
210
211   /* The remaining content length and a flag telling whether to use
212      the content length.  */
213   uint64_t content_length;
214   unsigned int content_length_valid:1;
215 };
216 typedef struct cookie_s *cookie_t;
217
218
219 /* Simple cookie functions.  Here the cookie is an int with the
220  * socket. */
221 #if defined(HAVE_W32_SYSTEM) && defined(HTTP_USE_NTBTLS)
222 static es_cookie_io_functions_t simple_cookie_functions =
223   {
224     simple_cookie_read,
225     simple_cookie_write,
226     NULL,
227     NULL
228   };
229 #endif
230
231
232 #if SIZEOF_UNSIGNED_LONG == 8
233 # define HTTP_SESSION_MAGIC 0x0068545470534553 /* "hTTpSES" */
234 #else
235 # define HTTP_SESSION_MAGIC 0x68547365         /* "hTse"    */
236 #endif
237
238 /* The session object. */
239 struct http_session_s
240 {
241   unsigned long magic;
242
243   int refcount;    /* Number of references to this object.  */
244 #ifdef HTTP_USE_GNUTLS
245   gnutls_certificate_credentials_t certcred;
246 #endif /*HTTP_USE_GNUTLS*/
247 #ifdef USE_TLS
248   tls_session_t tls_session;
249   struct {
250     int done;      /* Verifciation has been done.  */
251     int rc;        /* TLS verification return code.  */
252     unsigned int status; /* Verification status.  */
253   } verify;
254   char *servername; /* Malloced server name.  */
255 #endif /*USE_TLS*/
256   /* A callback function to log details of TLS certifciates.  */
257   void (*cert_log_cb) (http_session_t, gpg_error_t, const char *,
258                        const void **, size_t *);
259
260   /* The flags passed to the session object.  */
261   unsigned int flags;
262
263   /* A per-session TLS verification callback.  */
264   http_verify_cb_t verify_cb;
265   void *verify_cb_value;
266
267   /* The connect timeout */
268   unsigned int connect_timeout;
269 };
270
271
272 /* An object to save header lines. */
273 struct header_s
274 {
275   struct header_s *next;
276   char *value;    /* The value of the header (malloced).  */
277   char name[1];   /* The name of the header (canonicalized). */
278 };
279 typedef struct header_s *header_t;
280
281
282 #if SIZEOF_UNSIGNED_LONG == 8
283 # define HTTP_CONTEXT_MAGIC 0x0068545470435458 /* "hTTpCTX" */
284 #else
285 # define HTTP_CONTEXT_MAGIC 0x68546378         /* "hTcx"    */
286 #endif
287
288
289 /* Our handle context. */
290 struct http_context_s
291 {
292   unsigned long magic;
293   unsigned int status_code;
294   my_socket_t sock;
295   unsigned int in_data:1;
296   unsigned int is_http_0_9:1;
297   estream_t fp_read;
298   estream_t fp_write;
299   void *write_cookie;
300   void *read_cookie;
301   http_session_t session;
302   parsed_uri_t uri;
303   http_req_t req_type;
304   char *buffer;          /* Line buffer. */
305   size_t buffer_size;
306   unsigned int flags;
307   header_t headers;      /* Received headers. */
308 };
309
310
311 /* Two flags to enable verbose and debug mode.  Although currently not
312  * set-able a value > 1 for OPT_DEBUG enables debugging of the session
313  * reference counting.  */
314 static int opt_verbose;
315 static int opt_debug;
316
317 /* The global callback for the verification function.  */
318 static gpg_error_t (*tls_callback) (http_t, http_session_t, int);
319
320 /* The list of files with trusted CA certificates.  */
321 static strlist_t tls_ca_certlist;
322
323 /* The list of files with extra trusted CA certificates.  */
324 static strlist_t cfg_ca_certlist;
325
326 /* The global callback for net activity.  */
327 static void (*netactivity_cb)(void);
328
329
330 \f
331 #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
332
333 #if GNUPG_MAJOR_VERSION == 1
334 #define REQ_WINSOCK_MAJOR  1
335 #define REQ_WINSOCK_MINOR  1
336 #else
337 #define REQ_WINSOCK_MAJOR  2
338 #define REQ_WINSOCK_MINOR  2
339 #endif
340
341
342 static void
343 deinit_sockets (void)
344 {
345   WSACleanup();
346 }
347
348 static void
349 init_sockets (void)
350 {
351   static int initialized;
352   static WSADATA wsdata;
353
354   if (initialized)
355     return;
356
357   if ( WSAStartup( MAKEWORD (REQ_WINSOCK_MINOR, REQ_WINSOCK_MAJOR), &wsdata ) )
358     {
359       log_error ("error initializing socket library: ec=%d\n",
360                  (int)WSAGetLastError () );
361       return;
362     }
363   if ( LOBYTE(wsdata.wVersion) != REQ_WINSOCK_MAJOR
364        || HIBYTE(wsdata.wVersion) != REQ_WINSOCK_MINOR )
365     {
366       log_error ("socket library version is %x.%x - but %d.%d needed\n",
367                  LOBYTE(wsdata.wVersion), HIBYTE(wsdata.wVersion),
368                  REQ_WINSOCK_MAJOR, REQ_WINSOCK_MINOR);
369       WSACleanup();
370       return;
371     }
372   atexit ( deinit_sockets );
373   initialized = 1;
374 }
375 #endif /*HAVE_W32_SYSTEM && !HTTP_NO_WSASTARTUP*/
376
377
378 /* Create a new socket object.  Returns NULL and closes FD if not
379    enough memory is available.  */
380 static my_socket_t
381 _my_socket_new (int lnr, assuan_fd_t fd)
382 {
383   my_socket_t so;
384
385   so = xtrymalloc (sizeof *so);
386   if (!so)
387     {
388       int save_errno = errno;
389       assuan_sock_close (fd);
390       gpg_err_set_errno (save_errno);
391       return NULL;
392     }
393   so->fd = fd;
394   so->refcount = 1;
395   if (opt_debug)
396     log_debug ("http.c:%d:socket_new: object %p for fd %d created\n",
397                lnr, so, (int)so->fd);
398   return so;
399 }
400 #define my_socket_new(a) _my_socket_new (__LINE__, (a))
401
402 /* Bump up the reference counter for the socket object SO.  */
403 static my_socket_t
404 _my_socket_ref (int lnr, my_socket_t so)
405 {
406   so->refcount++;
407   if (opt_debug > 1)
408     log_debug ("http.c:%d:socket_ref: object %p for fd %d refcount now %d\n",
409                lnr, so, (int)so->fd, so->refcount);
410   return so;
411 }
412 #define my_socket_ref(a) _my_socket_ref (__LINE__,(a))
413
414
415 /* Bump down the reference counter for the socket object SO.  If SO
416    has no more references, close the socket and release the
417    object.  */
418 static void
419 _my_socket_unref (int lnr, my_socket_t so,
420                   void (*preclose)(void*), void *preclosearg)
421 {
422   if (so)
423     {
424       so->refcount--;
425       if (opt_debug > 1)
426         log_debug ("http.c:%d:socket_unref: object %p for fd %d ref now %d\n",
427                    lnr, so, (int)so->fd, so->refcount);
428
429       if (!so->refcount)
430         {
431           if (preclose)
432             preclose (preclosearg);
433           assuan_sock_close (so->fd);
434           xfree (so);
435         }
436     }
437 }
438 #define my_socket_unref(a,b,c) _my_socket_unref (__LINE__,(a),(b),(c))
439
440
441 #ifdef HTTP_USE_GNUTLS
442 static ssize_t
443 my_gnutls_read (gnutls_transport_ptr_t ptr, void *buffer, size_t size)
444 {
445   my_socket_t sock = ptr;
446 #if USE_NPTH
447   return npth_read (sock->fd, buffer, size);
448 #else
449   return read (sock->fd, buffer, size);
450 #endif
451 }
452 static ssize_t
453 my_gnutls_write (gnutls_transport_ptr_t ptr, const void *buffer, size_t size)
454 {
455   my_socket_t sock = ptr;
456 #if USE_NPTH
457   return npth_write (sock->fd, buffer, size);
458 #else
459   return write (sock->fd, buffer, size);
460 #endif
461 }
462 #endif /*HTTP_USE_GNUTLS*/
463
464
465 #ifdef HTTP_USE_NTBTLS
466 /* Connect the ntbls callback to our generic callback.  */
467 static gpg_error_t
468 my_ntbtls_verify_cb (void *opaque, ntbtls_t tls, unsigned int verify_flags)
469 {
470   http_t hd = opaque;
471
472   (void)verify_flags;
473
474   log_assert (hd && hd->session && hd->session->verify_cb);
475   log_assert (hd->magic == HTTP_CONTEXT_MAGIC);
476   log_assert (hd->session->magic == HTTP_SESSION_MAGIC);
477
478   return hd->session->verify_cb (hd->session->verify_cb_value,
479                                  hd, hd->session,
480                                  (hd->flags | hd->session->flags),
481                                  tls);
482 }
483 #endif /*HTTP_USE_NTBTLS*/
484
485
486
487 \f
488 /* This notification function is called by estream whenever stream is
489    closed.  Its purpose is to mark the closing in the handle so
490    that a http_close won't accidentally close the estream.  The function
491    http_close removes this notification so that it won't be called if
492    http_close was used before an es_fclose.  */
493 static void
494 fp_onclose_notification (estream_t stream, void *opaque)
495 {
496   http_t hd = opaque;
497
498   log_assert (hd->magic == HTTP_CONTEXT_MAGIC);
499   if (hd->fp_read && hd->fp_read == stream)
500     hd->fp_read = NULL;
501   else if (hd->fp_write && hd->fp_write == stream)
502     hd->fp_write = NULL;
503 }
504
505
506 /*
507  * Helper function to create an HTTP header with hex encoded data.  A
508  * new buffer is returned.  This buffer is the concatenation of the
509  * string PREFIX, the hex-encoded DATA of length LEN and the string
510  * SUFFIX.  On error NULL is returned and ERRNO set.
511  */
512 static char *
513 make_header_line (const char *prefix, const char *suffix,
514                   const void *data, size_t len )
515 {
516   static unsigned char bintoasc[] =
517     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
518     "abcdefghijklmnopqrstuvwxyz"
519     "0123456789+/";
520   const unsigned char *s = data;
521   char *buffer, *p;
522
523   buffer = xtrymalloc (strlen (prefix) + (len+2)/3*4 + strlen (suffix) + 1);
524   if (!buffer)
525     return NULL;
526   p = stpcpy (buffer, prefix);
527   for ( ; len >= 3 ; len -= 3, s += 3 )
528     {
529       *p++ = bintoasc[(s[0] >> 2) & 077];
530       *p++ = bintoasc[(((s[0] <<4)&060)|((s[1] >> 4)&017))&077];
531       *p++ = bintoasc[(((s[1]<<2)&074)|((s[2]>>6)&03))&077];
532       *p++ = bintoasc[s[2]&077];
533       *p = 0;
534     }
535   if ( len == 2 )
536     {
537       *p++ = bintoasc[(s[0] >> 2) & 077];
538       *p++ = bintoasc[(((s[0] <<4)&060)|((s[1] >> 4)&017))&077];
539       *p++ = bintoasc[((s[1]<<2)&074)];
540       *p++ = '=';
541     }
542   else if ( len == 1 )
543     {
544       *p++ = bintoasc[(s[0] >> 2) & 077];
545       *p++ = bintoasc[(s[0] <<4)&060];
546       *p++ = '=';
547       *p++ = '=';
548     }
549   *p = 0;
550   strcpy (p, suffix);
551   return buffer;
552 }
553
554
555
556 \f
557 /* Set verbosity and debug mode for this module. */
558 void
559 http_set_verbose (int verbose, int debug)
560 {
561   opt_verbose = verbose;
562   opt_debug = debug;
563 }
564
565
566 /* Register a non-standard global TLS callback function.  If no
567    verification is desired a callback needs to be registered which
568    always returns NULL.  */
569 void
570 http_register_tls_callback (gpg_error_t (*cb)(http_t, http_session_t, int))
571 {
572   tls_callback = cb;
573 }
574
575
576 /* Register a CA certificate for future use.  The certificate is
577    expected to be in FNAME.  PEM format is assume if FNAME has a
578    suffix of ".pem".  If FNAME is NULL the list of CA files is
579    removed.  */
580 void
581 http_register_tls_ca (const char *fname)
582 {
583   strlist_t sl;
584
585   if (!fname)
586     {
587       free_strlist (tls_ca_certlist);
588       tls_ca_certlist = NULL;
589     }
590   else
591     {
592       /* Warn if we can't access right now, but register it anyway in
593          case it becomes accessible later */
594       if (access (fname, F_OK))
595         log_info (_("can't access '%s': %s\n"), fname,
596                   gpg_strerror (gpg_error_from_syserror()));
597       sl = add_to_strlist (&tls_ca_certlist, fname);
598       if (*sl->d && !strcmp (sl->d + strlen (sl->d) - 4, ".pem"))
599         sl->flags = 1;
600     }
601 }
602
603
604 /* Register a CA certificate for future use.  The certificate is
605  * expected to be in FNAME.  PEM format is assume if FNAME has a
606  * suffix of ".pem".  If FNAME is NULL the list of CA files is
607  * removed.  This is a variant of http_register_tls_ca which puts the
608  * certificate into a separate list enabled using HTTP_FLAG_TRUST_CFG.  */
609 void
610 http_register_cfg_ca (const char *fname)
611 {
612   strlist_t sl;
613
614   if (!fname)
615     {
616       free_strlist (cfg_ca_certlist);
617       cfg_ca_certlist = NULL;
618     }
619   else
620     {
621       /* Warn if we can't access right now, but register it anyway in
622          case it becomes accessible later */
623       if (access (fname, F_OK))
624         log_info (_("can't access '%s': %s\n"), fname,
625                   gpg_strerror (gpg_error_from_syserror()));
626       sl = add_to_strlist (&cfg_ca_certlist, fname);
627       if (*sl->d && !strcmp (sl->d + strlen (sl->d) - 4, ".pem"))
628         sl->flags = 1;
629     }
630 }
631
632
633 /* Register a callback which is called every time the HTTP mode has
634  * made a successful connection to some server.  */
635 void
636 http_register_netactivity_cb (void (*cb)(void))
637 {
638   netactivity_cb = cb;
639 }
640
641
642 /* Call the netactivity callback if any.  */
643 static void
644 notify_netactivity (void)
645 {
646   if (netactivity_cb)
647     netactivity_cb ();
648 }
649
650
651
652 #ifdef USE_TLS
653 /* Free the TLS session associated with SESS, if any.  */
654 static void
655 close_tls_session (http_session_t sess)
656 {
657   if (sess->tls_session)
658     {
659 # if HTTP_USE_NTBTLS
660       /* FIXME!!
661          Possibly, ntbtls_get_transport and close those streams.
662          Somehow get SOCK to call my_socket_unref.
663       */
664       ntbtls_release (sess->tls_session);
665 # elif HTTP_USE_GNUTLS
666       my_socket_t sock = gnutls_transport_get_ptr (sess->tls_session);
667       my_socket_unref (sock, NULL, NULL);
668       gnutls_deinit (sess->tls_session);
669       if (sess->certcred)
670         gnutls_certificate_free_credentials (sess->certcred);
671 # endif /*HTTP_USE_GNUTLS*/
672       xfree (sess->servername);
673       sess->tls_session = NULL;
674     }
675 }
676 #endif /*USE_TLS*/
677
678
679 /* Release a session.  Take care not to release it while it is being
680    used by a http context object.  */
681 static void
682 session_unref (int lnr, http_session_t sess)
683 {
684   if (!sess)
685     return;
686
687   log_assert (sess->magic == HTTP_SESSION_MAGIC);
688
689   sess->refcount--;
690   if (opt_debug > 1)
691     log_debug ("http.c:%d:session_unref: sess %p ref now %d\n",
692                lnr, sess, sess->refcount);
693   if (sess->refcount)
694     return;
695
696 #ifdef USE_TLS
697   close_tls_session (sess);
698 #endif /*USE_TLS*/
699
700   sess->magic = 0xdeadbeef;
701   xfree (sess);
702 }
703 #define http_session_unref(a) session_unref (__LINE__, (a))
704
705 void
706 http_session_release (http_session_t sess)
707 {
708   http_session_unref (sess);
709 }
710
711
712 /* Create a new session object which is currently used to enable TLS
713  * support.  It may eventually allow reusing existing connections.
714  * Valid values for FLAGS are:
715  *   HTTP_FLAG_TRUST_DEF - Use the CAs set with http_register_tls_ca
716  *   HTTP_FLAG_TRUST_SYS - Also use the CAs defined by the system
717  *   HTTP_FLAG_TRUST_CFG - Also use CAs set with http_register_cfg_ca
718  *   HTTP_FLAG_NO_CRL    - Do not consult CRLs for https.
719  */
720 gpg_error_t
721 http_session_new (http_session_t *r_session,
722                   const char *intended_hostname, unsigned int flags,
723                   http_verify_cb_t verify_cb, void *verify_cb_value)
724 {
725   gpg_error_t err;
726   http_session_t sess;
727
728   *r_session = NULL;
729
730   sess = xtrycalloc (1, sizeof *sess);
731   if (!sess)
732     return gpg_error_from_syserror ();
733   sess->magic = HTTP_SESSION_MAGIC;
734   sess->refcount = 1;
735   sess->flags = flags;
736   sess->verify_cb = verify_cb;
737   sess->verify_cb_value = verify_cb_value;
738   sess->connect_timeout = 0;
739
740 #if HTTP_USE_NTBTLS
741   {
742     (void)intended_hostname; /* Not needed because we do not preload
743                               * certificates.  */
744
745     err = ntbtls_new (&sess->tls_session, NTBTLS_CLIENT);
746     if (err)
747       {
748         log_error ("ntbtls_new failed: %s\n", gpg_strerror (err));
749         goto leave;
750       }
751
752   }
753 #elif HTTP_USE_GNUTLS
754   {
755     const char *errpos;
756     int rc;
757     strlist_t sl;
758     int add_system_cas = !!(flags & HTTP_FLAG_TRUST_SYS);
759     int is_hkps_pool;
760
761     rc = gnutls_certificate_allocate_credentials (&sess->certcred);
762     if (rc < 0)
763       {
764         log_error ("gnutls_certificate_allocate_credentials failed: %s\n",
765                    gnutls_strerror (rc));
766         err = gpg_error (GPG_ERR_GENERAL);
767         goto leave;
768       }
769
770     is_hkps_pool = (intended_hostname
771                     && !ascii_strcasecmp (intended_hostname,
772                                           get_default_keyserver (1)));
773
774     /* If the user has not specified a CA list, and they are looking
775      * for the hkps pool from sks-keyservers.net, then default to
776      * Kristian's certificate authority:  */
777     if (!tls_ca_certlist && is_hkps_pool)
778       {
779         char *pemname = make_filename_try (gnupg_datadir (),
780                                            "sks-keyservers.netCA.pem", NULL);
781         if (!pemname)
782           {
783             err = gpg_error_from_syserror ();
784             log_error ("setting CA from file '%s' failed: %s\n",
785                        pemname, gpg_strerror (err));
786           }
787         else
788           {
789             rc = gnutls_certificate_set_x509_trust_file
790               (sess->certcred, pemname, GNUTLS_X509_FMT_PEM);
791             if (rc < 0)
792               log_info ("setting CA from file '%s' failed: %s\n",
793                         pemname, gnutls_strerror (rc));
794             xfree (pemname);
795           }
796
797         add_system_cas = 0;
798       }
799
800     /* Add configured certificates to the session.  */
801     if ((flags & HTTP_FLAG_TRUST_DEF))
802       {
803         for (sl = tls_ca_certlist; sl; sl = sl->next)
804           {
805             rc = gnutls_certificate_set_x509_trust_file
806               (sess->certcred, sl->d,
807                (sl->flags & 1)? GNUTLS_X509_FMT_PEM : GNUTLS_X509_FMT_DER);
808             if (rc < 0)
809               log_info ("setting CA from file '%s' failed: %s\n",
810                         sl->d, gnutls_strerror (rc));
811           }
812         if (!tls_ca_certlist && !is_hkps_pool)
813           add_system_cas = 1;
814       }
815
816     /* Add system certificates to the session.  */
817     if (add_system_cas)
818       {
819 #if GNUTLS_VERSION_NUMBER >= 0x030014
820         static int shown;
821
822         rc = gnutls_certificate_set_x509_system_trust (sess->certcred);
823         if (rc < 0)
824           log_info ("setting system CAs failed: %s\n", gnutls_strerror (rc));
825         else if (!shown)
826           {
827             shown = 1;
828             log_info ("number of system provided CAs: %d\n", rc);
829           }
830 #endif /* gnutls >= 3.0.20 */
831       }
832
833     /* Add other configured certificates to the session.  */
834     if ((flags & HTTP_FLAG_TRUST_CFG))
835       {
836         for (sl = cfg_ca_certlist; sl; sl = sl->next)
837           {
838             rc = gnutls_certificate_set_x509_trust_file
839               (sess->certcred, sl->d,
840                (sl->flags & 1)? GNUTLS_X509_FMT_PEM : GNUTLS_X509_FMT_DER);
841             if (rc < 0)
842               log_info ("setting extra CA from file '%s' failed: %s\n",
843                         sl->d, gnutls_strerror (rc));
844           }
845       }
846
847
848     rc = gnutls_init (&sess->tls_session, GNUTLS_CLIENT);
849     if (rc < 0)
850       {
851         log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc));
852         err = gpg_error (GPG_ERR_GENERAL);
853         goto leave;
854       }
855     /* A new session has the transport ptr set to (void*(-1), we need
856        it to be NULL.  */
857     gnutls_transport_set_ptr (sess->tls_session, NULL);
858
859     rc = gnutls_priority_set_direct (sess->tls_session,
860                                      "NORMAL",
861                                      &errpos);
862     if (rc < 0)
863       {
864         log_error ("gnutls_priority_set_direct failed at '%s': %s\n",
865                    errpos, gnutls_strerror (rc));
866         err = gpg_error (GPG_ERR_GENERAL);
867         goto leave;
868       }
869
870     rc = gnutls_credentials_set (sess->tls_session,
871                                  GNUTLS_CRD_CERTIFICATE, sess->certcred);
872     if (rc < 0)
873       {
874         log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc));
875         err = gpg_error (GPG_ERR_GENERAL);
876         goto leave;
877       }
878   }
879 #else /*!HTTP_USE_GNUTLS && !HTTP_USE_NTBTLS*/
880   {
881     (void)intended_hostname;
882     (void)flags;
883   }
884 #endif /*!HTTP_USE_GNUTLS && !HTTP_USE_NTBTLS*/
885
886   if (opt_debug > 1)
887     log_debug ("http.c:session_new: sess %p created\n", sess);
888   err = 0;
889
890 #if USE_TLS
891  leave:
892 #endif /*USE_TLS*/
893   if (err)
894     http_session_unref (sess);
895   else
896     *r_session = sess;
897
898   return err;
899 }
900
901
902 /* Increment the reference count for session SESS.  Passing NULL for
903    SESS is allowed. */
904 http_session_t
905 http_session_ref (http_session_t sess)
906 {
907   if (sess)
908     {
909       sess->refcount++;
910       if (opt_debug > 1)
911         log_debug ("http.c:session_ref: sess %p ref now %d\n",
912                    sess, sess->refcount);
913     }
914   return sess;
915 }
916
917
918 void
919 http_session_set_log_cb (http_session_t sess,
920                          void (*cb)(http_session_t, gpg_error_t,
921                                     const char *hostname,
922                                     const void **certs, size_t *certlens))
923 {
924   sess->cert_log_cb = cb;
925 }
926
927
928 /* Set the TIMEOUT in milliseconds for the connection's connect
929  * calls.  Using 0 disables the timeout.  */
930 void
931 http_session_set_timeout (http_session_t sess, unsigned int timeout)
932 {
933   sess->connect_timeout = timeout;
934 }
935
936
937
938 \f
939 /* Start a HTTP retrieval and on success store at R_HD a context
940    pointer for completing the request and to wait for the response.
941    If HTTPHOST is not NULL it is used for the Host header instead of a
942    Host header derived from the URL. */
943 gpg_error_t
944 http_open (ctrl_t ctrl, http_t *r_hd, http_req_t reqtype, const char *url,
945            const char *httphost,
946            const char *auth, unsigned int flags, const char *proxy,
947            http_session_t session, const char *srvtag, strlist_t headers)
948 {
949   gpg_error_t err;
950   http_t hd;
951
952   *r_hd = NULL;
953
954   if (!(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST))
955     return gpg_err_make (default_errsource, GPG_ERR_INV_ARG);
956
957   /* Create the handle. */
958   hd = xtrycalloc (1, sizeof *hd);
959   if (!hd)
960     return gpg_error_from_syserror ();
961   hd->magic = HTTP_CONTEXT_MAGIC;
962   hd->req_type = reqtype;
963   hd->flags = flags;
964   hd->session = http_session_ref (session);
965
966   err = parse_uri (&hd->uri, url, 0, !!(flags & HTTP_FLAG_FORCE_TLS));
967   if (!err)
968     err = send_request (ctrl, hd, httphost, auth, proxy, srvtag,
969                         hd->session? hd->session->connect_timeout : 0,
970                         headers);
971
972   if (err)
973     {
974       my_socket_unref (hd->sock, NULL, NULL);
975       if (hd->fp_read)
976         es_fclose (hd->fp_read);
977       if (hd->fp_write)
978         es_fclose (hd->fp_write);
979       http_session_unref (hd->session);
980       xfree (hd);
981     }
982   else
983     *r_hd = hd;
984   return err;
985 }
986
987
988 /* This function is useful to connect to a generic TCP service using
989    this http abstraction layer.  This has the advantage of providing
990    service tags and an estream interface.  TIMEOUT is in milliseconds. */
991 gpg_error_t
992 http_raw_connect (ctrl_t ctrl, http_t *r_hd,
993                   const char *server, unsigned short port,
994                   unsigned int flags, const char *srvtag, unsigned int timeout)
995 {
996   gpg_error_t err = 0;
997   http_t hd;
998   cookie_t cookie;
999
1000   *r_hd = NULL;
1001
1002   if ((flags & HTTP_FLAG_FORCE_TOR))
1003     {
1004       int mode;
1005
1006       if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
1007         {
1008           log_error ("Tor support is not available\n");
1009           return gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1010         }
1011       /* Non-blocking connects do not work with our Tor proxy because
1012        * we can't continue the Socks protocol after the EINPROGRESS.
1013        * Disable the timeout to use a blocking connect.  */
1014       timeout = 0;
1015     }
1016
1017   /* Create the handle. */
1018   hd = xtrycalloc (1, sizeof *hd);
1019   if (!hd)
1020     return gpg_error_from_syserror ();
1021   hd->magic = HTTP_CONTEXT_MAGIC;
1022   hd->req_type = HTTP_REQ_OPAQUE;
1023   hd->flags = flags;
1024
1025   /* Connect.  */
1026   {
1027     assuan_fd_t sock;
1028
1029     err = connect_server (ctrl, server, port,
1030                           hd->flags, srvtag, timeout, &sock);
1031     if (err)
1032       {
1033         xfree (hd);
1034         return err;
1035       }
1036     hd->sock = my_socket_new (sock);
1037     if (!hd->sock)
1038       {
1039         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1040         xfree (hd);
1041         return err;
1042       }
1043   }
1044
1045   /* Setup estreams for reading and writing.  */
1046   cookie = xtrycalloc (1, sizeof *cookie);
1047   if (!cookie)
1048     {
1049       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1050       goto leave;
1051     }
1052   cookie->sock = my_socket_ref (hd->sock);
1053   hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1054   if (!hd->fp_write)
1055     {
1056       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1057       my_socket_unref (cookie->sock, NULL, NULL);
1058       xfree (cookie);
1059       goto leave;
1060     }
1061   hd->write_cookie = cookie; /* Cookie now owned by FP_WRITE.  */
1062
1063   cookie = xtrycalloc (1, sizeof *cookie);
1064   if (!cookie)
1065     {
1066       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1067       goto leave;
1068     }
1069   cookie->sock = my_socket_ref (hd->sock);
1070   hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
1071   if (!hd->fp_read)
1072     {
1073       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1074       my_socket_unref (cookie->sock, NULL, NULL);
1075       xfree (cookie);
1076       goto leave;
1077     }
1078   hd->read_cookie = cookie; /* Cookie now owned by FP_READ.  */
1079
1080   /* Register close notification to interlock the use of es_fclose in
1081      http_close and in user code.  */
1082   err = es_onclose (hd->fp_write, 1, fp_onclose_notification, hd);
1083   if (!err)
1084     err = es_onclose (hd->fp_read, 1, fp_onclose_notification, hd);
1085
1086  leave:
1087   if (err)
1088     {
1089       if (hd->fp_read)
1090         es_fclose (hd->fp_read);
1091       if (hd->fp_write)
1092         es_fclose (hd->fp_write);
1093       my_socket_unref (hd->sock, NULL, NULL);
1094       xfree (hd);
1095     }
1096   else
1097     *r_hd = hd;
1098   return err;
1099 }
1100
1101
1102
1103
1104 void
1105 http_start_data (http_t hd)
1106 {
1107   if (!hd->in_data)
1108     {
1109       if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
1110         log_debug_string ("\r\n", "http.c:request-header:");
1111       es_fputs ("\r\n", hd->fp_write);
1112       es_fflush (hd->fp_write);
1113       hd->in_data = 1;
1114     }
1115   else
1116     es_fflush (hd->fp_write);
1117 }
1118
1119
1120 gpg_error_t
1121 http_wait_response (http_t hd)
1122 {
1123   gpg_error_t err;
1124   cookie_t cookie;
1125   int use_tls;
1126
1127   /* Make sure that we are in the data. */
1128   http_start_data (hd);
1129
1130   /* Close the write stream.  Note that the reference counted socket
1131      object keeps the actual system socket open.  */
1132   cookie = hd->write_cookie;
1133   if (!cookie)
1134     return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1135
1136   use_tls = cookie->use_tls;
1137   es_fclose (hd->fp_write);
1138   hd->fp_write = NULL;
1139   /* The close has released the cookie and thus we better set it to NULL.  */
1140   hd->write_cookie = NULL;
1141
1142   /* Shutdown one end of the socket is desired.  As per HTTP/1.0 this
1143      is not required but some very old servers (e.g. the original pksd
1144      keyserver didn't worked without it.  */
1145   if ((hd->flags & HTTP_FLAG_SHUTDOWN))
1146     shutdown (FD2INT (hd->sock->fd), 1);
1147   hd->in_data = 0;
1148
1149   /* Create a new cookie and a stream for reading.  */
1150   cookie = xtrycalloc (1, sizeof *cookie);
1151   if (!cookie)
1152     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1153   cookie->sock = my_socket_ref (hd->sock);
1154   cookie->session = http_session_ref (hd->session);
1155   cookie->use_tls = use_tls;
1156
1157   hd->read_cookie = cookie;
1158   hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
1159   if (!hd->fp_read)
1160     {
1161       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1162       my_socket_unref (cookie->sock, NULL, NULL);
1163       http_session_unref (cookie->session);
1164       xfree (cookie);
1165       hd->read_cookie = NULL;
1166       return err;
1167     }
1168
1169   err = parse_response (hd);
1170
1171   if (!err)
1172     err = es_onclose (hd->fp_read, 1, fp_onclose_notification, hd);
1173
1174   return err;
1175 }
1176
1177
1178 /* Convenience function to send a request and wait for the response.
1179    Closes the handle on error.  If PROXY is not NULL, this value will
1180    be used as an HTTP proxy and any enabled $http_proxy gets
1181    ignored. */
1182 gpg_error_t
1183 http_open_document (ctrl_t ctrl, http_t *r_hd, const char *document,
1184                     const char *auth, unsigned int flags, const char *proxy,
1185                     http_session_t session,
1186                     const char *srvtag, strlist_t headers)
1187 {
1188   gpg_error_t err;
1189
1190   err = http_open (ctrl, r_hd, HTTP_REQ_GET, document, NULL, auth, flags,
1191                    proxy, session, srvtag, headers);
1192   if (err)
1193     return err;
1194
1195   err = http_wait_response (*r_hd);
1196   if (err)
1197     http_close (*r_hd, 0);
1198
1199   return err;
1200 }
1201
1202
1203 void
1204 http_close (http_t hd, int keep_read_stream)
1205 {
1206   if (!hd)
1207     return;
1208
1209   log_assert (hd->magic == HTTP_CONTEXT_MAGIC);
1210
1211   /* First remove the close notifications for the streams.  */
1212   if (hd->fp_read)
1213     es_onclose (hd->fp_read, 0, fp_onclose_notification, hd);
1214   if (hd->fp_write)
1215     es_onclose (hd->fp_write, 0, fp_onclose_notification, hd);
1216
1217   /* Now we can close the streams.  */
1218   my_socket_unref (hd->sock, NULL, NULL);
1219   if (hd->fp_read && !keep_read_stream)
1220     es_fclose (hd->fp_read);
1221   if (hd->fp_write)
1222     es_fclose (hd->fp_write);
1223   http_session_unref (hd->session);
1224   hd->magic = 0xdeadbeef;
1225   http_release_parsed_uri (hd->uri);
1226   while (hd->headers)
1227     {
1228       header_t tmp = hd->headers->next;
1229       xfree (hd->headers->value);
1230       xfree (hd->headers);
1231       hd->headers = tmp;
1232     }
1233   xfree (hd->buffer);
1234   xfree (hd);
1235 }
1236
1237
1238 estream_t
1239 http_get_read_ptr (http_t hd)
1240 {
1241   return hd?hd->fp_read:NULL;
1242 }
1243
1244 estream_t
1245 http_get_write_ptr (http_t hd)
1246 {
1247   return hd?hd->fp_write:NULL;
1248 }
1249
1250 unsigned int
1251 http_get_status_code (http_t hd)
1252 {
1253   return hd?hd->status_code:0;
1254 }
1255
1256 /* Return information pertaining to TLS.  If TLS is not in use for HD,
1257    NULL is returned.  WHAT is used ask for specific information:
1258
1259      (NULL) := Only check whether TLS is in use.  Returns an
1260                unspecified string if TLS is in use.  That string may
1261                even be the empty string.
1262  */
1263 const char *
1264 http_get_tls_info (http_t hd, const char *what)
1265 {
1266   (void)what;
1267
1268   if (!hd)
1269     return NULL;
1270
1271   return hd->uri->use_tls? "":NULL;
1272 }
1273
1274
1275 \f
1276 static gpg_error_t
1277 parse_uri (parsed_uri_t *ret_uri, const char *uri,
1278            int no_scheme_check, int force_tls)
1279 {
1280   gpg_err_code_t ec;
1281
1282   *ret_uri = xtrycalloc (1, sizeof **ret_uri + 2 * strlen (uri) + 1);
1283   if (!*ret_uri)
1284     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1285   strcpy ((*ret_uri)->buffer, uri);
1286   strcpy ((*ret_uri)->buffer + strlen (uri) + 1, uri);
1287   (*ret_uri)->original = (*ret_uri)->buffer + strlen (uri) + 1;
1288   ec = do_parse_uri (*ret_uri, 0, no_scheme_check, force_tls);
1289   if (ec)
1290     {
1291       http_release_parsed_uri (*ret_uri);
1292       *ret_uri = NULL;
1293     }
1294   return gpg_err_make (default_errsource, ec);
1295 }
1296
1297
1298 /*
1299  * Parse an URI and put the result into the newly allocated RET_URI.
1300  * On success the caller must use http_release_parsed_uri() to
1301  * releases the resources.  If NO_SCHEME_CHECK is set, the function
1302  * tries to parse the URL in the same way it would do for an HTTP
1303  * style URI.
1304  */
1305 gpg_error_t
1306 http_parse_uri (parsed_uri_t *ret_uri, const char *uri,
1307                 int no_scheme_check)
1308 {
1309   return parse_uri (ret_uri, uri, no_scheme_check, 0);
1310 }
1311
1312
1313 void
1314 http_release_parsed_uri (parsed_uri_t uri)
1315 {
1316   if (uri)
1317     {
1318       uri_tuple_t r, r2;
1319
1320       for (r = uri->params; r; r = r2)
1321         {
1322           r2 = r->next;
1323           xfree (r);
1324         }
1325       for (r = uri->query; r; r = r2)
1326         {
1327           r2 = r->next;
1328           xfree (r);
1329         }
1330       xfree (uri);
1331     }
1332 }
1333
1334
1335 static gpg_err_code_t
1336 do_parse_uri (parsed_uri_t uri, int only_local_part,
1337               int no_scheme_check, int force_tls)
1338 {
1339   uri_tuple_t *tail;
1340   char *p, *p2, *p3, *pp;
1341   int n;
1342
1343   p = uri->buffer;
1344   n = strlen (uri->buffer);
1345
1346   /* Initialize all fields to an empty string or an empty list. */
1347   uri->scheme = uri->host = uri->path = p + n;
1348   uri->port = 0;
1349   uri->params = uri->query = NULL;
1350   uri->use_tls = 0;
1351   uri->is_http = 0;
1352   uri->opaque = 0;
1353   uri->v6lit = 0;
1354   uri->onion = 0;
1355   uri->explicit_port = 0;
1356   uri->off_host = 0;
1357   uri->off_path = 0;
1358
1359   /* A quick validity check. */
1360   if (strspn (p, VALID_URI_CHARS) != n)
1361     return GPG_ERR_BAD_URI;     /* Invalid characters found. */
1362
1363   if (!only_local_part)
1364     {
1365       /* Find the scheme. */
1366       if (!(p2 = strchr (p, ':')) || p2 == p)
1367         return GPG_ERR_BAD_URI; /* No scheme. */
1368       *p2++ = 0;
1369       for (pp=p; *pp; pp++)
1370        *pp = tolower (*(unsigned char*)pp);
1371       uri->scheme = p;
1372       if (!strcmp (uri->scheme, "http") && !force_tls)
1373         {
1374           uri->port = 80;
1375           uri->is_http = 1;
1376         }
1377       else if (!strcmp (uri->scheme, "hkp") && !force_tls)
1378         {
1379           uri->port = 11371;
1380           uri->is_http = 1;
1381         }
1382 #ifdef USE_TLS
1383       else if (!strcmp (uri->scheme, "https") || !strcmp (uri->scheme,"hkps")
1384                || (force_tls && (!strcmp (uri->scheme, "http")
1385                                  || !strcmp (uri->scheme,"hkp"))))
1386         {
1387           uri->port = 443;
1388           uri->is_http = 1;
1389           uri->use_tls = 1;
1390         }
1391 #endif /*USE_TLS*/
1392       else if (!no_scheme_check)
1393         return GPG_ERR_INV_URI; /* Unsupported scheme */
1394
1395       p = p2;
1396
1397       if (*p == '/' && p[1] == '/' ) /* There seems to be a hostname. */
1398         {
1399           p += 2;
1400           if ((p2 = strchr (p, '/')))
1401             {
1402               if (p2 - uri->buffer > 10000)
1403                 return GPG_ERR_BAD_URI;
1404               uri->off_path = p2 - uri->buffer;
1405               *p2++ = 0;
1406             }
1407           else
1408             {
1409               n = (p - uri->buffer) + strlen (p);
1410               if (n > 10000)
1411                 return GPG_ERR_BAD_URI;
1412               uri->off_path = n;
1413             }
1414
1415           /* Check for username/password encoding */
1416           if ((p3 = strchr (p, '@')))
1417             {
1418               uri->auth = p;
1419               *p3++ = '\0';
1420               p = p3;
1421             }
1422
1423           for (pp=p; *pp; pp++)
1424             *pp = tolower (*(unsigned char*)pp);
1425
1426           /* Handle an IPv6 literal */
1427           if( *p == '[' && (p3=strchr( p, ']' )) )
1428             {
1429               *p3++ = '\0';
1430               /* worst case, uri->host should have length 0, points to \0 */
1431               uri->host = p + 1;
1432               if (p - uri->buffer > 10000)
1433                 return GPG_ERR_BAD_URI;
1434               uri->off_host = (p + 1) - uri->buffer;
1435               uri->v6lit = 1;
1436               p = p3;
1437             }
1438           else
1439             {
1440               uri->host = p;
1441               if (p - uri->buffer > 10000)
1442                 return GPG_ERR_BAD_URI;
1443               uri->off_host = p - uri->buffer;
1444             }
1445
1446           if ((p3 = strchr (p, ':')))
1447             {
1448               *p3++ = '\0';
1449               uri->port = atoi (p3);
1450               uri->explicit_port = 1;
1451             }
1452
1453           if ((n = remove_escapes (uri->host)) < 0)
1454             return GPG_ERR_BAD_URI;
1455           if (n != strlen (uri->host))
1456             return GPG_ERR_BAD_URI;     /* Hostname includes a Nul. */
1457           p = p2 ? p2 : NULL;
1458         }
1459       else if (uri->is_http)
1460         return GPG_ERR_INV_URI; /* No Leading double slash for HTTP.  */
1461       else
1462         {
1463           uri->opaque = 1;
1464           uri->path = p;
1465           if (is_onion_address (uri->path))
1466             uri->onion = 1;
1467           return 0;
1468         }
1469
1470     } /* End global URI part. */
1471
1472   /* Parse the pathname part if any.  */
1473   if (p && *p)
1474     {
1475       /* TODO: Here we have to check params. */
1476
1477       /* Do we have a query part? */
1478       if ((p2 = strchr (p, '?')))
1479         *p2++ = 0;
1480
1481       uri->path = p;
1482       if ((n = remove_escapes (p)) < 0)
1483         return GPG_ERR_BAD_URI;
1484       if (n != strlen (p))
1485         return GPG_ERR_BAD_URI; /* Path includes a Nul. */
1486       p = p2 ? p2 : NULL;
1487
1488       /* Parse a query string if any.  */
1489       if (p && *p)
1490         {
1491           tail = &uri->query;
1492           for (;;)
1493             {
1494               uri_tuple_t elem;
1495
1496               if ((p2 = strchr (p, '&')))
1497                 *p2++ = 0;
1498               if (!(elem = parse_tuple (p)))
1499                 return GPG_ERR_BAD_URI;
1500               *tail = elem;
1501               tail = &elem->next;
1502
1503               if (!p2)
1504                 break; /* Ready. */
1505               p = p2;
1506             }
1507         }
1508     }
1509
1510   if (is_onion_address (uri->host))
1511     uri->onion = 1;
1512
1513   return 0;
1514 }
1515
1516
1517 /*
1518  * Remove all %xx escapes; this is done in-place.  Returns: New length
1519  * of the string.
1520  */
1521 static int
1522 remove_escapes (char *string)
1523 {
1524   int n = 0;
1525   unsigned char *p, *s;
1526
1527   for (p = s = (unsigned char*)string; *s; s++)
1528     {
1529       if (*s == '%')
1530         {
1531           if (s[1] && s[2] && isxdigit (s[1]) && isxdigit (s[2]))
1532             {
1533               s++;
1534               *p = *s >= '0' && *s <= '9' ? *s - '0' :
1535                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
1536               *p <<= 4;
1537               s++;
1538               *p |= *s >= '0' && *s <= '9' ? *s - '0' :
1539                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
1540               p++;
1541               n++;
1542             }
1543           else
1544             {
1545               *p++ = *s++;
1546               if (*s)
1547                 *p++ = *s++;
1548               if (*s)
1549                 *p++ = *s++;
1550               if (*s)
1551                 *p = 0;
1552               return -1; /* Bad URI. */
1553             }
1554         }
1555       else
1556         {
1557           *p++ = *s;
1558           n++;
1559         }
1560     }
1561   *p = 0; /* Make sure to keep a string terminator. */
1562   return n;
1563 }
1564
1565
1566 /* If SPECIAL is NULL this function escapes in forms mode.  */
1567 static size_t
1568 escape_data (char *buffer, const void *data, size_t datalen,
1569              const char *special)
1570 {
1571   int forms = !special;
1572   const unsigned char *s;
1573   size_t n = 0;
1574
1575   if (forms)
1576     special = "%;?&=";
1577
1578   for (s = data; datalen; s++, datalen--)
1579     {
1580       if (forms && *s == ' ')
1581         {
1582           if (buffer)
1583             *buffer++ = '+';
1584           n++;
1585         }
1586       else if (forms && *s == '\n')
1587         {
1588           if (buffer)
1589             memcpy (buffer, "%0D%0A", 6);
1590           n += 6;
1591         }
1592       else if (forms && *s == '\r' && datalen > 1 && s[1] == '\n')
1593         {
1594           if (buffer)
1595             memcpy (buffer, "%0D%0A", 6);
1596           n += 6;
1597           s++;
1598           datalen--;
1599         }
1600       else if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
1601         {
1602           if (buffer)
1603             *(unsigned char*)buffer++ = *s;
1604           n++;
1605         }
1606       else
1607         {
1608           if (buffer)
1609             {
1610               snprintf (buffer, 4, "%%%02X", *s);
1611               buffer += 3;
1612             }
1613           n += 3;
1614         }
1615     }
1616   return n;
1617 }
1618
1619
1620 static int
1621 insert_escapes (char *buffer, const char *string,
1622                 const char *special)
1623 {
1624   return escape_data (buffer, string, strlen (string), special);
1625 }
1626
1627
1628 /* Allocate a new string from STRING using standard HTTP escaping as
1629    well as escaping of characters given in SPECIALS.  A common pattern
1630    for SPECIALS is "%;?&=". However it depends on the needs, for
1631    example "+" and "/: often needs to be escaped too.  Returns NULL on
1632    failure and sets ERRNO.  If SPECIAL is NULL a dedicated forms
1633    encoding mode is used. */
1634 char *
1635 http_escape_string (const char *string, const char *specials)
1636 {
1637   int n;
1638   char *buf;
1639
1640   n = insert_escapes (NULL, string, specials);
1641   buf = xtrymalloc (n+1);
1642   if (buf)
1643     {
1644       insert_escapes (buf, string, specials);
1645       buf[n] = 0;
1646     }
1647   return buf;
1648 }
1649
1650 /* Allocate a new string from {DATA,DATALEN} using standard HTTP
1651    escaping as well as escaping of characters given in SPECIALS.  A
1652    common pattern for SPECIALS is "%;?&=".  However it depends on the
1653    needs, for example "+" and "/: often needs to be escaped too.
1654    Returns NULL on failure and sets ERRNO.  If SPECIAL is NULL a
1655    dedicated forms encoding mode is used. */
1656 char *
1657 http_escape_data (const void *data, size_t datalen, const char *specials)
1658 {
1659   int n;
1660   char *buf;
1661
1662   n = escape_data (NULL, data, datalen, specials);
1663   buf = xtrymalloc (n+1);
1664   if (buf)
1665     {
1666       escape_data (buf, data, datalen, specials);
1667       buf[n] = 0;
1668     }
1669   return buf;
1670 }
1671
1672
1673 static uri_tuple_t
1674 parse_tuple (char *string)
1675 {
1676   char *p = string;
1677   char *p2;
1678   int n;
1679   uri_tuple_t tuple;
1680
1681   if ((p2 = strchr (p, '=')))
1682     *p2++ = 0;
1683   if ((n = remove_escapes (p)) < 0)
1684     return NULL; /* Bad URI. */
1685   if (n != strlen (p))
1686     return NULL; /* Name with a Nul in it. */
1687   tuple = xtrycalloc (1, sizeof *tuple);
1688   if (!tuple)
1689     return NULL; /* Out of core. */
1690   tuple->name = p;
1691   if (!p2) /* We have only the name, so we assume an empty value string. */
1692     {
1693       tuple->value = p + strlen (p);
1694       tuple->valuelen = 0;
1695       tuple->no_value = 1; /* Explicitly mark that we have seen no '='. */
1696     }
1697   else /* Name and value. */
1698     {
1699       if ((n = remove_escapes (p2)) < 0)
1700         {
1701           xfree (tuple);
1702           return NULL; /* Bad URI. */
1703         }
1704       tuple->value = p2;
1705       tuple->valuelen = n;
1706     }
1707   return tuple;
1708 }
1709
1710
1711 /* Return true if STRING is likely "hostname:port" or only "hostname".  */
1712 static int
1713 is_hostname_port (const char *string)
1714 {
1715   int colons = 0;
1716
1717   if (!string || !*string)
1718     return 0;
1719   for (; *string; string++)
1720     {
1721       if (*string == ':')
1722         {
1723           if (colons)
1724             return 0;
1725           if (!string[1])
1726             return 0;
1727           colons++;
1728         }
1729       else if (!colons && strchr (" \t\f\n\v_@[]/", *string))
1730         return 0; /* Invalid characters in hostname. */
1731       else if (colons && !digitp (string))
1732         return 0; /* Not a digit in the port.  */
1733     }
1734   return 1;
1735 }
1736
1737
1738 /*
1739  * Send a HTTP request to the server
1740  * Returns 0 if the request was successful
1741  */
1742 static gpg_error_t
1743 send_request (ctrl_t ctrl, http_t hd, const char *httphost, const char *auth,
1744               const char *proxy, const char *srvtag, unsigned int timeout,
1745               strlist_t headers)
1746 {
1747   gpg_error_t err;
1748   const char *server;
1749   char *request, *p;
1750   unsigned short port;
1751   const char *http_proxy = NULL;
1752   char *proxy_authstr = NULL;
1753   char *authstr = NULL;
1754   assuan_fd_t sock;
1755 #ifdef USE_TLS
1756   int have_http_proxy = 0;
1757 #endif
1758
1759   if (hd->uri->use_tls && !hd->session)
1760     {
1761       log_error ("TLS requested but no session object provided\n");
1762       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1763     }
1764 #ifdef USE_TLS
1765   if (hd->uri->use_tls && !hd->session->tls_session)
1766     {
1767       log_error ("TLS requested but no TLS context available\n");
1768       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1769     }
1770   if (opt_debug)
1771     log_debug ("Using TLS library: %s %s\n",
1772 # if HTTP_USE_NTBTLS
1773                "NTBTLS", ntbtls_check_version (NULL)
1774 # elif HTTP_USE_GNUTLS
1775                "GNUTLS", gnutls_check_version (NULL)
1776 # else
1777                "?", "?"
1778 # endif /*HTTP_USE_*TLS*/
1779                );
1780 #endif /*USE_TLS*/
1781
1782   if ((hd->flags & HTTP_FLAG_FORCE_TOR))
1783     {
1784       int mode;
1785
1786       if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
1787         {
1788           log_error ("Tor support is not available\n");
1789           return gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1790         }
1791       /* Non-blocking connects do not work with our Tor proxy because
1792        * we can't continue the Socks protocol after the EINPROGRESS.
1793        * Disable the timeout to use a blocking connect.  */
1794       timeout = 0;
1795     }
1796
1797   server = *hd->uri->host ? hd->uri->host : "localhost";
1798   port = hd->uri->port ? hd->uri->port : 80;
1799
1800   /* Try to use SNI.  */
1801 #ifdef USE_TLS
1802   if (hd->uri->use_tls)
1803     {
1804 # if HTTP_USE_GNUTLS
1805       int rc;
1806 # endif
1807
1808       xfree (hd->session->servername);
1809       hd->session->servername = xtrystrdup (httphost? httphost : server);
1810       if (!hd->session->servername)
1811         {
1812           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1813           return err;
1814         }
1815
1816 # if HTTP_USE_NTBTLS
1817       err = ntbtls_set_hostname (hd->session->tls_session,
1818                                  hd->session->servername);
1819       if (err)
1820         {
1821           log_info ("ntbtls_set_hostname failed: %s\n", gpg_strerror (err));
1822           return err;
1823         }
1824 # elif HTTP_USE_GNUTLS
1825       rc = gnutls_server_name_set (hd->session->tls_session,
1826                                    GNUTLS_NAME_DNS,
1827                                    hd->session->servername,
1828                                    strlen (hd->session->servername));
1829       if (rc < 0)
1830         log_info ("gnutls_server_name_set failed: %s\n", gnutls_strerror (rc));
1831 # endif /*HTTP_USE_GNUTLS*/
1832     }
1833 #endif /*USE_TLS*/
1834
1835   if ( (proxy && *proxy)
1836        || ( (hd->flags & HTTP_FLAG_TRY_PROXY)
1837             && (http_proxy = getenv (HTTP_PROXY_ENV))
1838             && *http_proxy ))
1839     {
1840       parsed_uri_t uri;
1841
1842       if (proxy)
1843         http_proxy = proxy;
1844
1845       err = parse_uri (&uri, http_proxy, 0, 0);
1846       if (gpg_err_code (err) == GPG_ERR_INV_URI
1847           && is_hostname_port (http_proxy))
1848         {
1849           /* Retry assuming a "hostname:port" string.  */
1850           char *tmpname = strconcat ("http://", http_proxy, NULL);
1851           if (tmpname && !parse_uri (&uri, tmpname, 0, 0))
1852             err = 0;
1853           xfree (tmpname);
1854         }
1855
1856       if (err)
1857         ;
1858 #ifdef USE_TLS
1859       else if (!strcmp (uri->scheme, "http"))
1860         have_http_proxy = 1;
1861 #endif
1862       else if (!strcmp (uri->scheme, "socks4")
1863                || !strcmp (uri->scheme, "socks5h"))
1864         err = gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1865       else
1866         err = gpg_err_make (default_errsource, GPG_ERR_INV_URI);
1867
1868       if (err)
1869         {
1870           log_error ("invalid HTTP proxy (%s): %s\n",
1871                      http_proxy, gpg_strerror (err));
1872           return gpg_err_make (default_errsource, GPG_ERR_CONFIGURATION);
1873         }
1874
1875       if (uri->auth)
1876         {
1877           remove_escapes (uri->auth);
1878           proxy_authstr = make_header_line ("Proxy-Authorization: Basic ",
1879                                             "\r\n",
1880                                             uri->auth, strlen(uri->auth));
1881           if (!proxy_authstr)
1882             {
1883               err = gpg_err_make (default_errsource,
1884                                   gpg_err_code_from_syserror ());
1885               http_release_parsed_uri (uri);
1886               return err;
1887             }
1888         }
1889
1890       err = connect_server (ctrl,
1891                             *uri->host ? uri->host : "localhost",
1892                             uri->port ? uri->port : 80,
1893                             hd->flags, NULL, timeout, &sock);
1894       http_release_parsed_uri (uri);
1895     }
1896   else
1897     {
1898       err = connect_server (ctrl,
1899                             server, port, hd->flags, srvtag, timeout, &sock);
1900     }
1901
1902   if (err)
1903     {
1904       xfree (proxy_authstr);
1905       return err;
1906     }
1907   hd->sock = my_socket_new (sock);
1908   if (!hd->sock)
1909     {
1910       xfree (proxy_authstr);
1911       return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1912     }
1913
1914 #if USE_TLS
1915   if (have_http_proxy && hd->uri->use_tls)
1916     {
1917       int saved_flags;
1918       cookie_t cookie;
1919
1920       /* Try to use the CONNECT method to proxy our TLS stream.  */
1921       request = es_bsprintf
1922         ("CONNECT %s:%hu HTTP/1.0\r\nHost: %s:%hu\r\n%s",
1923          httphost ? httphost : server,
1924          port,
1925          httphost ? httphost : server,
1926          port,
1927          proxy_authstr ? proxy_authstr : "");
1928       xfree (proxy_authstr);
1929       proxy_authstr = NULL;
1930
1931       if (! request)
1932         return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1933
1934       if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
1935         log_debug_string (request, "http.c:request:");
1936
1937       cookie = xtrycalloc (1, sizeof *cookie);
1938       if (! cookie)
1939         {
1940           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1941           xfree (request);
1942           return err;
1943         }
1944       cookie->sock = my_socket_ref (hd->sock);
1945       hd->write_cookie = cookie;
1946
1947       hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1948       if (! hd->fp_write)
1949         {
1950           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1951           my_socket_unref (cookie->sock, NULL, NULL);
1952           xfree (cookie);
1953           xfree (request);
1954           hd->write_cookie = NULL;
1955           return err;
1956         }
1957       else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
1958         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1959
1960       xfree (request);
1961       request = NULL;
1962
1963       /* Make sure http_wait_response doesn't close the stream.  */
1964       saved_flags = hd->flags;
1965       hd->flags &= ~HTTP_FLAG_SHUTDOWN;
1966
1967       /* Get the response.  */
1968       err = http_wait_response (hd);
1969
1970       /* Restore flags, destroy stream.  */
1971       hd->flags = saved_flags;
1972       es_fclose (hd->fp_read);
1973       hd->fp_read = NULL;
1974       hd->read_cookie = NULL;
1975
1976       /* Reset state.  */
1977       hd->in_data = 0;
1978
1979       if (err)
1980         return err;
1981
1982       if (hd->status_code != 200)
1983         {
1984           request = es_bsprintf
1985             ("CONNECT %s:%hu",
1986              httphost ? httphost : server,
1987              port);
1988
1989           log_error (_("error accessing '%s': http status %u\n"),
1990                      request ? request : "out of core",
1991                      http_get_status_code (hd));
1992
1993           xfree (request);
1994           return gpg_error (GPG_ERR_NO_DATA);
1995         }
1996
1997       /* We are done with the proxy, the code below will establish a
1998        * TLS session and talk directly to the target server.  */
1999       http_proxy = NULL;
2000     }
2001 #endif  /* USE_TLS */
2002
2003 #if HTTP_USE_NTBTLS
2004   if (hd->uri->use_tls)
2005     {
2006       estream_t in, out;
2007
2008       my_socket_ref (hd->sock);
2009
2010       /* Until we support send/recv in estream under Windows we need
2011        * to use es_fopencookie.  */
2012 #ifdef HAVE_W32_SYSTEM
2013       in = es_fopencookie ((void*)(unsigned int)hd->sock->fd, "rb",
2014                            simple_cookie_functions);
2015 #else
2016       in = es_fdopen_nc (hd->sock->fd, "rb");
2017 #endif
2018       if (!in)
2019         {
2020           err = gpg_error_from_syserror ();
2021           xfree (proxy_authstr);
2022           return err;
2023         }
2024
2025 #ifdef HAVE_W32_SYSTEM
2026       out = es_fopencookie ((void*)(unsigned int)hd->sock->fd, "wb",
2027                             simple_cookie_functions);
2028 #else
2029       out = es_fdopen_nc (hd->sock->fd, "wb");
2030 #endif
2031       if (!out)
2032         {
2033           err = gpg_error_from_syserror ();
2034           es_fclose (in);
2035           xfree (proxy_authstr);
2036           return err;
2037         }
2038
2039       err = ntbtls_set_transport (hd->session->tls_session, in, out);
2040       if (err)
2041         {
2042           log_info ("TLS set_transport failed: %s <%s>\n",
2043                     gpg_strerror (err), gpg_strsource (err));
2044           xfree (proxy_authstr);
2045           return err;
2046         }
2047
2048 #ifdef HTTP_USE_NTBTLS
2049       if (hd->session->verify_cb)
2050         {
2051           err = ntbtls_set_verify_cb (hd->session->tls_session,
2052                                       my_ntbtls_verify_cb, hd);
2053           if (err)
2054             {
2055               log_error ("ntbtls_set_verify_cb failed: %s\n",
2056                          gpg_strerror (err));
2057               xfree (proxy_authstr);
2058               return err;
2059             }
2060         }
2061 #endif /*HTTP_USE_NTBTLS*/
2062
2063       while ((err = ntbtls_handshake (hd->session->tls_session)))
2064         {
2065           switch (err)
2066             {
2067             default:
2068               log_info ("TLS handshake failed: %s <%s>\n",
2069                         gpg_strerror (err), gpg_strsource (err));
2070               xfree (proxy_authstr);
2071               return err;
2072             }
2073         }
2074
2075       hd->session->verify.done = 0;
2076
2077       /* Try the available verify callbacks until one returns success
2078        * or a real error.  Note that NTBTLS does the verification
2079        * during the handshake via   */
2080 #ifdef HTTP_USE_NTBTLS
2081       err = 0; /* Fixme check that the CB has been called.  */
2082 #else
2083       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2084 #endif
2085
2086       if (hd->session->verify_cb
2087           && gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR
2088           && gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
2089         err = hd->session->verify_cb (hd->session->verify_cb_value,
2090                                       hd, hd->session,
2091                                       (hd->flags | hd->session->flags),
2092                                       hd->session->tls_session);
2093
2094       if (tls_callback
2095           && gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR
2096           && gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
2097         err = tls_callback (hd, hd->session, 0);
2098
2099       if (gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR
2100           && gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
2101         err = http_verify_server_credentials (hd->session);
2102
2103       if (err)
2104         {
2105           log_info ("TLS connection authentication failed: %s <%s>\n",
2106                     gpg_strerror (err), gpg_strsource (err));
2107           xfree (proxy_authstr);
2108           return err;
2109         }
2110
2111     }
2112 #elif HTTP_USE_GNUTLS
2113   if (hd->uri->use_tls)
2114     {
2115       int rc;
2116
2117       my_socket_ref (hd->sock);
2118       gnutls_transport_set_ptr (hd->session->tls_session, hd->sock);
2119       gnutls_transport_set_pull_function (hd->session->tls_session,
2120                                           my_gnutls_read);
2121       gnutls_transport_set_push_function (hd->session->tls_session,
2122                                           my_gnutls_write);
2123
2124     handshake_again:
2125       do
2126         {
2127           rc = gnutls_handshake (hd->session->tls_session);
2128         }
2129       while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
2130       if (rc < 0)
2131         {
2132           if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED
2133               || rc == GNUTLS_E_FATAL_ALERT_RECEIVED)
2134             {
2135               gnutls_alert_description_t alertno;
2136               const char *alertstr;
2137
2138               alertno = gnutls_alert_get (hd->session->tls_session);
2139               alertstr = gnutls_alert_get_name (alertno);
2140               log_info ("TLS handshake %s: %s (alert %d)\n",
2141                         rc == GNUTLS_E_WARNING_ALERT_RECEIVED
2142                         ? "warning" : "failed",
2143                         alertstr, (int)alertno);
2144               if (alertno == GNUTLS_A_UNRECOGNIZED_NAME && server)
2145                 log_info ("  (sent server name '%s')\n", server);
2146
2147               if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED)
2148                 goto handshake_again;
2149             }
2150           else
2151             log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
2152           xfree (proxy_authstr);
2153           return gpg_err_make (default_errsource, GPG_ERR_NETWORK);
2154         }
2155
2156       hd->session->verify.done = 0;
2157       if (tls_callback)
2158         err = tls_callback (hd, hd->session, 0);
2159       else
2160         err = http_verify_server_credentials (hd->session);
2161       if (err)
2162         {
2163           log_info ("TLS connection authentication failed: %s\n",
2164                     gpg_strerror (err));
2165           xfree (proxy_authstr);
2166           return err;
2167         }
2168     }
2169 #endif /*HTTP_USE_GNUTLS*/
2170
2171   if (auth || hd->uri->auth)
2172     {
2173       char *myauth;
2174
2175       if (auth)
2176         {
2177           myauth = xtrystrdup (auth);
2178           if (!myauth)
2179             {
2180               xfree (proxy_authstr);
2181               return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2182             }
2183           remove_escapes (myauth);
2184         }
2185       else
2186         {
2187           remove_escapes (hd->uri->auth);
2188           myauth = hd->uri->auth;
2189         }
2190
2191       authstr = make_header_line ("Authorization: Basic ", "\r\n",
2192                                   myauth, strlen (myauth));
2193       if (auth)
2194         xfree (myauth);
2195
2196       if (!authstr)
2197         {
2198           xfree (proxy_authstr);
2199           return gpg_err_make (default_errsource,
2200                                gpg_err_code_from_syserror ());
2201         }
2202     }
2203
2204   p = build_rel_path (hd->uri);
2205   if (!p)
2206     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2207
2208   if (http_proxy && *http_proxy)
2209     {
2210       request = es_bsprintf
2211         ("%s %s://%s:%hu%s%s HTTP/1.0\r\n%s%s",
2212          hd->req_type == HTTP_REQ_GET ? "GET" :
2213          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
2214          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
2215          hd->uri->use_tls? "https" : "http",
2216          httphost? httphost : server,
2217          port, *p == '/' ? "" : "/", p,
2218          authstr ? authstr : "",
2219          proxy_authstr ? proxy_authstr : "");
2220     }
2221   else
2222     {
2223       char portstr[35];
2224
2225       if (port == (hd->uri->use_tls? 443 : 80))
2226         *portstr = 0;
2227       else
2228         snprintf (portstr, sizeof portstr, ":%u", port);
2229
2230       request = es_bsprintf
2231         ("%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
2232          hd->req_type == HTTP_REQ_GET ? "GET" :
2233          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
2234          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
2235          *p == '/' ? "" : "/", p,
2236          httphost? httphost : server,
2237          portstr,
2238          authstr? authstr:"");
2239     }
2240   xfree (p);
2241   if (!request)
2242     {
2243       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2244       xfree (authstr);
2245       xfree (proxy_authstr);
2246       return err;
2247     }
2248
2249   if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
2250     log_debug_string (request, "http.c:request:");
2251
2252   /* First setup estream so that we can write even the first line
2253      using estream.  This is also required for the sake of gnutls. */
2254   {
2255     cookie_t cookie;
2256
2257     cookie = xtrycalloc (1, sizeof *cookie);
2258     if (!cookie)
2259       {
2260         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2261         goto leave;
2262       }
2263     cookie->sock = my_socket_ref (hd->sock);
2264     hd->write_cookie = cookie;
2265     cookie->use_tls = hd->uri->use_tls;
2266     cookie->session = http_session_ref (hd->session);
2267
2268     hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
2269     if (!hd->fp_write)
2270       {
2271         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2272         my_socket_unref (cookie->sock, NULL, NULL);
2273         xfree (cookie);
2274         hd->write_cookie = NULL;
2275       }
2276     else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
2277       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2278     else
2279       err = 0;
2280
2281   if (!err)
2282     {
2283       for (;headers; headers=headers->next)
2284         {
2285           if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
2286             log_debug_string (headers->d, "http.c:request-header:");
2287           if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write))
2288               || (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write)))
2289             {
2290               err = gpg_err_make (default_errsource,
2291                                   gpg_err_code_from_syserror ());
2292               break;
2293             }
2294         }
2295     }
2296   }
2297
2298  leave:
2299   es_free (request);
2300   xfree (authstr);
2301   xfree (proxy_authstr);
2302
2303   return err;
2304 }
2305
2306
2307 /*
2308  * Build the relative path from the parsed URI.  Minimal
2309  * implementation.  May return NULL in case of memory failure; errno
2310  * is then set accordingly.
2311  */
2312 static char *
2313 build_rel_path (parsed_uri_t uri)
2314 {
2315   uri_tuple_t r;
2316   char *rel_path, *p;
2317   int n;
2318
2319   /* Count the needed space. */
2320   n = insert_escapes (NULL, uri->path, "%;?&");
2321   /* TODO: build params. */
2322   for (r = uri->query; r; r = r->next)
2323     {
2324       n++; /* '?'/'&' */
2325       n += insert_escapes (NULL, r->name, "%;?&=");
2326       if (!r->no_value)
2327         {
2328           n++; /* '=' */
2329           n += insert_escapes (NULL, r->value, "%;?&=");
2330         }
2331     }
2332   n++;
2333
2334   /* Now allocate and copy. */
2335   p = rel_path = xtrymalloc (n);
2336   if (!p)
2337     return NULL;
2338   n = insert_escapes (p, uri->path, "%;?&");
2339   p += n;
2340   /* TODO: add params. */
2341   for (r = uri->query; r; r = r->next)
2342     {
2343       *p++ = r == uri->query ? '?' : '&';
2344       n = insert_escapes (p, r->name, "%;?&=");
2345       p += n;
2346       if (!r->no_value)
2347         {
2348           *p++ = '=';
2349           /* TODO: Use valuelen. */
2350           n = insert_escapes (p, r->value, "%;?&=");
2351           p += n;
2352         }
2353     }
2354   *p = 0;
2355   return rel_path;
2356 }
2357
2358
2359 /* Transform a header name into a standard capitalized format; e.g.
2360    "Content-Type".  Conversion stops at the colon.  As usual we don't
2361    use the localized versions of ctype.h. */
2362 static void
2363 capitalize_header_name (char *name)
2364 {
2365   int first = 1;
2366
2367   for (; *name && *name != ':'; name++)
2368     {
2369       if (*name == '-')
2370         first = 1;
2371       else if (first)
2372         {
2373           if (*name >= 'a' && *name <= 'z')
2374             *name = *name - 'a' + 'A';
2375           first = 0;
2376         }
2377       else if (*name >= 'A' && *name <= 'Z')
2378         *name = *name - 'A' + 'a';
2379     }
2380 }
2381
2382
2383 /* Store an HTTP header line in LINE away.  Line continuation is
2384    supported as well as merging of headers with the same name. This
2385    function may modify LINE. */
2386 static gpg_err_code_t
2387 store_header (http_t hd, char *line)
2388 {
2389   size_t n;
2390   char *p, *value;
2391   header_t h;
2392
2393   n = strlen (line);
2394   if (n && line[n-1] == '\n')
2395     {
2396       line[--n] = 0;
2397       if (n && line[n-1] == '\r')
2398         line[--n] = 0;
2399     }
2400   if (!n)  /* we are never called to hit this. */
2401     return GPG_ERR_BUG;
2402   if (*line == ' ' || *line == '\t')
2403     {
2404       /* Continuation. This won't happen too often as it is not
2405          recommended.  We use a straightforward implementation. */
2406       if (!hd->headers)
2407         return GPG_ERR_PROTOCOL_VIOLATION;
2408       n += strlen (hd->headers->value);
2409       p = xtrymalloc (n+1);
2410       if (!p)
2411         return gpg_err_code_from_syserror ();
2412       strcpy (stpcpy (p, hd->headers->value), line);
2413       xfree (hd->headers->value);
2414       hd->headers->value = p;
2415       return 0;
2416     }
2417
2418   capitalize_header_name (line);
2419   p = strchr (line, ':');
2420   if (!p)
2421     return GPG_ERR_PROTOCOL_VIOLATION;
2422   *p++ = 0;
2423   while (*p == ' ' || *p == '\t')
2424     p++;
2425   value = p;
2426
2427   for (h=hd->headers; h; h = h->next)
2428     if ( !strcmp (h->name, line) )
2429       break;
2430   if (h)
2431     {
2432       /* We have already seen a line with that name.  Thus we assume
2433        * it is a comma separated list and merge them.  */
2434       p = strconcat (h->value, ",", value, NULL);
2435       if (!p)
2436         return gpg_err_code_from_syserror ();
2437       xfree (h->value);
2438       h->value = p;
2439       return 0;
2440     }
2441
2442   /* Append a new header. */
2443   h = xtrymalloc (sizeof *h + strlen (line));
2444   if (!h)
2445     return gpg_err_code_from_syserror ();
2446   strcpy (h->name, line);
2447   h->value = xtrymalloc (strlen (value)+1);
2448   if (!h->value)
2449     {
2450       xfree (h);
2451       return gpg_err_code_from_syserror ();
2452     }
2453   strcpy (h->value, value);
2454   h->next = hd->headers;
2455   hd->headers = h;
2456
2457   return 0;
2458 }
2459
2460
2461 /* Return the header NAME from the last response.  The returned value
2462    is valid as along as HD has not been closed and no other request
2463    has been send. If the header was not found, NULL is returned.  NAME
2464    must be canonicalized, that is the first letter of each dash
2465    delimited part must be uppercase and all other letters lowercase.  */
2466 const char *
2467 http_get_header (http_t hd, const char *name)
2468 {
2469   header_t h;
2470
2471   for (h=hd->headers; h; h = h->next)
2472     if ( !strcmp (h->name, name) )
2473       return h->value;
2474   return NULL;
2475 }
2476
2477
2478 /* Return a newly allocated and NULL terminated array with pointers to
2479    header names.  The array must be released with xfree() and its
2480    content is only values as long as no other request has been
2481    send.  */
2482 const char **
2483 http_get_header_names (http_t hd)
2484 {
2485   const char **array;
2486   size_t n;
2487   header_t h;
2488
2489   for (n=0, h = hd->headers; h; h = h->next)
2490     n++;
2491   array = xtrycalloc (n+1, sizeof *array);
2492   if (array)
2493     {
2494       for (n=0, h = hd->headers; h; h = h->next)
2495         array[n++] = h->name;
2496     }
2497
2498   return array;
2499 }
2500
2501
2502 /*
2503  * Parse the response from a server.
2504  * Returns: Errorcode and sets some files in the handle
2505  */
2506 static gpg_err_code_t
2507 parse_response (http_t hd)
2508 {
2509   char *line, *p, *p2;
2510   size_t maxlen, len;
2511   cookie_t cookie = hd->read_cookie;
2512   const char *s;
2513
2514   /* Delete old header lines.  */
2515   while (hd->headers)
2516     {
2517       header_t tmp = hd->headers->next;
2518       xfree (hd->headers->value);
2519       xfree (hd->headers);
2520       hd->headers = tmp;
2521     }
2522
2523   /* Wait for the status line. */
2524   do
2525     {
2526       maxlen = MAX_LINELEN;
2527       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2528       line = hd->buffer;
2529       if (!line)
2530         return gpg_err_code_from_syserror (); /* Out of core. */
2531       if (!maxlen)
2532         return GPG_ERR_TRUNCATED; /* Line has been truncated. */
2533       if (!len)
2534         return GPG_ERR_EOF;
2535
2536       if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
2537         log_debug_string (line, "http.c:response:\n");
2538     }
2539   while (!*line);
2540
2541   if ((p = strchr (line, '/')))
2542     *p++ = 0;
2543   if (!p || strcmp (line, "HTTP"))
2544     return 0; /* Assume http 0.9. */
2545
2546   if ((p2 = strpbrk (p, " \t")))
2547     {
2548       *p2++ = 0;
2549       p2 += strspn (p2, " \t");
2550     }
2551   if (!p2)
2552     return 0; /* Also assume http 0.9. */
2553   p = p2;
2554   /* TODO: Add HTTP version number check. */
2555   if ((p2 = strpbrk (p, " \t")))
2556     *p2++ = 0;
2557   if (!isdigit ((unsigned int)p[0]) || !isdigit ((unsigned int)p[1])
2558       || !isdigit ((unsigned int)p[2]) || p[3])
2559     {
2560       /* Malformed HTTP status code - assume http 0.9. */
2561       hd->is_http_0_9 = 1;
2562       hd->status_code = 200;
2563       return 0;
2564     }
2565   hd->status_code = atoi (p);
2566
2567   /* Skip all the header lines and wait for the empty line. */
2568   do
2569     {
2570       maxlen = MAX_LINELEN;
2571       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2572       line = hd->buffer;
2573       if (!line)
2574         return gpg_err_code_from_syserror (); /* Out of core. */
2575       /* Note, that we can silently ignore truncated lines. */
2576       if (!len)
2577         return GPG_ERR_EOF;
2578       /* Trim line endings of empty lines. */
2579       if ((*line == '\r' && line[1] == '\n') || *line == '\n')
2580         *line = 0;
2581       if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
2582         log_info ("http.c:RESP: '%.*s'\n",
2583                   (int)strlen(line)-(*line&&line[1]?2:0),line);
2584       if (*line)
2585         {
2586           gpg_err_code_t ec = store_header (hd, line);
2587           if (ec)
2588             return ec;
2589         }
2590     }
2591   while (len && *line);
2592
2593   cookie->content_length_valid = 0;
2594   if (!(hd->flags & HTTP_FLAG_IGNORE_CL))
2595     {
2596       s = http_get_header (hd, "Content-Length");
2597       if (s)
2598         {
2599           cookie->content_length_valid = 1;
2600           cookie->content_length = string_to_u64 (s);
2601         }
2602     }
2603
2604   return 0;
2605 }
2606
2607 #if 0
2608 static int
2609 start_server ()
2610 {
2611   struct sockaddr_in mya;
2612   struct sockaddr_in peer;
2613   int fd, client;
2614   fd_set rfds;
2615   int addrlen;
2616   int i;
2617
2618   if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
2619     {
2620       log_error ("socket() failed: %s\n", strerror (errno));
2621       return -1;
2622     }
2623   i = 1;
2624   if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (byte *) & i, sizeof (i)))
2625     log_info ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno));
2626
2627   mya.sin_family = AF_INET;
2628   memset (&mya.sin_addr, 0, sizeof (mya.sin_addr));
2629   mya.sin_port = htons (11371);
2630
2631   if (bind (fd, (struct sockaddr *) &mya, sizeof (mya)))
2632     {
2633       log_error ("bind to port 11371 failed: %s\n", strerror (errno));
2634       sock_close (fd);
2635       return -1;
2636     }
2637
2638   if (listen (fd, 5))
2639     {
2640       log_error ("listen failed: %s\n", strerror (errno));
2641       sock_close (fd);
2642       return -1;
2643     }
2644
2645   for (;;)
2646     {
2647       FD_ZERO (&rfds);
2648       FD_SET (fd, &rfds);
2649
2650       if (my_select (fd + 1, &rfds, NULL, NULL, NULL) <= 0)
2651         continue;               /* ignore any errors */
2652
2653       if (!FD_ISSET (fd, &rfds))
2654         continue;
2655
2656       addrlen = sizeof peer;
2657       client = my_accept (fd, (struct sockaddr *) &peer, &addrlen);
2658       if (client == -1)
2659         continue;               /* oops */
2660
2661       log_info ("connect from %s\n", inet_ntoa (peer.sin_addr));
2662
2663       fflush (stdout);
2664       fflush (stderr);
2665       if (!fork ())
2666         {
2667           int c;
2668           FILE *fp;
2669
2670           fp = fdopen (client, "r");
2671           while ((c = getc (fp)) != EOF)
2672             putchar (c);
2673           fclose (fp);
2674           exit (0);
2675         }
2676       sock_close (client);
2677     }
2678
2679
2680   return 0;
2681 }
2682 #endif
2683
2684
2685
2686 /* Return true if SOCKS shall be used.  This is the case if tor_mode
2687  * is enabled and the desired address is not the loopback address.
2688  * This function is basically a copy of the same internal function in
2689  * Libassuan.  */
2690 static int
2691 use_socks (struct sockaddr_storage *addr)
2692 {
2693   int mode;
2694
2695   if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
2696     return 0;  /* Not in Tor mode.  */
2697   else if (addr->ss_family == AF_INET6)
2698     {
2699       struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr;
2700       const unsigned char *s;
2701       int i;
2702
2703       s = (unsigned char *)&addr_in6->sin6_addr.s6_addr;
2704       if (s[15] != 1)
2705         return 1;   /* Last octet is not 1 - not the loopback address.  */
2706       for (i=0; i < 15; i++, s++)
2707         if (*s)
2708           return 1; /* Non-zero octet found - not the loopback address.  */
2709
2710       return 0; /* This is the loopback address.  */
2711     }
2712   else if (addr->ss_family == AF_INET)
2713     {
2714       struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
2715
2716       if (*(unsigned char*)&addr_in->sin_addr.s_addr == 127)
2717         return 0; /* Loopback (127.0.0.0/8) */
2718
2719       return 1;
2720     }
2721   else
2722     return 0;
2723 }
2724
2725
2726 /* Wrapper around assuan_sock_new which takes the domain from an
2727  * address parameter.  */
2728 static assuan_fd_t
2729 my_sock_new_for_addr (struct sockaddr_storage *addr, int type, int proto)
2730 {
2731   int domain;
2732
2733   if (use_socks (addr))
2734     {
2735       /* Libassaun always uses 127.0.0.1 to connect to the socks
2736        * server (i.e. the Tor daemon).  */
2737       domain = AF_INET;
2738     }
2739   else
2740     domain = addr->ss_family;
2741
2742   return assuan_sock_new (domain, type, proto);
2743 }
2744
2745
2746 /* Call WSAGetLastError and map it to a libgpg-error.  */
2747 #ifdef HAVE_W32_SYSTEM
2748 static gpg_error_t
2749 my_wsagetlasterror (void)
2750 {
2751   int wsaerr;
2752   gpg_err_code_t ec;
2753
2754   wsaerr = WSAGetLastError ();
2755   switch (wsaerr)
2756     {
2757     case WSAENOTSOCK:        ec = GPG_ERR_EINVAL;       break;
2758     case WSAEWOULDBLOCK:     ec = GPG_ERR_EAGAIN;       break;
2759     case ERROR_BROKEN_PIPE:  ec = GPG_ERR_EPIPE;        break;
2760     case WSANOTINITIALISED:  ec = GPG_ERR_ENOSYS;       break;
2761     case WSAENOBUFS:         ec = GPG_ERR_ENOBUFS;      break;
2762     case WSAEMSGSIZE:        ec = GPG_ERR_EMSGSIZE;     break;
2763     case WSAECONNREFUSED:    ec = GPG_ERR_ECONNREFUSED; break;
2764     case WSAEISCONN:         ec = GPG_ERR_EISCONN;      break;
2765     case WSAEALREADY:        ec = GPG_ERR_EALREADY;     break;
2766     case WSAETIMEDOUT:       ec = GPG_ERR_ETIMEDOUT;    break;
2767     default:                 ec = GPG_ERR_EIO;          break;
2768     }
2769
2770   return gpg_err_make (default_errsource, ec);
2771 }
2772 #endif /*HAVE_W32_SYSTEM*/
2773
2774
2775 /* Connect SOCK and return GPG_ERR_ETIMEOUT if a connection could not
2776  * be established within TIMEOUT milliseconds.  0 indicates the
2777  * system's default timeout.  The other args are the usual connect
2778  * args.  On success 0 is returned, on timeout GPG_ERR_ETIMEDOUT, and
2779  * another error code for other errors.  On timeout the caller needs
2780  * to close the socket as soon as possible to stop an ongoing
2781  * handshake.
2782  *
2783  * This implementation is for well-behaving systems; see Stevens,
2784  * Network Programming, 2nd edition, Vol 1, 15.4.  */
2785 static gpg_error_t
2786 connect_with_timeout (assuan_fd_t sock,
2787                       struct sockaddr *addr, int addrlen,
2788                       unsigned int timeout)
2789 {
2790   gpg_error_t err;
2791   int syserr;
2792   socklen_t slen;
2793   fd_set rset, wset;
2794   struct timeval tval;
2795   int n;
2796
2797 #ifndef HAVE_W32_SYSTEM
2798   int oflags;
2799 # define RESTORE_BLOCKING()  do {  \
2800     fcntl (sock, F_SETFL, oflags); \
2801   } while (0)
2802 #else /*HAVE_W32_SYSTEM*/
2803 # define RESTORE_BLOCKING()  do {                       \
2804     unsigned long along = 0;                            \
2805     ioctlsocket (FD2INT (sock), FIONBIO, &along);       \
2806   } while (0)
2807 #endif /*HAVE_W32_SYSTEM*/
2808
2809
2810   if (!timeout)
2811     {
2812       /* Shortcut.  */
2813       if (assuan_sock_connect (sock, addr, addrlen))
2814         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2815       else
2816         err = 0;
2817       return err;
2818     }
2819
2820   /* Switch the socket into non-blocking mode.  */
2821 #ifdef HAVE_W32_SYSTEM
2822   {
2823     unsigned long along = 1;
2824     if (ioctlsocket (FD2INT (sock), FIONBIO, &along))
2825       return my_wsagetlasterror ();
2826   }
2827 #else
2828   oflags = fcntl (sock, F_GETFL, 0);
2829   if (fcntl (sock, F_SETFL, oflags | O_NONBLOCK))
2830     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2831 #endif
2832
2833   /* Do the connect.  */
2834   if (!assuan_sock_connect (sock, addr, addrlen))
2835     {
2836       /* Immediate connect.  Restore flags. */
2837       RESTORE_BLOCKING ();
2838       return 0; /* Success.  */
2839     }
2840   err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2841   if (gpg_err_code (err) != GPG_ERR_EINPROGRESS
2842 #ifdef HAVE_W32_SYSTEM
2843       && gpg_err_code (err) != GPG_ERR_EAGAIN
2844 #endif
2845       )
2846     {
2847       RESTORE_BLOCKING ();
2848       return err;
2849     }
2850
2851   FD_ZERO (&rset);
2852   FD_SET (FD2INT (sock), &rset);
2853   wset = rset;
2854   tval.tv_sec = timeout / 1000;
2855   tval.tv_usec = (timeout % 1000) * 1000;
2856
2857   n = my_select (FD2INT(sock)+1, &rset, &wset, NULL, &tval);
2858   if (n < 0)
2859     {
2860       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2861       RESTORE_BLOCKING ();
2862       return err;
2863     }
2864   if (!n)
2865     {
2866       /* Timeout: We do not restore the socket flags on timeout
2867        * because the caller is expected to close the socket.  */
2868       return gpg_err_make (default_errsource, GPG_ERR_ETIMEDOUT);
2869     }
2870   if (!FD_ISSET (sock, &rset) && !FD_ISSET (sock, &wset))
2871     {
2872       /* select misbehaved.  */
2873       return gpg_err_make (default_errsource, GPG_ERR_SYSTEM_BUG);
2874     }
2875
2876   slen = sizeof (syserr);
2877   if (getsockopt (FD2INT(sock), SOL_SOCKET, SO_ERROR,
2878                   (void*)&syserr, &slen) < 0)
2879     {
2880       /* Assume that this is Solaris which returns the error in ERRNO.  */
2881       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2882     }
2883   else if (syserr)
2884     err = gpg_err_make (default_errsource, gpg_err_code_from_errno (syserr));
2885   else
2886     err = 0; /* Connected.  */
2887
2888   RESTORE_BLOCKING ();
2889
2890   return err;
2891
2892 #undef RESTORE_BLOCKING
2893 }
2894
2895
2896 /* Actually connect to a server.  On success 0 is returned and the
2897  * file descriptor for the socket is stored at R_SOCK; on error an
2898  * error code is returned and ASSUAN_INVALID_FD is stored at R_SOCK.
2899  * TIMEOUT is the connect timeout in milliseconds.  Note that the
2900  * function tries to connect to all known addresses and the timeout is
2901  * for each one. */
2902 static gpg_error_t
2903 connect_server (ctrl_t ctrl, const char *server, unsigned short port,
2904                 unsigned int flags, const char *srvtag, unsigned int timeout,
2905                 assuan_fd_t *r_sock)
2906 {
2907   gpg_error_t err;
2908   assuan_fd_t sock = ASSUAN_INVALID_FD;
2909   unsigned int srvcount = 0;
2910   int hostfound = 0;
2911   int anyhostaddr = 0;
2912   int srv, connected, v4_valid, v6_valid;
2913   gpg_error_t last_err = 0;
2914   struct srventry *serverlist = NULL;
2915
2916   *r_sock = ASSUAN_INVALID_FD;
2917
2918 #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
2919   init_sockets ();
2920 #endif /*Windows*/
2921
2922   check_inet_support (&v4_valid, &v6_valid);
2923
2924   /* Onion addresses require special treatment.  */
2925   if (is_onion_address (server))
2926     {
2927 #ifdef ASSUAN_SOCK_TOR
2928
2929       if (opt_debug)
2930         log_debug ("http.c:connect_server:onion: name='%s' port=%hu\n",
2931                    server, port);
2932       sock = assuan_sock_connect_byname (server, port, 0, NULL,
2933                                          ASSUAN_SOCK_TOR);
2934       if (sock == ASSUAN_INVALID_FD)
2935         {
2936           err = gpg_err_make (default_errsource,
2937                               (errno == EHOSTUNREACH)? GPG_ERR_UNKNOWN_HOST
2938                               : gpg_err_code_from_syserror ());
2939           log_error ("can't connect to '%s': %s\n", server, gpg_strerror (err));
2940           return err;
2941         }
2942
2943       notify_netactivity ();
2944       *r_sock = sock;
2945       return 0;
2946
2947 #else /*!ASSUAN_SOCK_TOR*/
2948
2949       err = gpg_err_make (default_errsource, GPG_ERR_ENETUNREACH);
2950       return ASSUAN_INVALID_FD;
2951
2952 #endif /*!HASSUAN_SOCK_TOR*/
2953     }
2954
2955   /* Do the SRV thing */
2956   if (srvtag)
2957     {
2958       err = get_dns_srv (ctrl, server, srvtag, NULL, &serverlist, &srvcount);
2959       if (err)
2960         log_info ("getting '%s' SRV for '%s' failed: %s\n",
2961                   srvtag, server, gpg_strerror (err));
2962       /* Note that on error SRVCOUNT is zero.  */
2963       err = 0;
2964     }
2965
2966   if (!serverlist)
2967     {
2968       /* Either we're not using SRV, or the SRV lookup failed.  Make
2969          up a fake SRV record. */
2970       serverlist = xtrycalloc (1, sizeof *serverlist);
2971       if (!serverlist)
2972         return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2973
2974       serverlist->port = port;
2975       strncpy (serverlist->target, server, DIMof (struct srventry, target));
2976       serverlist->target[DIMof (struct srventry, target)-1] = '\0';
2977       srvcount = 1;
2978     }
2979
2980   connected = 0;
2981   for (srv=0; srv < srvcount && !connected; srv++)
2982     {
2983       dns_addrinfo_t aibuf, ai;
2984
2985       if (opt_debug)
2986         log_debug ("http.c:connect_server: trying name='%s' port=%hu\n",
2987                    serverlist[srv].target, port);
2988       err = resolve_dns_name (ctrl,
2989                               serverlist[srv].target, port, 0, SOCK_STREAM,
2990                               &aibuf, NULL);
2991       if (err)
2992         {
2993           log_info ("resolving '%s' failed: %s\n",
2994                     serverlist[srv].target, gpg_strerror (err));
2995           last_err = err;
2996           continue; /* Not found - try next one. */
2997         }
2998       hostfound = 1;
2999
3000       for (ai = aibuf; ai && !connected; ai = ai->next)
3001         {
3002           if (ai->family == AF_INET
3003               && ((flags & HTTP_FLAG_IGNORE_IPv4) || !v4_valid))
3004             continue;
3005           if (ai->family == AF_INET6
3006               && ((flags & HTTP_FLAG_IGNORE_IPv6) || !v6_valid))
3007             continue;
3008
3009           if (sock != ASSUAN_INVALID_FD)
3010             assuan_sock_close (sock);
3011           sock = my_sock_new_for_addr (ai->addr, ai->socktype, ai->protocol);
3012           if (sock == ASSUAN_INVALID_FD)
3013             {
3014               err = gpg_err_make (default_errsource,
3015                                   gpg_err_code_from_syserror ());
3016               log_error ("error creating socket: %s\n", gpg_strerror (err));
3017               free_dns_addrinfo (aibuf);
3018               xfree (serverlist);
3019               return err;
3020             }
3021
3022           anyhostaddr = 1;
3023           err = connect_with_timeout (sock, (struct sockaddr *)ai->addr,
3024                                       ai->addrlen, timeout);
3025           if (err)
3026             {
3027               last_err = err;
3028             }
3029           else
3030             {
3031               connected = 1;
3032               notify_netactivity ();
3033             }
3034         }
3035       free_dns_addrinfo (aibuf);
3036     }
3037
3038   xfree (serverlist);
3039
3040   if (!connected)
3041     {
3042       if (!hostfound)
3043         log_error ("can't connect to '%s': %s\n",
3044                    server, "host not found");
3045       else if (!anyhostaddr)
3046         log_error ("can't connect to '%s': %s\n",
3047                    server, "no IP address for host");
3048       else
3049         {
3050 #ifdef HAVE_W32_SYSTEM
3051         log_error ("can't connect to '%s': ec=%d\n",
3052                    server, (int)WSAGetLastError());
3053 #else
3054         log_error ("can't connect to '%s': %s\n",
3055                    server, gpg_strerror (last_err));
3056 #endif
3057         }
3058       err = last_err? last_err : gpg_err_make (default_errsource,
3059                                                GPG_ERR_UNKNOWN_HOST);
3060       if (sock != ASSUAN_INVALID_FD)
3061         assuan_sock_close (sock);
3062       return err;
3063     }
3064
3065   *r_sock = sock;
3066   return 0;
3067 }
3068
3069
3070 /* Helper to read from a socket.  This handles npth things and
3071  * EINTR.  */
3072 static gpgrt_ssize_t
3073 read_server (assuan_fd_t sock, void *buffer, size_t size)
3074 {
3075   int nread;
3076
3077   do
3078     {
3079 #ifdef HAVE_W32_SYSTEM
3080       /* Under Windows we need to use recv for a socket.  */
3081 # if defined(USE_NPTH)
3082       npth_unprotect ();
3083 # endif
3084       nread = recv (FD2INT (sock), buffer, size, 0);
3085 # if defined(USE_NPTH)
3086       npth_protect ();
3087 # endif
3088
3089 #else /*!HAVE_W32_SYSTEM*/
3090
3091 # ifdef USE_NPTH
3092       nread = npth_read (sock, buffer, size);
3093 # else
3094       nread = read (sock, buffer, size);
3095 # endif
3096
3097 #endif /*!HAVE_W32_SYSTEM*/
3098     }
3099   while (nread == -1 && errno == EINTR);
3100
3101   return nread;
3102 }
3103
3104
3105 static gpg_error_t
3106 write_server (assuan_fd_t sock, const char *data, size_t length)
3107 {
3108   int nleft;
3109   int nwritten;
3110
3111   nleft = length;
3112   while (nleft > 0)
3113     {
3114 #if defined(HAVE_W32_SYSTEM)
3115 # if defined(USE_NPTH)
3116       npth_unprotect ();
3117 # endif
3118       nwritten = send (FD2INT (sock), data, nleft, 0);
3119 # if defined(USE_NPTH)
3120       npth_protect ();
3121 # endif
3122       if ( nwritten == SOCKET_ERROR )
3123         {
3124           log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
3125           return gpg_error (GPG_ERR_NETWORK);
3126         }
3127 #else /*!HAVE_W32_SYSTEM*/
3128 # ifdef USE_NPTH
3129       nwritten = npth_write (sock, data, nleft);
3130 # else
3131       nwritten = write (sock, data, nleft);
3132 # endif
3133       if (nwritten == -1)
3134         {
3135           if (errno == EINTR)
3136             continue;
3137           if (errno == EAGAIN)
3138             {
3139               struct timeval tv;
3140
3141               tv.tv_sec = 0;
3142               tv.tv_usec = 50000;
3143               my_select (0, NULL, NULL, NULL, &tv);
3144               continue;
3145             }
3146           log_info ("network write failed: %s\n", strerror (errno));
3147           return gpg_error_from_syserror ();
3148         }
3149 #endif /*!HAVE_W32_SYSTEM*/
3150       nleft -= nwritten;
3151       data += nwritten;
3152     }
3153
3154   return 0;
3155 }
3156
3157
3158 \f
3159 /* Read handler for estream.  */
3160 static gpgrt_ssize_t
3161 cookie_read (void *cookie, void *buffer, size_t size)
3162 {
3163   cookie_t c = cookie;
3164   int nread;
3165
3166   if (c->content_length_valid)
3167     {
3168       if (!c->content_length)
3169         return 0; /* EOF */
3170       if (c->content_length < size)
3171         size = c->content_length;
3172     }
3173
3174 #if HTTP_USE_NTBTLS
3175   if (c->use_tls && c->session && c->session->tls_session)
3176     {
3177       estream_t in, out;
3178
3179       ntbtls_get_stream (c->session->tls_session, &in, &out);
3180       nread = es_fread (buffer, 1, size, in);
3181       if (opt_debug)
3182         log_debug ("TLS network read: %d/%zu\n", nread, size);
3183     }
3184   else
3185 #elif HTTP_USE_GNUTLS
3186   if (c->use_tls && c->session && c->session->tls_session)
3187     {
3188     again:
3189       nread = gnutls_record_recv (c->session->tls_session, buffer, size);
3190       if (nread < 0)
3191         {
3192           if (nread == GNUTLS_E_INTERRUPTED)
3193             goto again;
3194           if (nread == GNUTLS_E_AGAIN)
3195             {
3196               struct timeval tv;
3197
3198               tv.tv_sec = 0;
3199               tv.tv_usec = 50000;
3200               my_select (0, NULL, NULL, NULL, &tv);
3201               goto again;
3202             }
3203           if (nread == GNUTLS_E_REHANDSHAKE)
3204             goto again; /* A client is allowed to just ignore this request. */
3205           if (nread == GNUTLS_E_PREMATURE_TERMINATION)
3206             {
3207               /* The server terminated the connection.  Close the TLS
3208                  session, and indicate EOF using a short read.  */
3209               close_tls_session (c->session);
3210               return 0;
3211             }
3212           log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
3213           gpg_err_set_errno (EIO);
3214           return -1;
3215         }
3216     }
3217   else
3218 #endif /*HTTP_USE_GNUTLS*/
3219     {
3220       nread = read_server (c->sock->fd, buffer, size);
3221     }
3222
3223   if (c->content_length_valid && nread > 0)
3224     {
3225       if (nread < c->content_length)
3226         c->content_length -= nread;
3227       else
3228         c->content_length = 0;
3229     }
3230
3231   return (gpgrt_ssize_t)nread;
3232 }
3233
3234 /* Write handler for estream.  */
3235 static gpgrt_ssize_t
3236 cookie_write (void *cookie, const void *buffer_arg, size_t size)
3237 {
3238   const char *buffer = buffer_arg;
3239   cookie_t c = cookie;
3240   int nwritten = 0;
3241
3242 #if HTTP_USE_NTBTLS
3243   if (c->use_tls && c->session && c->session->tls_session)
3244     {
3245       estream_t in, out;
3246
3247       ntbtls_get_stream (c->session->tls_session, &in, &out);
3248       if (size == 0)
3249         es_fflush (out);
3250       else
3251         nwritten = es_fwrite (buffer, 1, size, out);
3252       if (opt_debug)
3253         log_debug ("TLS network write: %d/%zu\n", nwritten, size);
3254     }
3255   else
3256 #elif HTTP_USE_GNUTLS
3257   if (c->use_tls && c->session && c->session->tls_session)
3258     {
3259       int nleft = size;
3260       while (nleft > 0)
3261         {
3262           nwritten = gnutls_record_send (c->session->tls_session,
3263                                          buffer, nleft);
3264           if (nwritten <= 0)
3265             {
3266               if (nwritten == GNUTLS_E_INTERRUPTED)
3267                 continue;
3268               if (nwritten == GNUTLS_E_AGAIN)
3269                 {
3270                   struct timeval tv;
3271
3272                   tv.tv_sec = 0;
3273                   tv.tv_usec = 50000;
3274                   my_select (0, NULL, NULL, NULL, &tv);
3275                   continue;
3276                 }
3277               log_info ("TLS network write failed: %s\n",
3278                         gnutls_strerror (nwritten));
3279               gpg_err_set_errno (EIO);
3280               return -1;
3281             }
3282           nleft -= nwritten;
3283           buffer += nwritten;
3284         }
3285     }
3286   else
3287 #endif /*HTTP_USE_GNUTLS*/
3288     {
3289       if ( write_server (c->sock->fd, buffer, size) )
3290         {
3291           gpg_err_set_errno (EIO);
3292           nwritten = -1;
3293         }
3294       else
3295         nwritten = size;
3296     }
3297
3298   return (gpgrt_ssize_t)nwritten;
3299 }
3300
3301
3302 #if defined(HAVE_W32_SYSTEM) && defined(HTTP_USE_NTBTLS)
3303 static gpgrt_ssize_t
3304 simple_cookie_read (void *cookie, void *buffer, size_t size)
3305 {
3306   assuan_fd_t sock = (assuan_fd_t)cookie;
3307   return read_server (sock, buffer, size);
3308 }
3309
3310 static gpgrt_ssize_t
3311 simple_cookie_write (void *cookie, const void *buffer_arg, size_t size)
3312 {
3313   assuan_fd_t sock = (assuan_fd_t)cookie;
3314   const char *buffer = buffer_arg;
3315   int nwritten;
3316
3317   if (write_server (sock, buffer, size))
3318     {
3319       gpg_err_set_errno (EIO);
3320       nwritten = -1;
3321     }
3322   else
3323     nwritten = size;
3324
3325   return (gpgrt_ssize_t)nwritten;
3326 }
3327 #endif /*HAVE_W32_SYSTEM*/
3328
3329
3330 #ifdef HTTP_USE_GNUTLS
3331 /* Wrapper for gnutls_bye used by my_socket_unref.  */
3332 static void
3333 send_gnutls_bye (void *opaque)
3334 {
3335   tls_session_t tls_session = opaque;
3336   int ret;
3337
3338  again:
3339   do
3340     ret = gnutls_bye (tls_session, GNUTLS_SHUT_RDWR);
3341   while (ret == GNUTLS_E_INTERRUPTED);
3342   if (ret == GNUTLS_E_AGAIN)
3343     {
3344       struct timeval tv;
3345
3346       tv.tv_sec = 0;
3347       tv.tv_usec = 50000;
3348       my_select (0, NULL, NULL, NULL, &tv);
3349       goto again;
3350     }
3351 }
3352 #endif /*HTTP_USE_GNUTLS*/
3353
3354 /* Close handler for estream.  */
3355 static int
3356 cookie_close (void *cookie)
3357 {
3358   cookie_t c = cookie;
3359
3360   if (!c)
3361     return 0;
3362
3363 #if HTTP_USE_NTBTLS
3364   if (c->use_tls && c->session && c->session->tls_session)
3365     {
3366       /* FIXME!! Possibly call ntbtls_close_notify for close
3367          of write stream.  */
3368       my_socket_unref (c->sock, NULL, NULL);
3369     }
3370   else
3371 #elif HTTP_USE_GNUTLS
3372   if (c->use_tls && c->session && c->session->tls_session)
3373     my_socket_unref (c->sock, send_gnutls_bye, c->session->tls_session);
3374   else
3375 #endif /*HTTP_USE_GNUTLS*/
3376     if (c->sock)
3377       my_socket_unref (c->sock, NULL, NULL);
3378
3379   if (c->session)
3380     http_session_unref (c->session);
3381   xfree (c);
3382   return 0;
3383 }
3384
3385
3386
3387 \f
3388 /* Verify the credentials of the server.  Returns 0 on success and
3389    store the result in the session object.  */
3390 gpg_error_t
3391 http_verify_server_credentials (http_session_t sess)
3392 {
3393 #if HTTP_USE_GNUTLS
3394   static const char errprefix[] = "TLS verification of peer failed";
3395   int rc;
3396   unsigned int status;
3397   const char *hostname;
3398   const gnutls_datum_t *certlist;
3399   unsigned int certlistlen;
3400   gnutls_x509_crt_t cert;
3401   gpg_error_t err = 0;
3402
3403   sess->verify.done = 1;
3404   sess->verify.status = 0;
3405   sess->verify.rc = GNUTLS_E_CERTIFICATE_ERROR;
3406
3407   if (gnutls_certificate_type_get (sess->tls_session) != GNUTLS_CRT_X509)
3408     {
3409       log_error ("%s: %s\n", errprefix, "not an X.509 certificate");
3410       sess->verify.rc = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
3411       return gpg_error (GPG_ERR_GENERAL);
3412     }
3413
3414   rc = gnutls_certificate_verify_peers2 (sess->tls_session, &status);
3415   if (rc)
3416     {
3417       log_error ("%s: %s\n", errprefix, gnutls_strerror (rc));
3418       if (!err)
3419         err = gpg_error (GPG_ERR_GENERAL);
3420     }
3421   else if (status)
3422     {
3423       log_error ("%s: status=0x%04x\n", errprefix, status);
3424 #if GNUTLS_VERSION_NUMBER >= 0x030104
3425       {
3426         gnutls_datum_t statusdat;
3427
3428         if (!gnutls_certificate_verification_status_print
3429             (status, GNUTLS_CRT_X509, &statusdat, 0))
3430           {
3431             log_info ("%s: %s\n", errprefix, statusdat.data);
3432             gnutls_free (statusdat.data);
3433           }
3434       }
3435 #endif /*gnutls >= 3.1.4*/
3436
3437       sess->verify.status = status;
3438       if (!err)
3439         err = gpg_error (GPG_ERR_GENERAL);
3440     }
3441
3442   hostname = sess->servername;
3443   if (!hostname || !strchr (hostname, '.'))
3444     {
3445       log_error ("%s: %s\n", errprefix, "hostname missing");
3446       if (!err)
3447         err = gpg_error (GPG_ERR_GENERAL);
3448     }
3449
3450   certlist = gnutls_certificate_get_peers (sess->tls_session, &certlistlen);
3451   if (!certlistlen)
3452     {
3453       log_error ("%s: %s\n", errprefix, "server did not send a certificate");
3454       if (!err)
3455         err = gpg_error (GPG_ERR_GENERAL);
3456
3457       /* Need to stop here.  */
3458       if (err)
3459         return err;
3460     }
3461
3462   rc = gnutls_x509_crt_init (&cert);
3463   if (rc < 0)
3464     {
3465       if (!err)
3466         err = gpg_error (GPG_ERR_GENERAL);
3467       if (err)
3468         return err;
3469     }
3470
3471   rc = gnutls_x509_crt_import (cert, &certlist[0], GNUTLS_X509_FMT_DER);
3472   if (rc < 0)
3473     {
3474       log_error ("%s: %s: %s\n", errprefix, "error importing certificate",
3475                  gnutls_strerror (rc));
3476       if (!err)
3477         err = gpg_error (GPG_ERR_GENERAL);
3478     }
3479
3480   if (!gnutls_x509_crt_check_hostname (cert, hostname))
3481     {
3482       log_error ("%s: %s\n", errprefix, "hostname does not match");
3483       if (!err)
3484         err = gpg_error (GPG_ERR_GENERAL);
3485     }
3486
3487   gnutls_x509_crt_deinit (cert);
3488
3489   if (!err)
3490     sess->verify.rc = 0;
3491
3492   if (sess->cert_log_cb)
3493     {
3494       const void *bufarr[10];
3495       size_t buflenarr[10];
3496       size_t n;
3497
3498       for (n = 0; n < certlistlen && n < DIM (bufarr)-1; n++)
3499         {
3500           bufarr[n] = certlist[n].data;
3501           buflenarr[n] = certlist[n].size;
3502         }
3503       bufarr[n] = NULL;
3504       buflenarr[n] = 0;
3505       sess->cert_log_cb (sess, err, hostname, bufarr, buflenarr);
3506     }
3507
3508   return err;
3509 #else /*!HTTP_USE_GNUTLS*/
3510   (void)sess;
3511   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
3512 #endif
3513 }
3514
3515 /* Return the first query variable with the specified key.  If there
3516    is no such variable, return NULL.  */
3517 struct uri_tuple_s *
3518 uri_query_lookup (parsed_uri_t uri, const char *key)
3519 {
3520   struct uri_tuple_s *t;
3521
3522   for (t = uri->query; t; t = t->next)
3523     if (strcmp (t->name, key) == 0)
3524       return t;
3525
3526   return NULL;
3527 }
3528
3529
3530 /* Return true if both URI point to the same host for the purpose of
3531  * redirection check.  A is the original host and B the host given in
3532  * the Location header.  As a temporary workaround a fixed list of
3533  * exceptions is also consulted.  */
3534 static int
3535 same_host_p (parsed_uri_t a, parsed_uri_t b)
3536 {
3537   static struct
3538   {
3539     const char *from;  /* NULL uses the last entry from the table.  */
3540     const char *to;
3541   } allow[] =
3542   {
3543     { "protonmail.com", "api.protonmail.com" },
3544     { NULL,             "api.protonmail.ch"  },
3545     { "protonmail.ch",  "api.protonmail.com" },
3546     { NULL,             "api.protonmail.ch"  },
3547     { "pm.me",          "api.protonmail.ch"  }
3548   };
3549   static const char *subdomains[] =
3550     {
3551       "openpgpkey."
3552     };
3553   int i;
3554   const char *from;
3555
3556   if (!a->host || !b->host)
3557     return 0;
3558
3559   if (!ascii_strcasecmp (a->host, b->host))
3560     return 1;
3561
3562   from = NULL;
3563   for (i=0; i < DIM (allow); i++)
3564     {
3565       if (allow[i].from)
3566         from = allow[i].from;
3567       if (!from)
3568         continue;
3569       if (!ascii_strcasecmp (from, a->host)
3570           && !ascii_strcasecmp (allow[i].to, b->host))
3571         return 1;
3572     }
3573
3574   /* Also consider hosts the same if they differ only in a subdomain;
3575    * in both direction.  This allows to have redirection between the
3576    * WKD advanced and direct lookup methods. */
3577   for (i=0; i < DIM (subdomains); i++)
3578     {
3579       const char *subdom = subdomains[i];
3580       size_t subdomlen = strlen (subdom);
3581
3582       if (!ascii_strncasecmp (a->host, subdom, subdomlen)
3583           && !ascii_strcasecmp (a->host + subdomlen, b->host))
3584         return 1;
3585       if (!ascii_strncasecmp (b->host, subdom, subdomlen)
3586           && !ascii_strcasecmp (b->host + subdomlen, a->host))
3587         return 1;
3588     }
3589
3590   return 0;
3591 }
3592
3593
3594 /* Prepare a new URL for a HTTP redirect.  INFO has flags controlling
3595  * the operation, STATUS_CODE is used for diagnostics, LOCATION is the
3596  * value of the "Location" header, and R_URL reveives the new URL on
3597  * success or NULL or error.  Note that INFO->ORIG_URL is
3598  * required.  */
3599 gpg_error_t
3600 http_prepare_redirect (http_redir_info_t *info, unsigned int status_code,
3601                        const char *location, char **r_url)
3602 {
3603   gpg_error_t err;
3604   parsed_uri_t locuri;
3605   parsed_uri_t origuri;
3606   char *newurl;
3607   char *p;
3608
3609   *r_url = NULL;
3610
3611   if (!info || !info->orig_url)
3612     return gpg_error (GPG_ERR_INV_ARG);
3613
3614   if (!info->silent)
3615     log_info (_("URL '%s' redirected to '%s' (%u)\n"),
3616               info->orig_url, location? location:"[none]", status_code);
3617
3618   if (!info->redirects_left)
3619     {
3620       if (!info->silent)
3621         log_error (_("too many redirections\n"));
3622       return gpg_error (GPG_ERR_NO_DATA);
3623     }
3624   info->redirects_left--;
3625
3626   if (!location || !*location)
3627     return gpg_error (GPG_ERR_NO_DATA);
3628
3629   err = http_parse_uri (&locuri, location, 0);
3630   if (err)
3631     return err;
3632
3633   /* Make sure that an onion address only redirects to another
3634    * onion address, or that a https address only redirects to a
3635    * https address. */
3636   if (info->orig_onion && !locuri->onion)
3637     {
3638       dirmngr_status_printf (info->ctrl, "WARNING",
3639                              "http_redirect %u"
3640                              " redirect from onion to non-onion address"
3641                              " rejected",
3642                              err);
3643       http_release_parsed_uri (locuri);
3644       return gpg_error (GPG_ERR_FORBIDDEN);
3645     }
3646   if (!info->allow_downgrade && info->orig_https && !locuri->use_tls)
3647     {
3648       err = gpg_error (GPG_ERR_FORBIDDEN);
3649       dirmngr_status_printf (info->ctrl, "WARNING",
3650                              "http_redirect %u"
3651                              " redirect '%s' to '%s' rejected",
3652                              err, info->orig_url, location);
3653       http_release_parsed_uri (locuri);
3654       return err;
3655     }
3656
3657   if (info->trust_location)
3658     {
3659       /* We trust the Location - return it verbatim.  */
3660       http_release_parsed_uri (locuri);
3661       newurl = xtrystrdup (location);
3662       if (!newurl)
3663         {
3664           err = gpg_error_from_syserror ();
3665           http_release_parsed_uri (locuri);
3666           return err;
3667         }
3668     }
3669   else if ((err = http_parse_uri (&origuri, info->orig_url, 0)))
3670     {
3671       http_release_parsed_uri (locuri);
3672       return err;
3673     }
3674   else if (same_host_p (origuri, locuri))
3675     {
3676       /* The host is the same or on an exception list and thus we can
3677        * take the location verbatim.  */
3678       http_release_parsed_uri (origuri);
3679       http_release_parsed_uri (locuri);
3680       newurl = xtrystrdup (location);
3681       if (!newurl)
3682         {
3683           err = gpg_error_from_syserror ();
3684           http_release_parsed_uri (locuri);
3685           return err;
3686         }
3687     }
3688   else
3689     {
3690       /* We take only the host and port from the URL given in the
3691        * Location.  This limits the effects of redirection attacks by
3692        * rogue hosts returning an URL to servers in the client's own
3693        * network.  We don't even include the userinfo because they
3694        * should be considered similar to the path and query parts.
3695        */
3696       if (!(locuri->off_path - locuri->off_host))
3697         {
3698           http_release_parsed_uri (origuri);
3699           http_release_parsed_uri (locuri);
3700           return gpg_error (GPG_ERR_BAD_URI);
3701         }
3702       if (!(origuri->off_path - origuri->off_host))
3703         {
3704           http_release_parsed_uri (origuri);
3705           http_release_parsed_uri (locuri);
3706           return gpg_error (GPG_ERR_BAD_URI);
3707         }
3708
3709       newurl = xtrymalloc (strlen (origuri->original)
3710                            + (locuri->off_path - locuri->off_host) + 1);
3711       if (!newurl)
3712         {
3713           err = gpg_error_from_syserror ();
3714           http_release_parsed_uri (origuri);
3715           http_release_parsed_uri (locuri);
3716           return err;
3717         }
3718       /* Build new URL from
3719        *   uriguri:  scheme userinfo ---- ---- path rest
3720        *   locuri:   ------ -------- host port ---- ----
3721        */
3722       p = newurl;
3723       memcpy (p, origuri->original, origuri->off_host);
3724       p += origuri->off_host;
3725       memcpy (p, locuri->original + locuri->off_host,
3726               (locuri->off_path - locuri->off_host));
3727       p += locuri->off_path - locuri->off_host;
3728       strcpy (p, origuri->original + origuri->off_path);
3729
3730       http_release_parsed_uri (origuri);
3731       http_release_parsed_uri (locuri);
3732       if (!info->silent)
3733         log_info (_("redirection changed to '%s'\n"), newurl);
3734       dirmngr_status_printf (info->ctrl, "WARNING",
3735                              "http_redirect_cleanup %u"
3736                              " changed from '%s' to '%s'",
3737                              0, info->orig_url, newurl);
3738     }
3739
3740   *r_url = newurl;
3741   return 0;
3742 }
3743
3744
3745 /* Return string describing the http STATUS.  Returns an empty string
3746  * for an unknown status.  */
3747 const char *
3748 http_status2string (unsigned int status)
3749 {
3750   switch (status)
3751     {
3752     case 500: return "Internal Server Error";
3753     case 501: return "Not Implemented";
3754     case 502: return "Bad Gateway";
3755     case 503: return "Service Unavailable";
3756     case 504: return "Gateway Timeout";
3757     case 505: return "HTTP version Not Supported";
3758     case 506: return "Variant Also Negation";
3759     case 507: return "Insufficient Storage";
3760     case 508: return "Loop Detected";
3761     case 510: return "Not Extended";
3762     case 511: return "Network Authentication Required";
3763     }
3764
3765   return "";
3766 }