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