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