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