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