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