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