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