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