dirmngr: Implement experimental SRV record lookup for WKD.
[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
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       err = get_dns_srv (server, srvtag, NULL, &serverlist, &srvcount);
2366       if (err)
2367         log_info ("getting '%s' SRV for '%s' failed: %s\n",
2368                   srvtag, server, gpg_strerror (err));
2369       /* Note that on error SRVCOUNT is zero.  */
2370     }
2371
2372   if (!serverlist)
2373     {
2374       /* Either we're not using SRV, or the SRV lookup failed.  Make
2375          up a fake SRV record. */
2376       serverlist = xtrycalloc (1, sizeof *serverlist);
2377       if (!serverlist)
2378         return -1; /* Out of core.  */
2379       serverlist->port = port;
2380       strncpy (serverlist->target, server, DIMof (struct srventry, target));
2381       serverlist->target[DIMof (struct srventry, target)-1] = '\0';
2382       srvcount = 1;
2383     }
2384
2385   connected = 0;
2386   for (srv=0; srv < srvcount && !connected; srv++)
2387     {
2388       dns_addrinfo_t aibuf, ai;
2389
2390       err = resolve_dns_name (serverlist[srv].target, port, 0, SOCK_STREAM,
2391                               &aibuf, NULL);
2392       if (err)
2393         {
2394           log_info ("resolving '%s' failed: %s\n",
2395                     serverlist[srv].target, gpg_strerror (err));
2396           continue; /* Not found - try next one. */
2397         }
2398       hostfound = 1;
2399
2400       for (ai = aibuf; ai && !connected; ai = ai->next)
2401         {
2402           if (ai->family == AF_INET && (flags & HTTP_FLAG_IGNORE_IPv4))
2403             continue;
2404           if (ai->family == AF_INET6 && (flags & HTTP_FLAG_IGNORE_IPv6))
2405             continue;
2406
2407           if (sock != ASSUAN_INVALID_FD)
2408             assuan_sock_close (sock);
2409           sock = assuan_sock_new (ai->family, ai->socktype, ai->protocol);
2410           if (sock == ASSUAN_INVALID_FD)
2411             {
2412               int save_errno = errno;
2413               log_error ("error creating socket: %s\n", strerror (errno));
2414               free_dns_addrinfo (aibuf);
2415               xfree (serverlist);
2416               errno = save_errno;
2417               return ASSUAN_INVALID_FD;
2418             }
2419
2420           anyhostaddr = 1;
2421           ret = assuan_sock_connect (sock, ai->addr, ai->addrlen);
2422           if (ret)
2423             last_errno = errno;
2424           else
2425             {
2426               connected = 1;
2427               notify_netactivity ();
2428             }
2429         }
2430       free_dns_addrinfo (aibuf);
2431     }
2432
2433   xfree (serverlist);
2434
2435   if (!connected)
2436     {
2437       if (!hostfound)
2438         log_error ("can't connect to '%s': %s\n",
2439                    server, "host not found");
2440       else if (!anyhostaddr)
2441         log_error ("can't connect to '%s': %s\n",
2442                    server, "no IP address for host");
2443       else
2444         {
2445 #ifdef HAVE_W32_SYSTEM
2446         log_error ("can't connect to '%s': ec=%d\n",
2447                    server, (int)WSAGetLastError());
2448 #else
2449         log_error ("can't connect to '%s': %s\n",
2450                    server, strerror (last_errno));
2451 #endif
2452         }
2453       if (!hostfound || (hostfound && !anyhostaddr))
2454         *r_host_not_found = 1;
2455       if (sock != ASSUAN_INVALID_FD)
2456         assuan_sock_close (sock);
2457       gpg_err_set_errno (last_errno);
2458       return ASSUAN_INVALID_FD;
2459     }
2460   return sock;
2461 }
2462
2463
2464 static gpg_error_t
2465 write_server (int sock, const char *data, size_t length)
2466 {
2467   int nleft;
2468   int nwritten;
2469
2470   nleft = length;
2471   while (nleft > 0)
2472     {
2473 #if defined(HAVE_W32_SYSTEM)
2474 # if defined(USE_NPTH)
2475       npth_unprotect ();
2476 # endif
2477       nwritten = send (sock, data, nleft, 0);
2478 # if defined(USE_NPTH)
2479       npth_protect ();
2480 # endif
2481       if ( nwritten == SOCKET_ERROR )
2482         {
2483           log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
2484           return gpg_error (GPG_ERR_NETWORK);
2485         }
2486 #else /*!HAVE_W32_SYSTEM*/
2487 # ifdef USE_NPTH
2488       nwritten = npth_write (sock, data, nleft);
2489 # else
2490       nwritten = write (sock, data, nleft);
2491 # endif
2492       if (nwritten == -1)
2493         {
2494           if (errno == EINTR)
2495             continue;
2496           if (errno == EAGAIN)
2497             {
2498               struct timeval tv;
2499
2500               tv.tv_sec = 0;
2501               tv.tv_usec = 50000;
2502               my_select (0, NULL, NULL, NULL, &tv);
2503               continue;
2504             }
2505           log_info ("network write failed: %s\n", strerror (errno));
2506           return gpg_error_from_syserror ();
2507         }
2508 #endif /*!HAVE_W32_SYSTEM*/
2509       nleft -= nwritten;
2510       data += nwritten;
2511     }
2512
2513   return 0;
2514 }
2515
2516
2517 \f
2518 /* Read handler for estream.  */
2519 static gpgrt_ssize_t
2520 cookie_read (void *cookie, void *buffer, size_t size)
2521 {
2522   cookie_t c = cookie;
2523   int nread;
2524
2525   if (c->content_length_valid)
2526     {
2527       if (!c->content_length)
2528         return 0; /* EOF */
2529       if (c->content_length < size)
2530         size = c->content_length;
2531     }
2532
2533 #if HTTP_USE_NTBTLS
2534   if (c->use_tls && c->session && c->session->tls_session)
2535     {
2536       estream_t in, out;
2537
2538       ntbtls_get_stream (c->session->tls_session, &in, &out);
2539       nread = es_fread (buffer, 1, size, in);
2540       log_debug ("TLS network read: %d/%u\n", nread, size);
2541     }
2542   else
2543 #elif HTTP_USE_GNUTLS
2544   if (c->use_tls && c->session && c->session->tls_session)
2545     {
2546     again:
2547       nread = gnutls_record_recv (c->session->tls_session, buffer, size);
2548       if (nread < 0)
2549         {
2550           if (nread == GNUTLS_E_INTERRUPTED)
2551             goto again;
2552           if (nread == GNUTLS_E_AGAIN)
2553             {
2554               struct timeval tv;
2555
2556               tv.tv_sec = 0;
2557               tv.tv_usec = 50000;
2558               my_select (0, NULL, NULL, NULL, &tv);
2559               goto again;
2560             }
2561           if (nread == GNUTLS_E_REHANDSHAKE)
2562             goto again; /* A client is allowed to just ignore this request. */
2563           if (nread == GNUTLS_E_PREMATURE_TERMINATION)
2564             {
2565               /* The server terminated the connection.  Close the TLS
2566                  session, and indicate EOF using a short read.  */
2567               close_tls_session (c->session);
2568               return 0;
2569             }
2570           log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
2571           gpg_err_set_errno (EIO);
2572           return -1;
2573         }
2574     }
2575   else
2576 #endif /*HTTP_USE_GNUTLS*/
2577     {
2578       do
2579         {
2580 #ifdef HAVE_W32_SYSTEM
2581           /* Under Windows we need to use recv for a socket.  */
2582 # if defined(USE_NPTH)
2583           npth_unprotect ();
2584 # endif
2585           nread = recv (c->sock->fd, buffer, size, 0);
2586 # if defined(USE_NPTH)
2587           npth_protect ();
2588 # endif
2589
2590 #else /*!HAVE_W32_SYSTEM*/
2591
2592 # ifdef USE_NPTH
2593           nread = npth_read (c->sock->fd, buffer, size);
2594 # else
2595           nread = read (c->sock->fd, buffer, size);
2596 # endif
2597
2598 #endif /*!HAVE_W32_SYSTEM*/
2599         }
2600       while (nread == -1 && errno == EINTR);
2601     }
2602
2603   if (c->content_length_valid && nread > 0)
2604     {
2605       if (nread < c->content_length)
2606         c->content_length -= nread;
2607       else
2608         c->content_length = 0;
2609     }
2610
2611   return (gpgrt_ssize_t)nread;
2612 }
2613
2614 /* Write handler for estream.  */
2615 static gpgrt_ssize_t
2616 cookie_write (void *cookie, const void *buffer_arg, size_t size)
2617 {
2618   const char *buffer = buffer_arg;
2619   cookie_t c = cookie;
2620   int nwritten = 0;
2621
2622 #if HTTP_USE_NTBTLS
2623   if (c->use_tls && c->session && c->session->tls_session)
2624     {
2625       estream_t in, out;
2626
2627       ntbtls_get_stream (c->session->tls_session, &in, &out);
2628       if (size == 0)
2629         es_fflush (out);
2630       else
2631         nwritten = es_fwrite (buffer, 1, size, out);
2632       log_debug ("TLS network write: %d/%u\n", nwritten, size);
2633     }
2634   else
2635 #elif HTTP_USE_GNUTLS
2636   if (c->use_tls && c->session && c->session->tls_session)
2637     {
2638       int nleft = size;
2639       while (nleft > 0)
2640         {
2641           nwritten = gnutls_record_send (c->session->tls_session,
2642                                          buffer, nleft);
2643           if (nwritten <= 0)
2644             {
2645               if (nwritten == GNUTLS_E_INTERRUPTED)
2646                 continue;
2647               if (nwritten == GNUTLS_E_AGAIN)
2648                 {
2649                   struct timeval tv;
2650
2651                   tv.tv_sec = 0;
2652                   tv.tv_usec = 50000;
2653                   my_select (0, NULL, NULL, NULL, &tv);
2654                   continue;
2655                 }
2656               log_info ("TLS network write failed: %s\n",
2657                         gnutls_strerror (nwritten));
2658               gpg_err_set_errno (EIO);
2659               return -1;
2660             }
2661           nleft -= nwritten;
2662           buffer += nwritten;
2663         }
2664     }
2665   else
2666 #endif /*HTTP_USE_GNUTLS*/
2667     {
2668       if ( write_server (c->sock->fd, buffer, size) )
2669         {
2670           gpg_err_set_errno (EIO);
2671           nwritten = -1;
2672         }
2673       else
2674         nwritten = size;
2675     }
2676
2677   return (gpgrt_ssize_t)nwritten;
2678 }
2679
2680
2681 #ifdef HTTP_USE_GNUTLS
2682 /* Wrapper for gnutls_bye used by my_socket_unref.  */
2683 static void
2684 send_gnutls_bye (void *opaque)
2685 {
2686   tls_session_t tls_session = opaque;
2687   int ret;
2688
2689  again:
2690   do
2691     ret = gnutls_bye (tls_session, GNUTLS_SHUT_RDWR);
2692   while (ret == GNUTLS_E_INTERRUPTED);
2693   if (ret == GNUTLS_E_AGAIN)
2694     {
2695       struct timeval tv;
2696
2697       tv.tv_sec = 0;
2698       tv.tv_usec = 50000;
2699       my_select (0, NULL, NULL, NULL, &tv);
2700       goto again;
2701     }
2702 }
2703 #endif /*HTTP_USE_GNUTLS*/
2704
2705 /* Close handler for estream.  */
2706 static int
2707 cookie_close (void *cookie)
2708 {
2709   cookie_t c = cookie;
2710
2711   if (!c)
2712     return 0;
2713
2714 #if HTTP_USE_NTBTLS
2715   if (c->use_tls && c->session && c->session->tls_session)
2716     {
2717       /* FIXME!! Possibly call ntbtls_close_notify for close
2718          of write stream.  */
2719       my_socket_unref (c->sock, NULL, NULL);
2720     }
2721   else
2722 #elif HTTP_USE_GNUTLS
2723   if (c->use_tls && c->session && c->session->tls_session)
2724     my_socket_unref (c->sock, send_gnutls_bye, c->session->tls_session);
2725   else
2726 #endif /*HTTP_USE_GNUTLS*/
2727     if (c->sock)
2728       my_socket_unref (c->sock, NULL, NULL);
2729
2730   if (c->session)
2731     http_session_unref (c->session);
2732   xfree (c);
2733   return 0;
2734 }
2735
2736
2737
2738 \f
2739 /* Verify the credentials of the server.  Returns 0 on success and
2740    store the result in the session object.  */
2741 gpg_error_t
2742 http_verify_server_credentials (http_session_t sess)
2743 {
2744 #if HTTP_USE_NTBTLS
2745   (void)sess;
2746   return 0;  /* FIXME!! */
2747 #elif HTTP_USE_GNUTLS
2748   static const char const errprefix[] = "TLS verification of peer failed";
2749   int rc;
2750   unsigned int status;
2751   const char *hostname;
2752   const gnutls_datum_t *certlist;
2753   unsigned int certlistlen;
2754   gnutls_x509_crt_t cert;
2755   gpg_error_t err = 0;
2756
2757   sess->verify.done = 1;
2758   sess->verify.status = 0;
2759   sess->verify.rc = GNUTLS_E_CERTIFICATE_ERROR;
2760
2761   if (gnutls_certificate_type_get (sess->tls_session) != GNUTLS_CRT_X509)
2762     {
2763       log_error ("%s: %s\n", errprefix, "not an X.509 certificate");
2764       sess->verify.rc = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
2765       return gpg_error (GPG_ERR_GENERAL);
2766     }
2767
2768   rc = gnutls_certificate_verify_peers2 (sess->tls_session, &status);
2769   if (rc)
2770     {
2771       log_error ("%s: %s\n", errprefix, gnutls_strerror (rc));
2772       if (!err)
2773         err = gpg_error (GPG_ERR_GENERAL);
2774     }
2775   else if (status)
2776     {
2777       log_error ("%s: status=0x%04x\n", errprefix, status);
2778 #if GNUTLS_VERSION_NUMBER >= 0x030104
2779       {
2780         gnutls_datum_t statusdat;
2781
2782         if (!gnutls_certificate_verification_status_print
2783             (status, GNUTLS_CRT_X509, &statusdat, 0))
2784           {
2785             log_info ("%s: %s\n", errprefix, statusdat.data);
2786             gnutls_free (statusdat.data);
2787           }
2788       }
2789 #endif /*gnutls >= 3.1.4*/
2790
2791       sess->verify.status = status;
2792       if (!err)
2793         err = gpg_error (GPG_ERR_GENERAL);
2794     }
2795
2796   hostname = sess->servername;
2797   if (!hostname || !strchr (hostname, '.'))
2798     {
2799       log_error ("%s: %s\n", errprefix, "hostname missing");
2800       if (!err)
2801         err = gpg_error (GPG_ERR_GENERAL);
2802     }
2803
2804   certlist = gnutls_certificate_get_peers (sess->tls_session, &certlistlen);
2805   if (!certlistlen)
2806     {
2807       log_error ("%s: %s\n", errprefix, "server did not send a certificate");
2808       if (!err)
2809         err = gpg_error (GPG_ERR_GENERAL);
2810
2811       /* Need to stop here.  */
2812       if (err)
2813         return err;
2814     }
2815
2816   rc = gnutls_x509_crt_init (&cert);
2817   if (rc < 0)
2818     {
2819       if (!err)
2820         err = gpg_error (GPG_ERR_GENERAL);
2821       if (err)
2822         return err;
2823     }
2824
2825   rc = gnutls_x509_crt_import (cert, &certlist[0], GNUTLS_X509_FMT_DER);
2826   if (rc < 0)
2827     {
2828       log_error ("%s: %s: %s\n", errprefix, "error importing certificate",
2829                  gnutls_strerror (rc));
2830       if (!err)
2831         err = gpg_error (GPG_ERR_GENERAL);
2832     }
2833
2834   if (!gnutls_x509_crt_check_hostname (cert, hostname))
2835     {
2836       log_error ("%s: %s\n", errprefix, "hostname does not match");
2837       if (!err)
2838         err = gpg_error (GPG_ERR_GENERAL);
2839     }
2840
2841   gnutls_x509_crt_deinit (cert);
2842
2843   if (!err)
2844     sess->verify.rc = 0;
2845
2846   if (sess->cert_log_cb)
2847     {
2848       const void *bufarr[10];
2849       size_t buflenarr[10];
2850       size_t n;
2851
2852       for (n = 0; n < certlistlen && n < DIM (bufarr)-1; n++)
2853         {
2854           bufarr[n] = certlist[n].data;
2855           buflenarr[n] = certlist[n].size;
2856         }
2857       bufarr[n] = NULL;
2858       buflenarr[n] = 0;
2859       sess->cert_log_cb (sess, err, hostname, bufarr, buflenarr);
2860     }
2861
2862   return err;
2863 #else /*!HTTP_USE_GNUTLS*/
2864   (void)sess;
2865   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2866 #endif
2867 }
2868
2869 /* Return the first query variable with the specified key.  If there
2870    is no such variable, return NULL.  */
2871 struct uri_tuple_s *
2872 uri_query_lookup (parsed_uri_t uri, const char *key)
2873 {
2874   struct uri_tuple_s *t;
2875
2876   for (t = uri->query; t; t = t->next)
2877     if (strcmp (t->name, key) == 0)
2878       return t;
2879
2880   return NULL;
2881 }