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