chiark / gitweb /
dirmngr: Strip root zone suffix from libdns cname results.
[gnupg2.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
1173   /* A quick validity check. */
1174   if (strspn (p, VALID_URI_CHARS) != n)
1175     return GPG_ERR_BAD_URI;     /* Invalid characters found. */
1176
1177   if (!only_local_part)
1178     {
1179       /* Find the scheme. */
1180       if (!(p2 = strchr (p, ':')) || p2 == p)
1181         return GPG_ERR_BAD_URI; /* No scheme. */
1182       *p2++ = 0;
1183       for (pp=p; *pp; pp++)
1184        *pp = tolower (*(unsigned char*)pp);
1185       uri->scheme = p;
1186       if (!strcmp (uri->scheme, "http") && !force_tls)
1187         {
1188           uri->port = 80;
1189           uri->is_http = 1;
1190         }
1191       else if (!strcmp (uri->scheme, "hkp") && !force_tls)
1192         {
1193           uri->port = 11371;
1194           uri->is_http = 1;
1195         }
1196 #ifdef USE_TLS
1197       else if (!strcmp (uri->scheme, "https") || !strcmp (uri->scheme,"hkps")
1198                || (force_tls && (!strcmp (uri->scheme, "http")
1199                                  || !strcmp (uri->scheme,"hkp"))))
1200         {
1201           uri->port = 443;
1202           uri->is_http = 1;
1203           uri->use_tls = 1;
1204         }
1205 #endif /*USE_TLS*/
1206       else if (!no_scheme_check)
1207         return GPG_ERR_INV_URI; /* Unsupported scheme */
1208
1209       p = p2;
1210
1211       if (*p == '/' && p[1] == '/' ) /* There seems to be a hostname. */
1212         {
1213           p += 2;
1214           if ((p2 = strchr (p, '/')))
1215             *p2++ = 0;
1216
1217           /* Check for username/password encoding */
1218           if ((p3 = strchr (p, '@')))
1219             {
1220               uri->auth = p;
1221               *p3++ = '\0';
1222               p = p3;
1223             }
1224
1225           for (pp=p; *pp; pp++)
1226             *pp = tolower (*(unsigned char*)pp);
1227
1228           /* Handle an IPv6 literal */
1229           if( *p == '[' && (p3=strchr( p, ']' )) )
1230             {
1231               *p3++ = '\0';
1232               /* worst case, uri->host should have length 0, points to \0 */
1233               uri->host = p + 1;
1234               uri->v6lit = 1;
1235               p = p3;
1236             }
1237           else
1238             uri->host = p;
1239
1240           if ((p3 = strchr (p, ':')))
1241             {
1242               *p3++ = '\0';
1243               uri->port = atoi (p3);
1244             }
1245
1246           if ((n = remove_escapes (uri->host)) < 0)
1247             return GPG_ERR_BAD_URI;
1248           if (n != strlen (uri->host))
1249             return GPG_ERR_BAD_URI;     /* Hostname incudes a Nul. */
1250           p = p2 ? p2 : NULL;
1251         }
1252       else if (uri->is_http)
1253         return GPG_ERR_INV_URI; /* No Leading double slash for HTTP.  */
1254       else
1255         {
1256           uri->opaque = 1;
1257           uri->path = p;
1258           if (is_onion_address (uri->path))
1259             uri->onion = 1;
1260           return 0;
1261         }
1262
1263     } /* End global URI part. */
1264
1265   /* Parse the pathname part if any.  */
1266   if (p && *p)
1267     {
1268       /* TODO: Here we have to check params. */
1269
1270       /* Do we have a query part? */
1271       if ((p2 = strchr (p, '?')))
1272         *p2++ = 0;
1273
1274       uri->path = p;
1275       if ((n = remove_escapes (p)) < 0)
1276         return GPG_ERR_BAD_URI;
1277       if (n != strlen (p))
1278         return GPG_ERR_BAD_URI; /* Path includes a Nul. */
1279       p = p2 ? p2 : NULL;
1280
1281       /* Parse a query string if any.  */
1282       if (p && *p)
1283         {
1284           tail = &uri->query;
1285           for (;;)
1286             {
1287               uri_tuple_t elem;
1288
1289               if ((p2 = strchr (p, '&')))
1290                 *p2++ = 0;
1291               if (!(elem = parse_tuple (p)))
1292                 return GPG_ERR_BAD_URI;
1293               *tail = elem;
1294               tail = &elem->next;
1295
1296               if (!p2)
1297                 break; /* Ready. */
1298               p = p2;
1299             }
1300         }
1301     }
1302
1303   if (is_onion_address (uri->host))
1304     uri->onion = 1;
1305
1306   return 0;
1307 }
1308
1309
1310 /*
1311  * Remove all %xx escapes; this is done in-place.  Returns: New length
1312  * of the string.
1313  */
1314 static int
1315 remove_escapes (char *string)
1316 {
1317   int n = 0;
1318   unsigned char *p, *s;
1319
1320   for (p = s = (unsigned char*)string; *s; s++)
1321     {
1322       if (*s == '%')
1323         {
1324           if (s[1] && s[2] && isxdigit (s[1]) && isxdigit (s[2]))
1325             {
1326               s++;
1327               *p = *s >= '0' && *s <= '9' ? *s - '0' :
1328                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
1329               *p <<= 4;
1330               s++;
1331               *p |= *s >= '0' && *s <= '9' ? *s - '0' :
1332                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
1333               p++;
1334               n++;
1335             }
1336           else
1337             {
1338               *p++ = *s++;
1339               if (*s)
1340                 *p++ = *s++;
1341               if (*s)
1342                 *p++ = *s++;
1343               if (*s)
1344                 *p = 0;
1345               return -1; /* Bad URI. */
1346             }
1347         }
1348       else
1349         {
1350           *p++ = *s;
1351           n++;
1352         }
1353     }
1354   *p = 0; /* Make sure to keep a string terminator. */
1355   return n;
1356 }
1357
1358
1359 /* If SPECIAL is NULL this function escapes in forms mode.  */
1360 static size_t
1361 escape_data (char *buffer, const void *data, size_t datalen,
1362              const char *special)
1363 {
1364   int forms = !special;
1365   const unsigned char *s;
1366   size_t n = 0;
1367
1368   if (forms)
1369     special = "%;?&=";
1370
1371   for (s = data; datalen; s++, datalen--)
1372     {
1373       if (forms && *s == ' ')
1374         {
1375           if (buffer)
1376             *buffer++ = '+';
1377           n++;
1378         }
1379       else if (forms && *s == '\n')
1380         {
1381           if (buffer)
1382             memcpy (buffer, "%0D%0A", 6);
1383           n += 6;
1384         }
1385       else if (forms && *s == '\r' && datalen > 1 && s[1] == '\n')
1386         {
1387           if (buffer)
1388             memcpy (buffer, "%0D%0A", 6);
1389           n += 6;
1390           s++;
1391           datalen--;
1392         }
1393       else if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
1394         {
1395           if (buffer)
1396             *(unsigned char*)buffer++ = *s;
1397           n++;
1398         }
1399       else
1400         {
1401           if (buffer)
1402             {
1403               snprintf (buffer, 4, "%%%02X", *s);
1404               buffer += 3;
1405             }
1406           n += 3;
1407         }
1408     }
1409   return n;
1410 }
1411
1412
1413 static int
1414 insert_escapes (char *buffer, const char *string,
1415                 const char *special)
1416 {
1417   return escape_data (buffer, string, strlen (string), special);
1418 }
1419
1420
1421 /* Allocate a new string from STRING using standard HTTP escaping as
1422    well as escaping of characters given in SPECIALS.  A common pattern
1423    for SPECIALS is "%;?&=". However it depends on the needs, for
1424    example "+" and "/: often needs to be escaped too.  Returns NULL on
1425    failure and sets ERRNO.  If SPECIAL is NULL a dedicated forms
1426    encoding mode is used. */
1427 char *
1428 http_escape_string (const char *string, const char *specials)
1429 {
1430   int n;
1431   char *buf;
1432
1433   n = insert_escapes (NULL, string, specials);
1434   buf = xtrymalloc (n+1);
1435   if (buf)
1436     {
1437       insert_escapes (buf, string, specials);
1438       buf[n] = 0;
1439     }
1440   return buf;
1441 }
1442
1443 /* Allocate a new string from {DATA,DATALEN} using standard HTTP
1444    escaping as well as escaping of characters given in SPECIALS.  A
1445    common pattern for SPECIALS is "%;?&=".  However it depends on the
1446    needs, for example "+" and "/: often needs to be escaped too.
1447    Returns NULL on failure and sets ERRNO.  If SPECIAL is NULL a
1448    dedicated forms encoding mode is used. */
1449 char *
1450 http_escape_data (const void *data, size_t datalen, const char *specials)
1451 {
1452   int n;
1453   char *buf;
1454
1455   n = escape_data (NULL, data, datalen, specials);
1456   buf = xtrymalloc (n+1);
1457   if (buf)
1458     {
1459       escape_data (buf, data, datalen, specials);
1460       buf[n] = 0;
1461     }
1462   return buf;
1463 }
1464
1465
1466 static uri_tuple_t
1467 parse_tuple (char *string)
1468 {
1469   char *p = string;
1470   char *p2;
1471   int n;
1472   uri_tuple_t tuple;
1473
1474   if ((p2 = strchr (p, '=')))
1475     *p2++ = 0;
1476   if ((n = remove_escapes (p)) < 0)
1477     return NULL; /* Bad URI. */
1478   if (n != strlen (p))
1479     return NULL; /* Name with a Nul in it. */
1480   tuple = xtrycalloc (1, sizeof *tuple);
1481   if (!tuple)
1482     return NULL; /* Out of core. */
1483   tuple->name = p;
1484   if (!p2) /* We have only the name, so we assume an empty value string. */
1485     {
1486       tuple->value = p + strlen (p);
1487       tuple->valuelen = 0;
1488       tuple->no_value = 1; /* Explicitly mark that we have seen no '='. */
1489     }
1490   else /* Name and value. */
1491     {
1492       if ((n = remove_escapes (p2)) < 0)
1493         {
1494           xfree (tuple);
1495           return NULL; /* Bad URI. */
1496         }
1497       tuple->value = p2;
1498       tuple->valuelen = n;
1499     }
1500   return tuple;
1501 }
1502
1503
1504 /* Return true if STRING is likely "hostname:port" or only "hostname".  */
1505 static int
1506 is_hostname_port (const char *string)
1507 {
1508   int colons = 0;
1509
1510   if (!string || !*string)
1511     return 0;
1512   for (; *string; string++)
1513     {
1514       if (*string == ':')
1515         {
1516           if (colons)
1517             return 0;
1518           if (!string[1])
1519             return 0;
1520           colons++;
1521         }
1522       else if (!colons && strchr (" \t\f\n\v_@[]/", *string))
1523         return 0; /* Invalid characters in hostname. */
1524       else if (colons && !digitp (string))
1525         return 0; /* Not a digit in the port.  */
1526     }
1527   return 1;
1528 }
1529
1530
1531 /*
1532  * Send a HTTP request to the server
1533  * Returns 0 if the request was successful
1534  */
1535 static gpg_error_t
1536 send_request (http_t hd, const char *httphost, const char *auth,
1537               const char *proxy, const char *srvtag, strlist_t headers)
1538 {
1539   gpg_error_t err;
1540   const char *server;
1541   char *request, *p;
1542   unsigned short port;
1543   const char *http_proxy = NULL;
1544   char *proxy_authstr = NULL;
1545   char *authstr = NULL;
1546   int sock;
1547   int hnf;
1548
1549   if (hd->uri->use_tls && !hd->session)
1550     {
1551       log_error ("TLS requested but no session object provided\n");
1552       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1553     }
1554 #ifdef USE_TLS
1555   if (hd->uri->use_tls && !hd->session->tls_session)
1556     {
1557       log_error ("TLS requested but no GNUTLS context available\n");
1558       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1559     }
1560 #endif /*USE_TLS*/
1561
1562   if ((hd->flags & HTTP_FLAG_FORCE_TOR))
1563     {
1564       int mode;
1565
1566       if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
1567         {
1568           log_error ("Tor support is not available\n");
1569           return gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1570         }
1571     }
1572
1573   server = *hd->uri->host ? hd->uri->host : "localhost";
1574   port = hd->uri->port ? hd->uri->port : 80;
1575
1576   /* Try to use SNI.  */
1577 #ifdef USE_TLS
1578   if (hd->uri->use_tls)
1579     {
1580 # if HTTP_USE_GNUTLS
1581       int rc;
1582 # endif
1583
1584       xfree (hd->session->servername);
1585       hd->session->servername = xtrystrdup (httphost? httphost : server);
1586       if (!hd->session->servername)
1587         {
1588           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1589           return err;
1590         }
1591
1592 # if HTTP_USE_NTBTLS
1593       err = ntbtls_set_hostname (hd->session->tls_session,
1594                                  hd->session->servername);
1595       if (err)
1596         {
1597           log_info ("ntbtls_set_hostname failed: %s\n", gpg_strerror (err));
1598           return err;
1599         }
1600 # elif HTTP_USE_GNUTLS
1601       rc = gnutls_server_name_set (hd->session->tls_session,
1602                                    GNUTLS_NAME_DNS,
1603                                    hd->session->servername,
1604                                    strlen (hd->session->servername));
1605       if (rc < 0)
1606         log_info ("gnutls_server_name_set failed: %s\n", gnutls_strerror (rc));
1607 # endif /*HTTP_USE_GNUTLS*/
1608     }
1609 #endif /*USE_TLS*/
1610
1611   if ( (proxy && *proxy)
1612        || ( (hd->flags & HTTP_FLAG_TRY_PROXY)
1613             && (http_proxy = getenv (HTTP_PROXY_ENV))
1614             && *http_proxy ))
1615     {
1616       parsed_uri_t uri;
1617       int save_errno;
1618
1619       if (proxy)
1620         http_proxy = proxy;
1621
1622       err = parse_uri (&uri, http_proxy, 0, 0);
1623       if (gpg_err_code (err) == GPG_ERR_INV_URI
1624           && is_hostname_port (http_proxy))
1625         {
1626           /* Retry assuming a "hostname:port" string.  */
1627           char *tmpname = strconcat ("http://", http_proxy, NULL);
1628           if (tmpname && !parse_uri (&uri, tmpname, 0, 0))
1629             err = 0;
1630           xfree (tmpname);
1631         }
1632
1633       if (err)
1634         ;
1635       else if (!strcmp (uri->scheme, "http") || !strcmp (uri->scheme, "socks4"))
1636         ;
1637       else if (!strcmp (uri->scheme, "socks5h"))
1638         err = gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1639       else
1640         err = gpg_err_make (default_errsource, GPG_ERR_INV_URI);
1641
1642       if (err)
1643         {
1644           log_error ("invalid HTTP proxy (%s): %s\n",
1645                      http_proxy, gpg_strerror (err));
1646           return gpg_err_make (default_errsource, GPG_ERR_CONFIGURATION);
1647         }
1648
1649       if (uri->auth)
1650         {
1651           remove_escapes (uri->auth);
1652           proxy_authstr = make_header_line ("Proxy-Authorization: Basic ",
1653                                             "\r\n",
1654                                             uri->auth, strlen(uri->auth));
1655           if (!proxy_authstr)
1656             {
1657               err = gpg_err_make (default_errsource,
1658                                   gpg_err_code_from_syserror ());
1659               http_release_parsed_uri (uri);
1660               return err;
1661             }
1662         }
1663
1664       sock = connect_server (*uri->host ? uri->host : "localhost",
1665                              uri->port ? uri->port : 80,
1666                              hd->flags, srvtag, &hnf);
1667       save_errno = errno;
1668       http_release_parsed_uri (uri);
1669       if (sock == ASSUAN_INVALID_FD)
1670         gpg_err_set_errno (save_errno);
1671     }
1672   else
1673     {
1674       sock = connect_server (server, port, hd->flags, srvtag, &hnf);
1675     }
1676
1677   if (sock == ASSUAN_INVALID_FD)
1678     {
1679       xfree (proxy_authstr);
1680       return gpg_err_make (default_errsource,
1681                            (hnf? GPG_ERR_UNKNOWN_HOST
1682                                : gpg_err_code_from_syserror ()));
1683     }
1684   hd->sock = my_socket_new (sock);
1685   if (!hd->sock)
1686     {
1687       xfree (proxy_authstr);
1688       return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1689     }
1690
1691
1692
1693 #if HTTP_USE_NTBTLS
1694   if (hd->uri->use_tls)
1695     {
1696       estream_t in, out;
1697
1698       my_socket_ref (hd->sock);
1699
1700       in = es_fdopen_nc (hd->sock->fd, "rb");
1701       if (!in)
1702         {
1703           err = gpg_error_from_syserror ();
1704           xfree (proxy_authstr);
1705           return err;
1706         }
1707
1708       out = es_fdopen_nc (hd->sock->fd, "wb");
1709       if (!out)
1710         {
1711           err = gpg_error_from_syserror ();
1712           es_fclose (in);
1713           xfree (proxy_authstr);
1714           return err;
1715         }
1716
1717       err = ntbtls_set_transport (hd->session->tls_session, in, out);
1718       if (err)
1719         {
1720           log_info ("TLS set_transport failed: %s <%s>\n",
1721                     gpg_strerror (err), gpg_strsource (err));
1722           xfree (proxy_authstr);
1723           return err;
1724         }
1725
1726       while ((err = ntbtls_handshake (hd->session->tls_session)))
1727         {
1728           switch (err)
1729             {
1730             default:
1731               log_info ("TLS handshake failed: %s <%s>\n",
1732                         gpg_strerror (err), gpg_strsource (err));
1733               xfree (proxy_authstr);
1734               return err;
1735             }
1736         }
1737
1738       hd->session->verify.done = 0;
1739       if (tls_callback)
1740         err = tls_callback (hd, hd->session, 0);
1741       else
1742         err = http_verify_server_credentials (hd->session);
1743       if (err)
1744         {
1745           log_info ("TLS connection authentication failed: %s <%s>\n",
1746                     gpg_strerror (err), gpg_strsource (err));
1747           xfree (proxy_authstr);
1748           return err;
1749         }
1750     }
1751 #elif HTTP_USE_GNUTLS
1752   if (hd->uri->use_tls)
1753     {
1754       int rc;
1755
1756       my_socket_ref (hd->sock);
1757       gnutls_transport_set_ptr (hd->session->tls_session, hd->sock);
1758       gnutls_transport_set_pull_function (hd->session->tls_session,
1759                                           my_gnutls_read);
1760       gnutls_transport_set_push_function (hd->session->tls_session,
1761                                           my_gnutls_write);
1762
1763       do
1764         {
1765           rc = gnutls_handshake (hd->session->tls_session);
1766         }
1767       while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
1768       if (rc < 0)
1769         {
1770           if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED
1771               || rc == GNUTLS_E_FATAL_ALERT_RECEIVED)
1772             {
1773               gnutls_alert_description_t alertno;
1774               const char *alertstr;
1775
1776               alertno = gnutls_alert_get (hd->session->tls_session);
1777               alertstr = gnutls_alert_get_name (alertno);
1778               log_info ("TLS handshake failed: %s (alert %d)\n",
1779                         alertstr, (int)alertno);
1780               if (alertno == GNUTLS_A_UNRECOGNIZED_NAME && server)
1781                 log_info ("  (sent server name '%s')\n", server);
1782             }
1783           else
1784             log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
1785           xfree (proxy_authstr);
1786           return gpg_err_make (default_errsource, GPG_ERR_NETWORK);
1787         }
1788
1789       hd->session->verify.done = 0;
1790       if (tls_callback)
1791         err = tls_callback (hd, hd->session, 0);
1792       else
1793         err = http_verify_server_credentials (hd->session);
1794       if (err)
1795         {
1796           log_info ("TLS connection authentication failed: %s\n",
1797                     gpg_strerror (err));
1798           xfree (proxy_authstr);
1799           return err;
1800         }
1801     }
1802 #endif /*HTTP_USE_GNUTLS*/
1803
1804   if (auth || hd->uri->auth)
1805     {
1806       char *myauth;
1807
1808       if (auth)
1809         {
1810           myauth = xtrystrdup (auth);
1811           if (!myauth)
1812             {
1813               xfree (proxy_authstr);
1814               return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1815             }
1816           remove_escapes (myauth);
1817         }
1818       else
1819         {
1820           remove_escapes (hd->uri->auth);
1821           myauth = hd->uri->auth;
1822         }
1823
1824       authstr = make_header_line ("Authorization: Basic ", "\r\n",
1825                                   myauth, strlen (myauth));
1826       if (auth)
1827         xfree (myauth);
1828
1829       if (!authstr)
1830         {
1831           xfree (proxy_authstr);
1832           return gpg_err_make (default_errsource,
1833                                gpg_err_code_from_syserror ());
1834         }
1835     }
1836
1837   p = build_rel_path (hd->uri);
1838   if (!p)
1839     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1840
1841   if (http_proxy && *http_proxy)
1842     {
1843       request = es_bsprintf
1844         ("%s %s://%s:%hu%s%s HTTP/1.0\r\n%s%s",
1845          hd->req_type == HTTP_REQ_GET ? "GET" :
1846          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
1847          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
1848          hd->uri->use_tls? "https" : "http",
1849          httphost? httphost : server,
1850          port, *p == '/' ? "" : "/", p,
1851          authstr ? authstr : "",
1852          proxy_authstr ? proxy_authstr : "");
1853     }
1854   else
1855     {
1856       char portstr[35];
1857
1858       if (port == 80)
1859         *portstr = 0;
1860       else
1861         snprintf (portstr, sizeof portstr, ":%u", port);
1862
1863       request = es_bsprintf
1864         ("%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
1865          hd->req_type == HTTP_REQ_GET ? "GET" :
1866          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
1867          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
1868          *p == '/' ? "" : "/", p,
1869          httphost? httphost : server,
1870          portstr,
1871          authstr? authstr:"");
1872     }
1873   xfree (p);
1874   if (!request)
1875     {
1876       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1877       xfree (authstr);
1878       xfree (proxy_authstr);
1879       return err;
1880     }
1881
1882   /* log_debug ("request:\n%s\nEND request\n", request); */
1883
1884   /* First setup estream so that we can write even the first line
1885      using estream.  This is also required for the sake of gnutls. */
1886   {
1887     cookie_t cookie;
1888
1889     cookie = xtrycalloc (1, sizeof *cookie);
1890     if (!cookie)
1891       {
1892         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1893         goto leave;
1894       }
1895     cookie->sock = my_socket_ref (hd->sock);
1896     hd->write_cookie = cookie;
1897     cookie->use_tls = hd->uri->use_tls;
1898     cookie->session = http_session_ref (hd->session);
1899
1900     hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1901     if (!hd->fp_write)
1902       {
1903         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1904         my_socket_unref (cookie->sock, NULL, NULL);
1905         xfree (cookie);
1906         hd->write_cookie = NULL;
1907       }
1908     else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
1909       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1910     else
1911       err = 0;
1912
1913   if (!err)
1914     {
1915       for (;headers; headers=headers->next)
1916         {
1917           if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write))
1918               || (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write)))
1919             {
1920               err = gpg_err_make (default_errsource,
1921                                   gpg_err_code_from_syserror ());
1922               break;
1923             }
1924         }
1925     }
1926   }
1927
1928  leave:
1929   es_free (request);
1930   xfree (authstr);
1931   xfree (proxy_authstr);
1932
1933   return err;
1934 }
1935
1936
1937 /*
1938  * Build the relative path from the parsed URI.  Minimal
1939  * implementation.  May return NULL in case of memory failure; errno
1940  * is then set accordingly.
1941  */
1942 static char *
1943 build_rel_path (parsed_uri_t uri)
1944 {
1945   uri_tuple_t r;
1946   char *rel_path, *p;
1947   int n;
1948
1949   /* Count the needed space. */
1950   n = insert_escapes (NULL, uri->path, "%;?&");
1951   /* TODO: build params. */
1952   for (r = uri->query; r; r = r->next)
1953     {
1954       n++; /* '?'/'&' */
1955       n += insert_escapes (NULL, r->name, "%;?&=");
1956       if (!r->no_value)
1957         {
1958           n++; /* '=' */
1959           n += insert_escapes (NULL, r->value, "%;?&=");
1960         }
1961     }
1962   n++;
1963
1964   /* Now allocate and copy. */
1965   p = rel_path = xtrymalloc (n);
1966   if (!p)
1967     return NULL;
1968   n = insert_escapes (p, uri->path, "%;?&");
1969   p += n;
1970   /* TODO: add params. */
1971   for (r = uri->query; r; r = r->next)
1972     {
1973       *p++ = r == uri->query ? '?' : '&';
1974       n = insert_escapes (p, r->name, "%;?&=");
1975       p += n;
1976       if (!r->no_value)
1977         {
1978           *p++ = '=';
1979           /* TODO: Use valuelen. */
1980           n = insert_escapes (p, r->value, "%;?&=");
1981           p += n;
1982         }
1983     }
1984   *p = 0;
1985   return rel_path;
1986 }
1987
1988
1989 /* Transform a header name into a standard capitalized format; e.g.
1990    "Content-Type".  Conversion stops at the colon.  As usual we don't
1991    use the localized versions of ctype.h. */
1992 static void
1993 capitalize_header_name (char *name)
1994 {
1995   int first = 1;
1996
1997   for (; *name && *name != ':'; name++)
1998     {
1999       if (*name == '-')
2000         first = 1;
2001       else if (first)
2002         {
2003           if (*name >= 'a' && *name <= 'z')
2004             *name = *name - 'a' + 'A';
2005           first = 0;
2006         }
2007       else if (*name >= 'A' && *name <= 'Z')
2008         *name = *name - 'A' + 'a';
2009     }
2010 }
2011
2012
2013 /* Store an HTTP header line in LINE away.  Line continuation is
2014    supported as well as merging of headers with the same name. This
2015    function may modify LINE. */
2016 static gpg_err_code_t
2017 store_header (http_t hd, char *line)
2018 {
2019   size_t n;
2020   char *p, *value;
2021   header_t h;
2022
2023   n = strlen (line);
2024   if (n && line[n-1] == '\n')
2025     {
2026       line[--n] = 0;
2027       if (n && line[n-1] == '\r')
2028         line[--n] = 0;
2029     }
2030   if (!n)  /* we are never called to hit this. */
2031     return GPG_ERR_BUG;
2032   if (*line == ' ' || *line == '\t')
2033     {
2034       /* Continuation. This won't happen too often as it is not
2035          recommended.  We use a straightforward implementaion. */
2036       if (!hd->headers)
2037         return GPG_ERR_PROTOCOL_VIOLATION;
2038       n += strlen (hd->headers->value);
2039       p = xtrymalloc (n+1);
2040       if (!p)
2041         return gpg_err_code_from_syserror ();
2042       strcpy (stpcpy (p, hd->headers->value), line);
2043       xfree (hd->headers->value);
2044       hd->headers->value = p;
2045       return 0;
2046     }
2047
2048   capitalize_header_name (line);
2049   p = strchr (line, ':');
2050   if (!p)
2051     return GPG_ERR_PROTOCOL_VIOLATION;
2052   *p++ = 0;
2053   while (*p == ' ' || *p == '\t')
2054     p++;
2055   value = p;
2056
2057   for (h=hd->headers; h; h = h->next)
2058     if ( !strcmp (h->name, line) )
2059       break;
2060   if (h)
2061     {
2062       /* We have already seen a line with that name.  Thus we assume
2063          it is a comma separated list and merge them.  */
2064       p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1);
2065       if (!p)
2066         return gpg_err_code_from_syserror ();
2067       strcpy (stpcpy (stpcpy (p, h->value), ","), value);
2068       xfree (h->value);
2069       h->value = p;
2070       return 0;
2071     }
2072
2073   /* Append a new header. */
2074   h = xtrymalloc (sizeof *h + strlen (line));
2075   if (!h)
2076     return gpg_err_code_from_syserror ();
2077   strcpy (h->name, line);
2078   h->value = xtrymalloc (strlen (value)+1);
2079   if (!h->value)
2080     {
2081       xfree (h);
2082       return gpg_err_code_from_syserror ();
2083     }
2084   strcpy (h->value, value);
2085   h->next = hd->headers;
2086   hd->headers = h;
2087
2088   return 0;
2089 }
2090
2091
2092 /* Return the header NAME from the last response.  The returned value
2093    is valid as along as HD has not been closed and no other request
2094    has been send. If the header was not found, NULL is returned.  NAME
2095    must be canonicalized, that is the first letter of each dash
2096    delimited part must be uppercase and all other letters lowercase.  */
2097 const char *
2098 http_get_header (http_t hd, const char *name)
2099 {
2100   header_t h;
2101
2102   for (h=hd->headers; h; h = h->next)
2103     if ( !strcmp (h->name, name) )
2104       return h->value;
2105   return NULL;
2106 }
2107
2108
2109 /* Return a newly allocated and NULL terminated array with pointers to
2110    header names.  The array must be released with xfree() and its
2111    content is only values as long as no other request has been
2112    send.  */
2113 const char **
2114 http_get_header_names (http_t hd)
2115 {
2116   const char **array;
2117   size_t n;
2118   header_t h;
2119
2120   for (n=0, h = hd->headers; h; h = h->next)
2121     n++;
2122   array = xtrycalloc (n+1, sizeof *array);
2123   if (array)
2124     {
2125       for (n=0, h = hd->headers; h; h = h->next)
2126         array[n++] = h->name;
2127     }
2128
2129   return array;
2130 }
2131
2132
2133 /*
2134  * Parse the response from a server.
2135  * Returns: Errorcode and sets some files in the handle
2136  */
2137 static gpg_err_code_t
2138 parse_response (http_t hd)
2139 {
2140   char *line, *p, *p2;
2141   size_t maxlen, len;
2142   cookie_t cookie = hd->read_cookie;
2143   const char *s;
2144
2145   /* Delete old header lines.  */
2146   while (hd->headers)
2147     {
2148       header_t tmp = hd->headers->next;
2149       xfree (hd->headers->value);
2150       xfree (hd->headers);
2151       hd->headers = tmp;
2152     }
2153
2154   /* Wait for the status line. */
2155   do
2156     {
2157       maxlen = MAX_LINELEN;
2158       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2159       line = hd->buffer;
2160       if (!line)
2161         return gpg_err_code_from_syserror (); /* Out of core. */
2162       if (!maxlen)
2163         return GPG_ERR_TRUNCATED; /* Line has been truncated. */
2164       if (!len)
2165         return GPG_ERR_EOF;
2166
2167       if ((hd->flags & HTTP_FLAG_LOG_RESP))
2168         log_info ("RESP: '%.*s'\n",
2169                   (int)strlen(line)-(*line&&line[1]?2:0),line);
2170     }
2171   while (!*line);
2172
2173   if ((p = strchr (line, '/')))
2174     *p++ = 0;
2175   if (!p || strcmp (line, "HTTP"))
2176     return 0; /* Assume http 0.9. */
2177
2178   if ((p2 = strpbrk (p, " \t")))
2179     {
2180       *p2++ = 0;
2181       p2 += strspn (p2, " \t");
2182     }
2183   if (!p2)
2184     return 0; /* Also assume http 0.9. */
2185   p = p2;
2186   /* TODO: Add HTTP version number check. */
2187   if ((p2 = strpbrk (p, " \t")))
2188     *p2++ = 0;
2189   if (!isdigit ((unsigned int)p[0]) || !isdigit ((unsigned int)p[1])
2190       || !isdigit ((unsigned int)p[2]) || p[3])
2191     {
2192       /* Malformed HTTP status code - assume http 0.9. */
2193       hd->is_http_0_9 = 1;
2194       hd->status_code = 200;
2195       return 0;
2196     }
2197   hd->status_code = atoi (p);
2198
2199   /* Skip all the header lines and wait for the empty line. */
2200   do
2201     {
2202       maxlen = MAX_LINELEN;
2203       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2204       line = hd->buffer;
2205       if (!line)
2206         return gpg_err_code_from_syserror (); /* Out of core. */
2207       /* Note, that we can silently ignore truncated lines. */
2208       if (!len)
2209         return GPG_ERR_EOF;
2210       /* Trim line endings of empty lines. */
2211       if ((*line == '\r' && line[1] == '\n') || *line == '\n')
2212         *line = 0;
2213       if ((hd->flags & HTTP_FLAG_LOG_RESP))
2214         log_info ("RESP: '%.*s'\n",
2215                   (int)strlen(line)-(*line&&line[1]?2:0),line);
2216       if (*line)
2217         {
2218           gpg_err_code_t ec = store_header (hd, line);
2219           if (ec)
2220             return ec;
2221         }
2222     }
2223   while (len && *line);
2224
2225   cookie->content_length_valid = 0;
2226   if (!(hd->flags & HTTP_FLAG_IGNORE_CL))
2227     {
2228       s = http_get_header (hd, "Content-Length");
2229       if (s)
2230         {
2231           cookie->content_length_valid = 1;
2232           cookie->content_length = string_to_u64 (s);
2233         }
2234     }
2235
2236   return 0;
2237 }
2238
2239 #if 0
2240 static int
2241 start_server ()
2242 {
2243   struct sockaddr_in mya;
2244   struct sockaddr_in peer;
2245   int fd, client;
2246   fd_set rfds;
2247   int addrlen;
2248   int i;
2249
2250   if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
2251     {
2252       log_error ("socket() failed: %s\n", strerror (errno));
2253       return -1;
2254     }
2255   i = 1;
2256   if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (byte *) & i, sizeof (i)))
2257     log_info ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno));
2258
2259   mya.sin_family = AF_INET;
2260   memset (&mya.sin_addr, 0, sizeof (mya.sin_addr));
2261   mya.sin_port = htons (11371);
2262
2263   if (bind (fd, (struct sockaddr *) &mya, sizeof (mya)))
2264     {
2265       log_error ("bind to port 11371 failed: %s\n", strerror (errno));
2266       sock_close (fd);
2267       return -1;
2268     }
2269
2270   if (listen (fd, 5))
2271     {
2272       log_error ("listen failed: %s\n", strerror (errno));
2273       sock_close (fd);
2274       return -1;
2275     }
2276
2277   for (;;)
2278     {
2279       FD_ZERO (&rfds);
2280       FD_SET (fd, &rfds);
2281
2282       if (my_select (fd + 1, &rfds, NULL, NULL, NULL) <= 0)
2283         continue;               /* ignore any errors */
2284
2285       if (!FD_ISSET (fd, &rfds))
2286         continue;
2287
2288       addrlen = sizeof peer;
2289       client = my_accept (fd, (struct sockaddr *) &peer, &addrlen);
2290       if (client == -1)
2291         continue;               /* oops */
2292
2293       log_info ("connect from %s\n", inet_ntoa (peer.sin_addr));
2294
2295       fflush (stdout);
2296       fflush (stderr);
2297       if (!fork ())
2298         {
2299           int c;
2300           FILE *fp;
2301
2302           fp = fdopen (client, "r");
2303           while ((c = getc (fp)) != EOF)
2304             putchar (c);
2305           fclose (fp);
2306           exit (0);
2307         }
2308       sock_close (client);
2309     }
2310
2311
2312   return 0;
2313 }
2314 #endif
2315
2316 /* Actually connect to a server.  Returns the file descriptor or -1 on
2317    error.  ERRNO is set on error. */
2318 static assuan_fd_t
2319 connect_server (const char *server, unsigned short port,
2320                 unsigned int flags, const char *srvtag, int *r_host_not_found)
2321 {
2322   gpg_error_t err;
2323   assuan_fd_t sock = ASSUAN_INVALID_FD;
2324   unsigned int srvcount = 0;
2325   int hostfound = 0;
2326   int anyhostaddr = 0;
2327   int srv, connected;
2328   int last_errno = 0;
2329   struct srventry *serverlist = NULL;
2330   int ret;
2331
2332   *r_host_not_found = 0;
2333 #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
2334   init_sockets ();
2335 #endif /*Windows*/
2336
2337   /* Onion addresses require special treatment.  */
2338   if (is_onion_address (server))
2339     {
2340 #ifdef ASSUAN_SOCK_TOR
2341
2342       sock = assuan_sock_connect_byname (server, port, 0, NULL,
2343                                          ASSUAN_SOCK_TOR);
2344       if (sock == ASSUAN_INVALID_FD)
2345         {
2346           if (errno == EHOSTUNREACH)
2347             *r_host_not_found = 1;
2348           log_error ("can't connect to '%s': %s\n", server, strerror (errno));
2349         }
2350       else
2351         notify_netactivity ();
2352       return sock;
2353
2354 #else /*!ASSUAN_SOCK_TOR*/
2355
2356       gpg_err_set_errno (ENETUNREACH);
2357       return -1; /* Out of core.  */
2358
2359 #endif /*!HASSUAN_SOCK_TOR*/
2360     }
2361
2362   /* Do the SRV thing */
2363   if (srvtag)
2364     {
2365       /* We're using SRV, so append the tags. */
2366       if (1 + strlen (srvtag) + 6 + strlen (server) + 1
2367           <= DIMof (struct srventry, target))
2368         {
2369           char *srvname = xtrymalloc (DIMof (struct srventry, target));
2370
2371           if (!srvname) /* Out of core */
2372             {
2373               serverlist = NULL;
2374               srvcount = 0;
2375             }
2376           else
2377             {
2378               stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srvtag),
2379                               "._tcp."), server);
2380               err = get_dns_srv (srvname, &serverlist, &srvcount);
2381               if (err)
2382                 log_info ("getting SRV '%s' failed: %s\n",
2383                           srvname, gpg_strerror (err));
2384               xfree (srvname);
2385               /* Note that on error SRVCOUNT is zero.  */
2386             }
2387         }
2388     }
2389
2390   if (!serverlist)
2391     {
2392       /* Either we're not using SRV, or the SRV lookup failed.  Make
2393          up a fake SRV record. */
2394       serverlist = xtrycalloc (1, sizeof *serverlist);
2395       if (!serverlist)
2396         return -1; /* Out of core.  */
2397       serverlist->port = port;
2398       strncpy (serverlist->target, server, DIMof (struct srventry, target));
2399       serverlist->target[DIMof (struct srventry, target)-1] = '\0';
2400       srvcount = 1;
2401     }
2402
2403   connected = 0;
2404   for (srv=0; srv < srvcount && !connected; srv++)
2405     {
2406       dns_addrinfo_t aibuf, ai;
2407
2408       err = resolve_dns_name (serverlist[srv].target, port, 0, SOCK_STREAM,
2409                               &aibuf, NULL);
2410       if (err)
2411         {
2412           log_info ("resolving '%s' failed: %s\n",
2413                     serverlist[srv].target, gpg_strerror (err));
2414           continue; /* Not found - try next one. */
2415         }
2416       hostfound = 1;
2417
2418       for (ai = aibuf; ai && !connected; ai = ai->next)
2419         {
2420           if (ai->family == AF_INET && (flags & HTTP_FLAG_IGNORE_IPv4))
2421             continue;
2422           if (ai->family == AF_INET6 && (flags & HTTP_FLAG_IGNORE_IPv6))
2423             continue;
2424
2425           if (sock != ASSUAN_INVALID_FD)
2426             assuan_sock_close (sock);
2427           sock = assuan_sock_new (ai->family, ai->socktype, ai->protocol);
2428           if (sock == ASSUAN_INVALID_FD)
2429             {
2430               int save_errno = errno;
2431               log_error ("error creating socket: %s\n", strerror (errno));
2432               free_dns_addrinfo (aibuf);
2433               xfree (serverlist);
2434               errno = save_errno;
2435               return ASSUAN_INVALID_FD;
2436             }
2437
2438           anyhostaddr = 1;
2439           ret = assuan_sock_connect (sock, ai->addr, ai->addrlen);
2440           if (ret)
2441             last_errno = errno;
2442           else
2443             {
2444               connected = 1;
2445               notify_netactivity ();
2446             }
2447         }
2448       free_dns_addrinfo (aibuf);
2449     }
2450
2451   xfree (serverlist);
2452
2453   if (!connected)
2454     {
2455       if (!hostfound)
2456         log_error ("can't connect to '%s': %s\n",
2457                    server, "host not found");
2458       else if (!anyhostaddr)
2459         log_error ("can't connect to '%s': %s\n",
2460                    server, "no IP address for host");
2461       else
2462         {
2463 #ifdef HAVE_W32_SYSTEM
2464         log_error ("can't connect to '%s': ec=%d\n",
2465                    server, (int)WSAGetLastError());
2466 #else
2467         log_error ("can't connect to '%s': %s\n",
2468                    server, strerror (last_errno));
2469 #endif
2470         }
2471       if (!hostfound || (hostfound && !anyhostaddr))
2472         *r_host_not_found = 1;
2473       if (sock != ASSUAN_INVALID_FD)
2474         assuan_sock_close (sock);
2475       gpg_err_set_errno (last_errno);
2476       return ASSUAN_INVALID_FD;
2477     }
2478   return sock;
2479 }
2480
2481
2482 static gpg_error_t
2483 write_server (int sock, const char *data, size_t length)
2484 {
2485   int nleft;
2486   int nwritten;
2487
2488   nleft = length;
2489   while (nleft > 0)
2490     {
2491 #if defined(HAVE_W32_SYSTEM)
2492 # if defined(USE_NPTH)
2493       npth_unprotect ();
2494 # endif
2495       nwritten = send (sock, data, nleft, 0);
2496 # if defined(USE_NPTH)
2497       npth_protect ();
2498 # endif
2499       if ( nwritten == SOCKET_ERROR )
2500         {
2501           log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
2502           return gpg_error (GPG_ERR_NETWORK);
2503         }
2504 #else /*!HAVE_W32_SYSTEM*/
2505 # ifdef USE_NPTH
2506       nwritten = npth_write (sock, data, nleft);
2507 # else
2508       nwritten = write (sock, data, nleft);
2509 # endif
2510       if (nwritten == -1)
2511         {
2512           if (errno == EINTR)
2513             continue;
2514           if (errno == EAGAIN)
2515             {
2516               struct timeval tv;
2517
2518               tv.tv_sec = 0;
2519               tv.tv_usec = 50000;
2520               my_select (0, NULL, NULL, NULL, &tv);
2521               continue;
2522             }
2523           log_info ("network write failed: %s\n", strerror (errno));
2524           return gpg_error_from_syserror ();
2525         }
2526 #endif /*!HAVE_W32_SYSTEM*/
2527       nleft -= nwritten;
2528       data += nwritten;
2529     }
2530
2531   return 0;
2532 }
2533
2534
2535 \f
2536 /* Read handler for estream.  */
2537 static gpgrt_ssize_t
2538 cookie_read (void *cookie, void *buffer, size_t size)
2539 {
2540   cookie_t c = cookie;
2541   int nread;
2542
2543   if (c->content_length_valid)
2544     {
2545       if (!c->content_length)
2546         return 0; /* EOF */
2547       if (c->content_length < size)
2548         size = c->content_length;
2549     }
2550
2551 #if HTTP_USE_NTBTLS
2552   if (c->use_tls && c->session && c->session->tls_session)
2553     {
2554       estream_t in, out;
2555
2556       ntbtls_get_stream (c->session->tls_session, &in, &out);
2557       nread = es_fread (buffer, 1, size, in);
2558       log_debug ("TLS network read: %d/%u\n", nread, size);
2559     }
2560   else
2561 #elif HTTP_USE_GNUTLS
2562   if (c->use_tls && c->session && c->session->tls_session)
2563     {
2564     again:
2565       nread = gnutls_record_recv (c->session->tls_session, buffer, size);
2566       if (nread < 0)
2567         {
2568           if (nread == GNUTLS_E_INTERRUPTED)
2569             goto again;
2570           if (nread == GNUTLS_E_AGAIN)
2571             {
2572               struct timeval tv;
2573
2574               tv.tv_sec = 0;
2575               tv.tv_usec = 50000;
2576               my_select (0, NULL, NULL, NULL, &tv);
2577               goto again;
2578             }
2579           if (nread == GNUTLS_E_REHANDSHAKE)
2580             goto again; /* A client is allowed to just ignore this request. */
2581           if (nread == GNUTLS_E_PREMATURE_TERMINATION)
2582             {
2583               /* The server terminated the connection.  Close the TLS
2584                  session, and indicate EOF using a short read.  */
2585               close_tls_session (c->session);
2586               return 0;
2587             }
2588           log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
2589           gpg_err_set_errno (EIO);
2590           return -1;
2591         }
2592     }
2593   else
2594 #endif /*HTTP_USE_GNUTLS*/
2595     {
2596       do
2597         {
2598 #ifdef HAVE_W32_SYSTEM
2599           /* Under Windows we need to use recv for a socket.  */
2600 # if defined(USE_NPTH)
2601           npth_unprotect ();
2602 # endif
2603           nread = recv (c->sock->fd, buffer, size, 0);
2604 # if defined(USE_NPTH)
2605           npth_protect ();
2606 # endif
2607
2608 #else /*!HAVE_W32_SYSTEM*/
2609
2610 # ifdef USE_NPTH
2611           nread = npth_read (c->sock->fd, buffer, size);
2612 # else
2613           nread = read (c->sock->fd, buffer, size);
2614 # endif
2615
2616 #endif /*!HAVE_W32_SYSTEM*/
2617         }
2618       while (nread == -1 && errno == EINTR);
2619     }
2620
2621   if (c->content_length_valid && nread > 0)
2622     {
2623       if (nread < c->content_length)
2624         c->content_length -= nread;
2625       else
2626         c->content_length = 0;
2627     }
2628
2629   return (gpgrt_ssize_t)nread;
2630 }
2631
2632 /* Write handler for estream.  */
2633 static gpgrt_ssize_t
2634 cookie_write (void *cookie, const void *buffer_arg, size_t size)
2635 {
2636   const char *buffer = buffer_arg;
2637   cookie_t c = cookie;
2638   int nwritten = 0;
2639
2640 #if HTTP_USE_NTBTLS
2641   if (c->use_tls && c->session && c->session->tls_session)
2642     {
2643       estream_t in, out;
2644
2645       ntbtls_get_stream (c->session->tls_session, &in, &out);
2646       if (size == 0)
2647         es_fflush (out);
2648       else
2649         nwritten = es_fwrite (buffer, 1, size, out);
2650       log_debug ("TLS network write: %d/%u\n", nwritten, size);
2651     }
2652   else
2653 #elif HTTP_USE_GNUTLS
2654   if (c->use_tls && c->session && c->session->tls_session)
2655     {
2656       int nleft = size;
2657       while (nleft > 0)
2658         {
2659           nwritten = gnutls_record_send (c->session->tls_session,
2660                                          buffer, nleft);
2661           if (nwritten <= 0)
2662             {
2663               if (nwritten == GNUTLS_E_INTERRUPTED)
2664                 continue;
2665               if (nwritten == GNUTLS_E_AGAIN)
2666                 {
2667                   struct timeval tv;
2668
2669                   tv.tv_sec = 0;
2670                   tv.tv_usec = 50000;
2671                   my_select (0, NULL, NULL, NULL, &tv);
2672                   continue;
2673                 }
2674               log_info ("TLS network write failed: %s\n",
2675                         gnutls_strerror (nwritten));
2676               gpg_err_set_errno (EIO);
2677               return -1;
2678             }
2679           nleft -= nwritten;
2680           buffer += nwritten;
2681         }
2682     }
2683   else
2684 #endif /*HTTP_USE_GNUTLS*/
2685     {
2686       if ( write_server (c->sock->fd, buffer, size) )
2687         {
2688           gpg_err_set_errno (EIO);
2689           nwritten = -1;
2690         }
2691       else
2692         nwritten = size;
2693     }
2694
2695   return (gpgrt_ssize_t)nwritten;
2696 }
2697
2698
2699 #ifdef HTTP_USE_GNUTLS
2700 /* Wrapper for gnutls_bye used by my_socket_unref.  */
2701 static void
2702 send_gnutls_bye (void *opaque)
2703 {
2704   tls_session_t tls_session = opaque;
2705   int ret;
2706
2707  again:
2708   do
2709     ret = gnutls_bye (tls_session, GNUTLS_SHUT_RDWR);
2710   while (ret == GNUTLS_E_INTERRUPTED);
2711   if (ret == GNUTLS_E_AGAIN)
2712     {
2713       struct timeval tv;
2714
2715       tv.tv_sec = 0;
2716       tv.tv_usec = 50000;
2717       my_select (0, NULL, NULL, NULL, &tv);
2718       goto again;
2719     }
2720 }
2721 #endif /*HTTP_USE_GNUTLS*/
2722
2723 /* Close handler for estream.  */
2724 static int
2725 cookie_close (void *cookie)
2726 {
2727   cookie_t c = cookie;
2728
2729   if (!c)
2730     return 0;
2731
2732 #if HTTP_USE_NTBTLS
2733   if (c->use_tls && c->session && c->session->tls_session)
2734     {
2735       /* FIXME!! Possibly call ntbtls_close_notify for close
2736          of write stream.  */
2737       my_socket_unref (c->sock, NULL, NULL);
2738     }
2739   else
2740 #elif HTTP_USE_GNUTLS
2741   if (c->use_tls && c->session && c->session->tls_session)
2742     my_socket_unref (c->sock, send_gnutls_bye, c->session->tls_session);
2743   else
2744 #endif /*HTTP_USE_GNUTLS*/
2745     if (c->sock)
2746       my_socket_unref (c->sock, NULL, NULL);
2747
2748   if (c->session)
2749     http_session_unref (c->session);
2750   xfree (c);
2751   return 0;
2752 }
2753
2754
2755
2756 \f
2757 /* Verify the credentials of the server.  Returns 0 on success and
2758    store the result in the session object.  */
2759 gpg_error_t
2760 http_verify_server_credentials (http_session_t sess)
2761 {
2762 #if HTTP_USE_NTBTLS
2763   (void)sess;
2764   return 0;  /* FIXME!! */
2765 #elif HTTP_USE_GNUTLS
2766   static const char const errprefix[] = "TLS verification of peer failed";
2767   int rc;
2768   unsigned int status;
2769   const char *hostname;
2770   const gnutls_datum_t *certlist;
2771   unsigned int certlistlen;
2772   gnutls_x509_crt_t cert;
2773   gpg_error_t err = 0;
2774
2775   sess->verify.done = 1;
2776   sess->verify.status = 0;
2777   sess->verify.rc = GNUTLS_E_CERTIFICATE_ERROR;
2778
2779   if (gnutls_certificate_type_get (sess->tls_session) != GNUTLS_CRT_X509)
2780     {
2781       log_error ("%s: %s\n", errprefix, "not an X.509 certificate");
2782       sess->verify.rc = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
2783       return gpg_error (GPG_ERR_GENERAL);
2784     }
2785
2786   rc = gnutls_certificate_verify_peers2 (sess->tls_session, &status);
2787   if (rc)
2788     {
2789       log_error ("%s: %s\n", errprefix, gnutls_strerror (rc));
2790       if (!err)
2791         err = gpg_error (GPG_ERR_GENERAL);
2792     }
2793   else if (status)
2794     {
2795       log_error ("%s: status=0x%04x\n", errprefix, status);
2796 #if GNUTLS_VERSION_NUMBER >= 0x030104
2797       {
2798         gnutls_datum_t statusdat;
2799
2800         if (!gnutls_certificate_verification_status_print
2801             (status, GNUTLS_CRT_X509, &statusdat, 0))
2802           {
2803             log_info ("%s: %s\n", errprefix, statusdat.data);
2804             gnutls_free (statusdat.data);
2805           }
2806       }
2807 #endif /*gnutls >= 3.1.4*/
2808
2809       sess->verify.status = status;
2810       if (!err)
2811         err = gpg_error (GPG_ERR_GENERAL);
2812     }
2813
2814   hostname = sess->servername;
2815   if (!hostname || !strchr (hostname, '.'))
2816     {
2817       log_error ("%s: %s\n", errprefix, "hostname missing");
2818       if (!err)
2819         err = gpg_error (GPG_ERR_GENERAL);
2820     }
2821
2822   certlist = gnutls_certificate_get_peers (sess->tls_session, &certlistlen);
2823   if (!certlistlen)
2824     {
2825       log_error ("%s: %s\n", errprefix, "server did not send a certificate");
2826       if (!err)
2827         err = gpg_error (GPG_ERR_GENERAL);
2828
2829       /* Need to stop here.  */
2830       if (err)
2831         return err;
2832     }
2833
2834   rc = gnutls_x509_crt_init (&cert);
2835   if (rc < 0)
2836     {
2837       if (!err)
2838         err = gpg_error (GPG_ERR_GENERAL);
2839       if (err)
2840         return err;
2841     }
2842
2843   rc = gnutls_x509_crt_import (cert, &certlist[0], GNUTLS_X509_FMT_DER);
2844   if (rc < 0)
2845     {
2846       log_error ("%s: %s: %s\n", errprefix, "error importing certificate",
2847                  gnutls_strerror (rc));
2848       if (!err)
2849         err = gpg_error (GPG_ERR_GENERAL);
2850     }
2851
2852   if (!gnutls_x509_crt_check_hostname (cert, hostname))
2853     {
2854       log_error ("%s: %s\n", errprefix, "hostname does not match");
2855       if (!err)
2856         err = gpg_error (GPG_ERR_GENERAL);
2857     }
2858
2859   gnutls_x509_crt_deinit (cert);
2860
2861   if (!err)
2862     sess->verify.rc = 0;
2863
2864   if (sess->cert_log_cb)
2865     {
2866       const void *bufarr[10];
2867       size_t buflenarr[10];
2868       size_t n;
2869
2870       for (n = 0; n < certlistlen && n < DIM (bufarr)-1; n++)
2871         {
2872           bufarr[n] = certlist[n].data;
2873           buflenarr[n] = certlist[n].size;
2874         }
2875       bufarr[n] = NULL;
2876       buflenarr[n] = 0;
2877       sess->cert_log_cb (sess, err, hostname, bufarr, buflenarr);
2878     }
2879
2880   return err;
2881 #else /*!HTTP_USE_GNUTLS*/
2882   (void)sess;
2883   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2884 #endif
2885 }
2886
2887 /* Return the first query variable with the specified key.  If there
2888    is no such variable, return NULL.  */
2889 struct uri_tuple_s *
2890 uri_query_lookup (parsed_uri_t uri, const char *key)
2891 {
2892   struct uri_tuple_s *t;
2893
2894   for (t = uri->query; t; t = t->next)
2895     if (strcmp (t->name, key) == 0)
2896       return t;
2897
2898   return NULL;
2899 }