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