chiark / gitweb /
dirmngr: New option --no-use-tor and internal changes.
[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 gpg_error_t connect_server (const char *server, unsigned short port,
159                                    unsigned int flags, const char *srvtag,
160                                    assuan_fd_t *r_sock);
161 static gpg_error_t write_server (int sock, const char *data, size_t length);
162
163 static gpgrt_ssize_t cookie_read (void *cookie, void *buffer, size_t size);
164 static gpgrt_ssize_t cookie_write (void *cookie,
165                                    const void *buffer, size_t size);
166 static int cookie_close (void *cookie);
167
168
169 /* A socket object used to a allow ref counting of sockets.  */
170 struct my_socket_s
171 {
172   assuan_fd_t fd; /* The actual socket - shall never be ASSUAN_INVALID_FD.  */
173   int refcount;   /* Number of references to this socket.  */
174 };
175 typedef struct my_socket_s *my_socket_t;
176
177
178 /* Cookie function structure and cookie object.  */
179 static es_cookie_io_functions_t cookie_functions =
180   {
181     cookie_read,
182     cookie_write,
183     NULL,
184     cookie_close
185   };
186
187 struct cookie_s
188 {
189   /* Socket object or NULL if already closed. */
190   my_socket_t sock;
191
192   /* The session object or NULL if not used. */
193   http_session_t session;
194
195   /* True if TLS is to be used.  */
196   int use_tls;
197
198   /* The remaining content length and a flag telling whether to use
199      the content length.  */
200   uint64_t content_length;
201   unsigned int content_length_valid:1;
202 };
203 typedef struct cookie_s *cookie_t;
204
205 /* The session object. */
206 struct http_session_s
207 {
208   int refcount;    /* Number of references to this object.  */
209 #ifdef HTTP_USE_GNUTLS
210   gnutls_certificate_credentials_t certcred;
211 #endif /*HTTP_USE_GNUTLS*/
212 #ifdef USE_TLS
213   tls_session_t tls_session;
214   struct {
215     int done;      /* Verifciation has been done.  */
216     int rc;        /* TLS verification return code.  */
217     unsigned int status; /* Verification status.  */
218   } verify;
219   char *servername; /* Malloced server name.  */
220 #endif /*USE_TLS*/
221   /* A callback function to log details of TLS certifciates.  */
222   void (*cert_log_cb) (http_session_t, gpg_error_t, const char *,
223                        const void **, size_t *);
224 };
225
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
928   *r_hd = NULL;
929
930   if ((flags & HTTP_FLAG_FORCE_TOR))
931     {
932       int mode;
933
934       if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
935         {
936           log_error ("Tor support is not available\n");
937           return gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
938         }
939     }
940
941   /* Create the handle. */
942   hd = xtrycalloc (1, sizeof *hd);
943   if (!hd)
944     return gpg_error_from_syserror ();
945   hd->req_type = HTTP_REQ_OPAQUE;
946   hd->flags = flags;
947
948   /* Connect.  */
949   {
950     assuan_fd_t sock;
951
952     err = connect_server (server, port, hd->flags, srvtag, &sock);
953     if (err)
954       {
955         xfree (hd);
956         return err;
957       }
958     hd->sock = my_socket_new (sock);
959     if (!hd->sock)
960       {
961         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
962         xfree (hd);
963         return err;
964       }
965   }
966
967   /* Setup estreams for reading and writing.  */
968   cookie = xtrycalloc (1, sizeof *cookie);
969   if (!cookie)
970     {
971       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
972       goto leave;
973     }
974   cookie->sock = my_socket_ref (hd->sock);
975   hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
976   if (!hd->fp_write)
977     {
978       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
979       my_socket_unref (cookie->sock, NULL, NULL);
980       xfree (cookie);
981       goto leave;
982     }
983   hd->write_cookie = cookie; /* Cookie now owned by FP_WRITE.  */
984
985   cookie = xtrycalloc (1, sizeof *cookie);
986   if (!cookie)
987     {
988       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
989       goto leave;
990     }
991   cookie->sock = my_socket_ref (hd->sock);
992   hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
993   if (!hd->fp_read)
994     {
995       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
996       my_socket_unref (cookie->sock, NULL, NULL);
997       xfree (cookie);
998       goto leave;
999     }
1000   hd->read_cookie = cookie; /* Cookie now owned by FP_READ.  */
1001
1002   /* Register close notification to interlock the use of es_fclose in
1003      http_close and in user code.  */
1004   err = es_onclose (hd->fp_write, 1, fp_onclose_notification, hd);
1005   if (!err)
1006     err = es_onclose (hd->fp_read, 1, fp_onclose_notification, hd);
1007
1008  leave:
1009   if (err)
1010     {
1011       if (hd->fp_read)
1012         es_fclose (hd->fp_read);
1013       if (hd->fp_write)
1014         es_fclose (hd->fp_write);
1015       my_socket_unref (hd->sock, NULL, NULL);
1016       xfree (hd);
1017     }
1018   else
1019     *r_hd = hd;
1020   return err;
1021 }
1022
1023
1024
1025
1026 void
1027 http_start_data (http_t hd)
1028 {
1029   if (!hd->in_data)
1030     {
1031       if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
1032         log_debug_with_string ("\r\n", "http.c:request-header:");
1033       es_fputs ("\r\n", hd->fp_write);
1034       es_fflush (hd->fp_write);
1035       hd->in_data = 1;
1036     }
1037   else
1038     es_fflush (hd->fp_write);
1039 }
1040
1041
1042 gpg_error_t
1043 http_wait_response (http_t hd)
1044 {
1045   gpg_error_t err;
1046   cookie_t cookie;
1047
1048   /* Make sure that we are in the data. */
1049   http_start_data (hd);
1050
1051   /* Close the write stream.  Note that the reference counted socket
1052      object keeps the actual system socket open.  */
1053   cookie = hd->write_cookie;
1054   if (!cookie)
1055     return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1056
1057   es_fclose (hd->fp_write);
1058   hd->fp_write = NULL;
1059   /* The close has released the cookie and thus we better set it to NULL.  */
1060   hd->write_cookie = NULL;
1061
1062   /* Shutdown one end of the socket is desired.  As per HTTP/1.0 this
1063      is not required but some very old servers (e.g. the original pksd
1064      keyserver didn't worked without it.  */
1065   if ((hd->flags & HTTP_FLAG_SHUTDOWN))
1066     shutdown (hd->sock->fd, 1);
1067   hd->in_data = 0;
1068
1069   /* Create a new cookie and a stream for reading.  */
1070   cookie = xtrycalloc (1, sizeof *cookie);
1071   if (!cookie)
1072     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1073   cookie->sock = my_socket_ref (hd->sock);
1074   cookie->session = http_session_ref (hd->session);
1075   cookie->use_tls = hd->uri->use_tls;
1076
1077   hd->read_cookie = cookie;
1078   hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
1079   if (!hd->fp_read)
1080     {
1081       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1082       my_socket_unref (cookie->sock, NULL, NULL);
1083       http_session_unref (cookie->session);
1084       xfree (cookie);
1085       hd->read_cookie = NULL;
1086       return err;
1087     }
1088
1089   err = parse_response (hd);
1090
1091   if (!err)
1092     err = es_onclose (hd->fp_read, 1, fp_onclose_notification, hd);
1093
1094   return err;
1095 }
1096
1097
1098 /* Convenience function to send a request and wait for the response.
1099    Closes the handle on error.  If PROXY is not NULL, this value will
1100    be used as an HTTP proxy and any enabled $http_proxy gets
1101    ignored. */
1102 gpg_error_t
1103 http_open_document (http_t *r_hd, const char *document,
1104                     const char *auth, unsigned int flags, const char *proxy,
1105                     http_session_t session,
1106                     const char *srvtag, strlist_t headers)
1107 {
1108   gpg_error_t err;
1109
1110   err = http_open (r_hd, HTTP_REQ_GET, document, NULL, auth, flags,
1111                    proxy, session, srvtag, headers);
1112   if (err)
1113     return err;
1114
1115   err = http_wait_response (*r_hd);
1116   if (err)
1117     http_close (*r_hd, 0);
1118
1119   return err;
1120 }
1121
1122
1123 void
1124 http_close (http_t hd, int keep_read_stream)
1125 {
1126   if (!hd)
1127     return;
1128
1129   /* First remove the close notifications for the streams.  */
1130   if (hd->fp_read)
1131     es_onclose (hd->fp_read, 0, fp_onclose_notification, hd);
1132   if (hd->fp_write)
1133     es_onclose (hd->fp_write, 0, fp_onclose_notification, hd);
1134
1135   /* Now we can close the streams.  */
1136   my_socket_unref (hd->sock, NULL, NULL);
1137   if (hd->fp_read && !keep_read_stream)
1138     es_fclose (hd->fp_read);
1139   if (hd->fp_write)
1140     es_fclose (hd->fp_write);
1141   http_session_unref (hd->session);
1142   http_release_parsed_uri (hd->uri);
1143   while (hd->headers)
1144     {
1145       header_t tmp = hd->headers->next;
1146       xfree (hd->headers->value);
1147       xfree (hd->headers);
1148       hd->headers = tmp;
1149     }
1150   xfree (hd->buffer);
1151   xfree (hd);
1152 }
1153
1154
1155 estream_t
1156 http_get_read_ptr (http_t hd)
1157 {
1158   return hd?hd->fp_read:NULL;
1159 }
1160
1161 estream_t
1162 http_get_write_ptr (http_t hd)
1163 {
1164   return hd?hd->fp_write:NULL;
1165 }
1166
1167 unsigned int
1168 http_get_status_code (http_t hd)
1169 {
1170   return hd?hd->status_code:0;
1171 }
1172
1173 /* Return information pertaining to TLS.  If TLS is not in use for HD,
1174    NULL is returned.  WHAT is used ask for specific information:
1175
1176      (NULL) := Only check whether TLS is is use.  Returns an
1177                unspecified string if TLS is in use.  That string may
1178                even be the empty string.
1179  */
1180 const char *
1181 http_get_tls_info (http_t hd, const char *what)
1182 {
1183   (void)what;
1184
1185   if (!hd)
1186     return NULL;
1187
1188   return hd->uri->use_tls? "":NULL;
1189 }
1190
1191
1192 \f
1193 static gpg_error_t
1194 parse_uri (parsed_uri_t *ret_uri, const char *uri,
1195            int no_scheme_check, int force_tls)
1196 {
1197   gpg_err_code_t ec;
1198
1199   *ret_uri = xtrycalloc (1, sizeof **ret_uri + strlen (uri));
1200   if (!*ret_uri)
1201     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1202   strcpy ((*ret_uri)->buffer, uri);
1203   ec = do_parse_uri (*ret_uri, 0, no_scheme_check, force_tls);
1204   if (ec)
1205     {
1206       xfree (*ret_uri);
1207       *ret_uri = NULL;
1208     }
1209   return gpg_err_make (default_errsource, ec);
1210 }
1211
1212
1213 /*
1214  * Parse an URI and put the result into the newly allocated RET_URI.
1215  * On success the caller must use http_release_parsed_uri() to
1216  * releases the resources.  If NO_SCHEME_CHECK is set, the function
1217  * tries to parse the URL in the same way it would do for an HTTP
1218  * style URI.
1219  */
1220 gpg_error_t
1221 http_parse_uri (parsed_uri_t *ret_uri, const char *uri,
1222                 int no_scheme_check)
1223 {
1224   return parse_uri (ret_uri, uri, no_scheme_check, 0);
1225 }
1226
1227
1228 void
1229 http_release_parsed_uri (parsed_uri_t uri)
1230 {
1231   if (uri)
1232     {
1233       uri_tuple_t r, r2;
1234
1235       for (r = uri->query; r; r = r2)
1236         {
1237           r2 = r->next;
1238           xfree (r);
1239         }
1240       xfree (uri);
1241     }
1242 }
1243
1244
1245 static gpg_err_code_t
1246 do_parse_uri (parsed_uri_t uri, int only_local_part,
1247               int no_scheme_check, int force_tls)
1248 {
1249   uri_tuple_t *tail;
1250   char *p, *p2, *p3, *pp;
1251   int n;
1252
1253   p = uri->buffer;
1254   n = strlen (uri->buffer);
1255
1256   /* Initialize all fields to an empty string or an empty list. */
1257   uri->scheme = uri->host = uri->path = p + n;
1258   uri->port = 0;
1259   uri->params = uri->query = NULL;
1260   uri->use_tls = 0;
1261   uri->is_http = 0;
1262   uri->opaque = 0;
1263   uri->v6lit = 0;
1264   uri->onion = 0;
1265   uri->explicit_port = 0;
1266
1267   /* A quick validity check. */
1268   if (strspn (p, VALID_URI_CHARS) != n)
1269     return GPG_ERR_BAD_URI;     /* Invalid characters found. */
1270
1271   if (!only_local_part)
1272     {
1273       /* Find the scheme. */
1274       if (!(p2 = strchr (p, ':')) || p2 == p)
1275         return GPG_ERR_BAD_URI; /* No scheme. */
1276       *p2++ = 0;
1277       for (pp=p; *pp; pp++)
1278        *pp = tolower (*(unsigned char*)pp);
1279       uri->scheme = p;
1280       if (!strcmp (uri->scheme, "http") && !force_tls)
1281         {
1282           uri->port = 80;
1283           uri->is_http = 1;
1284         }
1285       else if (!strcmp (uri->scheme, "hkp") && !force_tls)
1286         {
1287           uri->port = 11371;
1288           uri->is_http = 1;
1289         }
1290 #ifdef USE_TLS
1291       else if (!strcmp (uri->scheme, "https") || !strcmp (uri->scheme,"hkps")
1292                || (force_tls && (!strcmp (uri->scheme, "http")
1293                                  || !strcmp (uri->scheme,"hkp"))))
1294         {
1295           uri->port = 443;
1296           uri->is_http = 1;
1297           uri->use_tls = 1;
1298         }
1299 #endif /*USE_TLS*/
1300       else if (!no_scheme_check)
1301         return GPG_ERR_INV_URI; /* Unsupported scheme */
1302
1303       p = p2;
1304
1305       if (*p == '/' && p[1] == '/' ) /* There seems to be a hostname. */
1306         {
1307           p += 2;
1308           if ((p2 = strchr (p, '/')))
1309             *p2++ = 0;
1310
1311           /* Check for username/password encoding */
1312           if ((p3 = strchr (p, '@')))
1313             {
1314               uri->auth = p;
1315               *p3++ = '\0';
1316               p = p3;
1317             }
1318
1319           for (pp=p; *pp; pp++)
1320             *pp = tolower (*(unsigned char*)pp);
1321
1322           /* Handle an IPv6 literal */
1323           if( *p == '[' && (p3=strchr( p, ']' )) )
1324             {
1325               *p3++ = '\0';
1326               /* worst case, uri->host should have length 0, points to \0 */
1327               uri->host = p + 1;
1328               uri->v6lit = 1;
1329               p = p3;
1330             }
1331           else
1332             uri->host = p;
1333
1334           if ((p3 = strchr (p, ':')))
1335             {
1336               *p3++ = '\0';
1337               uri->port = atoi (p3);
1338               uri->explicit_port = 1;
1339             }
1340
1341           if ((n = remove_escapes (uri->host)) < 0)
1342             return GPG_ERR_BAD_URI;
1343           if (n != strlen (uri->host))
1344             return GPG_ERR_BAD_URI;     /* Hostname incudes a Nul. */
1345           p = p2 ? p2 : NULL;
1346         }
1347       else if (uri->is_http)
1348         return GPG_ERR_INV_URI; /* No Leading double slash for HTTP.  */
1349       else
1350         {
1351           uri->opaque = 1;
1352           uri->path = p;
1353           if (is_onion_address (uri->path))
1354             uri->onion = 1;
1355           return 0;
1356         }
1357
1358     } /* End global URI part. */
1359
1360   /* Parse the pathname part if any.  */
1361   if (p && *p)
1362     {
1363       /* TODO: Here we have to check params. */
1364
1365       /* Do we have a query part? */
1366       if ((p2 = strchr (p, '?')))
1367         *p2++ = 0;
1368
1369       uri->path = p;
1370       if ((n = remove_escapes (p)) < 0)
1371         return GPG_ERR_BAD_URI;
1372       if (n != strlen (p))
1373         return GPG_ERR_BAD_URI; /* Path includes a Nul. */
1374       p = p2 ? p2 : NULL;
1375
1376       /* Parse a query string if any.  */
1377       if (p && *p)
1378         {
1379           tail = &uri->query;
1380           for (;;)
1381             {
1382               uri_tuple_t elem;
1383
1384               if ((p2 = strchr (p, '&')))
1385                 *p2++ = 0;
1386               if (!(elem = parse_tuple (p)))
1387                 return GPG_ERR_BAD_URI;
1388               *tail = elem;
1389               tail = &elem->next;
1390
1391               if (!p2)
1392                 break; /* Ready. */
1393               p = p2;
1394             }
1395         }
1396     }
1397
1398   if (is_onion_address (uri->host))
1399     uri->onion = 1;
1400
1401   return 0;
1402 }
1403
1404
1405 /*
1406  * Remove all %xx escapes; this is done in-place.  Returns: New length
1407  * of the string.
1408  */
1409 static int
1410 remove_escapes (char *string)
1411 {
1412   int n = 0;
1413   unsigned char *p, *s;
1414
1415   for (p = s = (unsigned char*)string; *s; s++)
1416     {
1417       if (*s == '%')
1418         {
1419           if (s[1] && s[2] && isxdigit (s[1]) && isxdigit (s[2]))
1420             {
1421               s++;
1422               *p = *s >= '0' && *s <= '9' ? *s - '0' :
1423                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
1424               *p <<= 4;
1425               s++;
1426               *p |= *s >= '0' && *s <= '9' ? *s - '0' :
1427                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
1428               p++;
1429               n++;
1430             }
1431           else
1432             {
1433               *p++ = *s++;
1434               if (*s)
1435                 *p++ = *s++;
1436               if (*s)
1437                 *p++ = *s++;
1438               if (*s)
1439                 *p = 0;
1440               return -1; /* Bad URI. */
1441             }
1442         }
1443       else
1444         {
1445           *p++ = *s;
1446           n++;
1447         }
1448     }
1449   *p = 0; /* Make sure to keep a string terminator. */
1450   return n;
1451 }
1452
1453
1454 /* If SPECIAL is NULL this function escapes in forms mode.  */
1455 static size_t
1456 escape_data (char *buffer, const void *data, size_t datalen,
1457              const char *special)
1458 {
1459   int forms = !special;
1460   const unsigned char *s;
1461   size_t n = 0;
1462
1463   if (forms)
1464     special = "%;?&=";
1465
1466   for (s = data; datalen; s++, datalen--)
1467     {
1468       if (forms && *s == ' ')
1469         {
1470           if (buffer)
1471             *buffer++ = '+';
1472           n++;
1473         }
1474       else if (forms && *s == '\n')
1475         {
1476           if (buffer)
1477             memcpy (buffer, "%0D%0A", 6);
1478           n += 6;
1479         }
1480       else if (forms && *s == '\r' && datalen > 1 && s[1] == '\n')
1481         {
1482           if (buffer)
1483             memcpy (buffer, "%0D%0A", 6);
1484           n += 6;
1485           s++;
1486           datalen--;
1487         }
1488       else if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
1489         {
1490           if (buffer)
1491             *(unsigned char*)buffer++ = *s;
1492           n++;
1493         }
1494       else
1495         {
1496           if (buffer)
1497             {
1498               snprintf (buffer, 4, "%%%02X", *s);
1499               buffer += 3;
1500             }
1501           n += 3;
1502         }
1503     }
1504   return n;
1505 }
1506
1507
1508 static int
1509 insert_escapes (char *buffer, const char *string,
1510                 const char *special)
1511 {
1512   return escape_data (buffer, string, strlen (string), special);
1513 }
1514
1515
1516 /* Allocate a new string from STRING using standard HTTP escaping as
1517    well as escaping of characters given in SPECIALS.  A common pattern
1518    for SPECIALS is "%;?&=". However it depends on the needs, for
1519    example "+" and "/: often needs to be escaped too.  Returns NULL on
1520    failure and sets ERRNO.  If SPECIAL is NULL a dedicated forms
1521    encoding mode is used. */
1522 char *
1523 http_escape_string (const char *string, const char *specials)
1524 {
1525   int n;
1526   char *buf;
1527
1528   n = insert_escapes (NULL, string, specials);
1529   buf = xtrymalloc (n+1);
1530   if (buf)
1531     {
1532       insert_escapes (buf, string, specials);
1533       buf[n] = 0;
1534     }
1535   return buf;
1536 }
1537
1538 /* Allocate a new string from {DATA,DATALEN} using standard HTTP
1539    escaping as well as escaping of characters given in SPECIALS.  A
1540    common pattern for SPECIALS is "%;?&=".  However it depends on the
1541    needs, for example "+" and "/: often needs to be escaped too.
1542    Returns NULL on failure and sets ERRNO.  If SPECIAL is NULL a
1543    dedicated forms encoding mode is used. */
1544 char *
1545 http_escape_data (const void *data, size_t datalen, const char *specials)
1546 {
1547   int n;
1548   char *buf;
1549
1550   n = escape_data (NULL, data, datalen, specials);
1551   buf = xtrymalloc (n+1);
1552   if (buf)
1553     {
1554       escape_data (buf, data, datalen, specials);
1555       buf[n] = 0;
1556     }
1557   return buf;
1558 }
1559
1560
1561 static uri_tuple_t
1562 parse_tuple (char *string)
1563 {
1564   char *p = string;
1565   char *p2;
1566   int n;
1567   uri_tuple_t tuple;
1568
1569   if ((p2 = strchr (p, '=')))
1570     *p2++ = 0;
1571   if ((n = remove_escapes (p)) < 0)
1572     return NULL; /* Bad URI. */
1573   if (n != strlen (p))
1574     return NULL; /* Name with a Nul in it. */
1575   tuple = xtrycalloc (1, sizeof *tuple);
1576   if (!tuple)
1577     return NULL; /* Out of core. */
1578   tuple->name = p;
1579   if (!p2) /* We have only the name, so we assume an empty value string. */
1580     {
1581       tuple->value = p + strlen (p);
1582       tuple->valuelen = 0;
1583       tuple->no_value = 1; /* Explicitly mark that we have seen no '='. */
1584     }
1585   else /* Name and value. */
1586     {
1587       if ((n = remove_escapes (p2)) < 0)
1588         {
1589           xfree (tuple);
1590           return NULL; /* Bad URI. */
1591         }
1592       tuple->value = p2;
1593       tuple->valuelen = n;
1594     }
1595   return tuple;
1596 }
1597
1598
1599 /* Return true if STRING is likely "hostname:port" or only "hostname".  */
1600 static int
1601 is_hostname_port (const char *string)
1602 {
1603   int colons = 0;
1604
1605   if (!string || !*string)
1606     return 0;
1607   for (; *string; string++)
1608     {
1609       if (*string == ':')
1610         {
1611           if (colons)
1612             return 0;
1613           if (!string[1])
1614             return 0;
1615           colons++;
1616         }
1617       else if (!colons && strchr (" \t\f\n\v_@[]/", *string))
1618         return 0; /* Invalid characters in hostname. */
1619       else if (colons && !digitp (string))
1620         return 0; /* Not a digit in the port.  */
1621     }
1622   return 1;
1623 }
1624
1625
1626 /*
1627  * Send a HTTP request to the server
1628  * Returns 0 if the request was successful
1629  */
1630 static gpg_error_t
1631 send_request (http_t hd, const char *httphost, const char *auth,
1632               const char *proxy, const char *srvtag, strlist_t headers)
1633 {
1634   gpg_error_t err;
1635   const char *server;
1636   char *request, *p;
1637   unsigned short port;
1638   const char *http_proxy = NULL;
1639   char *proxy_authstr = NULL;
1640   char *authstr = NULL;
1641   int sock;
1642
1643   if (hd->uri->use_tls && !hd->session)
1644     {
1645       log_error ("TLS requested but no session object provided\n");
1646       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1647     }
1648 #ifdef USE_TLS
1649   if (hd->uri->use_tls && !hd->session->tls_session)
1650     {
1651       log_error ("TLS requested but no GNUTLS context available\n");
1652       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1653     }
1654 #endif /*USE_TLS*/
1655
1656   if ((hd->flags & HTTP_FLAG_FORCE_TOR))
1657     {
1658       int mode;
1659
1660       if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
1661         {
1662           log_error ("Tor support is not available\n");
1663           return gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1664         }
1665     }
1666
1667   server = *hd->uri->host ? hd->uri->host : "localhost";
1668   port = hd->uri->port ? hd->uri->port : 80;
1669
1670   /* Try to use SNI.  */
1671 #ifdef USE_TLS
1672   if (hd->uri->use_tls)
1673     {
1674 # if HTTP_USE_GNUTLS
1675       int rc;
1676 # endif
1677
1678       xfree (hd->session->servername);
1679       hd->session->servername = xtrystrdup (httphost? httphost : server);
1680       if (!hd->session->servername)
1681         {
1682           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1683           return err;
1684         }
1685
1686 # if HTTP_USE_NTBTLS
1687       err = ntbtls_set_hostname (hd->session->tls_session,
1688                                  hd->session->servername);
1689       if (err)
1690         {
1691           log_info ("ntbtls_set_hostname failed: %s\n", gpg_strerror (err));
1692           return err;
1693         }
1694 # elif HTTP_USE_GNUTLS
1695       rc = gnutls_server_name_set (hd->session->tls_session,
1696                                    GNUTLS_NAME_DNS,
1697                                    hd->session->servername,
1698                                    strlen (hd->session->servername));
1699       if (rc < 0)
1700         log_info ("gnutls_server_name_set failed: %s\n", gnutls_strerror (rc));
1701 # endif /*HTTP_USE_GNUTLS*/
1702     }
1703 #endif /*USE_TLS*/
1704
1705   if ( (proxy && *proxy)
1706        || ( (hd->flags & HTTP_FLAG_TRY_PROXY)
1707             && (http_proxy = getenv (HTTP_PROXY_ENV))
1708             && *http_proxy ))
1709     {
1710       parsed_uri_t uri;
1711
1712       if (proxy)
1713         http_proxy = proxy;
1714
1715       err = parse_uri (&uri, http_proxy, 0, 0);
1716       if (gpg_err_code (err) == GPG_ERR_INV_URI
1717           && is_hostname_port (http_proxy))
1718         {
1719           /* Retry assuming a "hostname:port" string.  */
1720           char *tmpname = strconcat ("http://", http_proxy, NULL);
1721           if (tmpname && !parse_uri (&uri, tmpname, 0, 0))
1722             err = 0;
1723           xfree (tmpname);
1724         }
1725
1726       if (err)
1727         ;
1728       else if (!strcmp (uri->scheme, "http") || !strcmp (uri->scheme, "socks4"))
1729         ;
1730       else if (!strcmp (uri->scheme, "socks5h"))
1731         err = gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1732       else
1733         err = gpg_err_make (default_errsource, GPG_ERR_INV_URI);
1734
1735       if (err)
1736         {
1737           log_error ("invalid HTTP proxy (%s): %s\n",
1738                      http_proxy, gpg_strerror (err));
1739           return gpg_err_make (default_errsource, GPG_ERR_CONFIGURATION);
1740         }
1741
1742       if (uri->auth)
1743         {
1744           remove_escapes (uri->auth);
1745           proxy_authstr = make_header_line ("Proxy-Authorization: Basic ",
1746                                             "\r\n",
1747                                             uri->auth, strlen(uri->auth));
1748           if (!proxy_authstr)
1749             {
1750               err = gpg_err_make (default_errsource,
1751                                   gpg_err_code_from_syserror ());
1752               http_release_parsed_uri (uri);
1753               return err;
1754             }
1755         }
1756
1757       err = connect_server (*uri->host ? uri->host : "localhost",
1758                             uri->port ? uri->port : 80,
1759                             hd->flags, srvtag, &sock);
1760       http_release_parsed_uri (uri);
1761     }
1762   else
1763     {
1764       err = connect_server (server, port, hd->flags, srvtag, &sock);
1765     }
1766
1767   if (err)
1768     {
1769       xfree (proxy_authstr);
1770       return err;
1771     }
1772   hd->sock = my_socket_new (sock);
1773   if (!hd->sock)
1774     {
1775       xfree (proxy_authstr);
1776       return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1777     }
1778
1779
1780 #if HTTP_USE_NTBTLS
1781   if (hd->uri->use_tls)
1782     {
1783       estream_t in, out;
1784
1785       my_socket_ref (hd->sock);
1786
1787       in = es_fdopen_nc (hd->sock->fd, "rb");
1788       if (!in)
1789         {
1790           err = gpg_error_from_syserror ();
1791           xfree (proxy_authstr);
1792           return err;
1793         }
1794
1795       out = es_fdopen_nc (hd->sock->fd, "wb");
1796       if (!out)
1797         {
1798           err = gpg_error_from_syserror ();
1799           es_fclose (in);
1800           xfree (proxy_authstr);
1801           return err;
1802         }
1803
1804       err = ntbtls_set_transport (hd->session->tls_session, in, out);
1805       if (err)
1806         {
1807           log_info ("TLS set_transport failed: %s <%s>\n",
1808                     gpg_strerror (err), gpg_strsource (err));
1809           xfree (proxy_authstr);
1810           return err;
1811         }
1812
1813       while ((err = ntbtls_handshake (hd->session->tls_session)))
1814         {
1815           switch (err)
1816             {
1817             default:
1818               log_info ("TLS handshake failed: %s <%s>\n",
1819                         gpg_strerror (err), gpg_strsource (err));
1820               xfree (proxy_authstr);
1821               return err;
1822             }
1823         }
1824
1825       hd->session->verify.done = 0;
1826       if (tls_callback)
1827         err = tls_callback (hd, hd->session, 0);
1828       else
1829         err = http_verify_server_credentials (hd->session);
1830       if (err)
1831         {
1832           log_info ("TLS connection authentication failed: %s <%s>\n",
1833                     gpg_strerror (err), gpg_strsource (err));
1834           xfree (proxy_authstr);
1835           return err;
1836         }
1837     }
1838 #elif HTTP_USE_GNUTLS
1839   if (hd->uri->use_tls)
1840     {
1841       int rc;
1842
1843       my_socket_ref (hd->sock);
1844       gnutls_transport_set_ptr (hd->session->tls_session, hd->sock);
1845       gnutls_transport_set_pull_function (hd->session->tls_session,
1846                                           my_gnutls_read);
1847       gnutls_transport_set_push_function (hd->session->tls_session,
1848                                           my_gnutls_write);
1849
1850       do
1851         {
1852           rc = gnutls_handshake (hd->session->tls_session);
1853         }
1854       while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
1855       if (rc < 0)
1856         {
1857           if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED
1858               || rc == GNUTLS_E_FATAL_ALERT_RECEIVED)
1859             {
1860               gnutls_alert_description_t alertno;
1861               const char *alertstr;
1862
1863               alertno = gnutls_alert_get (hd->session->tls_session);
1864               alertstr = gnutls_alert_get_name (alertno);
1865               log_info ("TLS handshake failed: %s (alert %d)\n",
1866                         alertstr, (int)alertno);
1867               if (alertno == GNUTLS_A_UNRECOGNIZED_NAME && server)
1868                 log_info ("  (sent server name '%s')\n", server);
1869             }
1870           else
1871             log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
1872           xfree (proxy_authstr);
1873           return gpg_err_make (default_errsource, GPG_ERR_NETWORK);
1874         }
1875
1876       hd->session->verify.done = 0;
1877       if (tls_callback)
1878         err = tls_callback (hd, hd->session, 0);
1879       else
1880         err = http_verify_server_credentials (hd->session);
1881       if (err)
1882         {
1883           log_info ("TLS connection authentication failed: %s\n",
1884                     gpg_strerror (err));
1885           xfree (proxy_authstr);
1886           return err;
1887         }
1888     }
1889 #endif /*HTTP_USE_GNUTLS*/
1890
1891   if (auth || hd->uri->auth)
1892     {
1893       char *myauth;
1894
1895       if (auth)
1896         {
1897           myauth = xtrystrdup (auth);
1898           if (!myauth)
1899             {
1900               xfree (proxy_authstr);
1901               return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1902             }
1903           remove_escapes (myauth);
1904         }
1905       else
1906         {
1907           remove_escapes (hd->uri->auth);
1908           myauth = hd->uri->auth;
1909         }
1910
1911       authstr = make_header_line ("Authorization: Basic ", "\r\n",
1912                                   myauth, strlen (myauth));
1913       if (auth)
1914         xfree (myauth);
1915
1916       if (!authstr)
1917         {
1918           xfree (proxy_authstr);
1919           return gpg_err_make (default_errsource,
1920                                gpg_err_code_from_syserror ());
1921         }
1922     }
1923
1924   p = build_rel_path (hd->uri);
1925   if (!p)
1926     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1927
1928   if (http_proxy && *http_proxy)
1929     {
1930       request = es_bsprintf
1931         ("%s %s://%s:%hu%s%s HTTP/1.0\r\n%s%s",
1932          hd->req_type == HTTP_REQ_GET ? "GET" :
1933          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
1934          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
1935          hd->uri->use_tls? "https" : "http",
1936          httphost? httphost : server,
1937          port, *p == '/' ? "" : "/", p,
1938          authstr ? authstr : "",
1939          proxy_authstr ? proxy_authstr : "");
1940     }
1941   else
1942     {
1943       char portstr[35];
1944
1945       if (port == 80)
1946         *portstr = 0;
1947       else
1948         snprintf (portstr, sizeof portstr, ":%u", port);
1949
1950       request = es_bsprintf
1951         ("%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
1952          hd->req_type == HTTP_REQ_GET ? "GET" :
1953          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
1954          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
1955          *p == '/' ? "" : "/", p,
1956          httphost? httphost : server,
1957          portstr,
1958          authstr? authstr:"");
1959     }
1960   xfree (p);
1961   if (!request)
1962     {
1963       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1964       xfree (authstr);
1965       xfree (proxy_authstr);
1966       return err;
1967     }
1968
1969   if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
1970     log_debug_with_string (request, "http.c:request:");
1971
1972   /* First setup estream so that we can write even the first line
1973      using estream.  This is also required for the sake of gnutls. */
1974   {
1975     cookie_t cookie;
1976
1977     cookie = xtrycalloc (1, sizeof *cookie);
1978     if (!cookie)
1979       {
1980         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1981         goto leave;
1982       }
1983     cookie->sock = my_socket_ref (hd->sock);
1984     hd->write_cookie = cookie;
1985     cookie->use_tls = hd->uri->use_tls;
1986     cookie->session = http_session_ref (hd->session);
1987
1988     hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1989     if (!hd->fp_write)
1990       {
1991         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1992         my_socket_unref (cookie->sock, NULL, NULL);
1993         xfree (cookie);
1994         hd->write_cookie = NULL;
1995       }
1996     else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
1997       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1998     else
1999       err = 0;
2000
2001   if (!err)
2002     {
2003       for (;headers; headers=headers->next)
2004         {
2005           if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
2006             log_debug_with_string (headers->d, "http.c:request-header:");
2007           if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write))
2008               || (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write)))
2009             {
2010               err = gpg_err_make (default_errsource,
2011                                   gpg_err_code_from_syserror ());
2012               break;
2013             }
2014         }
2015     }
2016   }
2017
2018  leave:
2019   es_free (request);
2020   xfree (authstr);
2021   xfree (proxy_authstr);
2022
2023   return err;
2024 }
2025
2026
2027 /*
2028  * Build the relative path from the parsed URI.  Minimal
2029  * implementation.  May return NULL in case of memory failure; errno
2030  * is then set accordingly.
2031  */
2032 static char *
2033 build_rel_path (parsed_uri_t uri)
2034 {
2035   uri_tuple_t r;
2036   char *rel_path, *p;
2037   int n;
2038
2039   /* Count the needed space. */
2040   n = insert_escapes (NULL, uri->path, "%;?&");
2041   /* TODO: build params. */
2042   for (r = uri->query; r; r = r->next)
2043     {
2044       n++; /* '?'/'&' */
2045       n += insert_escapes (NULL, r->name, "%;?&=");
2046       if (!r->no_value)
2047         {
2048           n++; /* '=' */
2049           n += insert_escapes (NULL, r->value, "%;?&=");
2050         }
2051     }
2052   n++;
2053
2054   /* Now allocate and copy. */
2055   p = rel_path = xtrymalloc (n);
2056   if (!p)
2057     return NULL;
2058   n = insert_escapes (p, uri->path, "%;?&");
2059   p += n;
2060   /* TODO: add params. */
2061   for (r = uri->query; r; r = r->next)
2062     {
2063       *p++ = r == uri->query ? '?' : '&';
2064       n = insert_escapes (p, r->name, "%;?&=");
2065       p += n;
2066       if (!r->no_value)
2067         {
2068           *p++ = '=';
2069           /* TODO: Use valuelen. */
2070           n = insert_escapes (p, r->value, "%;?&=");
2071           p += n;
2072         }
2073     }
2074   *p = 0;
2075   return rel_path;
2076 }
2077
2078
2079 /* Transform a header name into a standard capitalized format; e.g.
2080    "Content-Type".  Conversion stops at the colon.  As usual we don't
2081    use the localized versions of ctype.h. */
2082 static void
2083 capitalize_header_name (char *name)
2084 {
2085   int first = 1;
2086
2087   for (; *name && *name != ':'; name++)
2088     {
2089       if (*name == '-')
2090         first = 1;
2091       else if (first)
2092         {
2093           if (*name >= 'a' && *name <= 'z')
2094             *name = *name - 'a' + 'A';
2095           first = 0;
2096         }
2097       else if (*name >= 'A' && *name <= 'Z')
2098         *name = *name - 'A' + 'a';
2099     }
2100 }
2101
2102
2103 /* Store an HTTP header line in LINE away.  Line continuation is
2104    supported as well as merging of headers with the same name. This
2105    function may modify LINE. */
2106 static gpg_err_code_t
2107 store_header (http_t hd, char *line)
2108 {
2109   size_t n;
2110   char *p, *value;
2111   header_t h;
2112
2113   n = strlen (line);
2114   if (n && line[n-1] == '\n')
2115     {
2116       line[--n] = 0;
2117       if (n && line[n-1] == '\r')
2118         line[--n] = 0;
2119     }
2120   if (!n)  /* we are never called to hit this. */
2121     return GPG_ERR_BUG;
2122   if (*line == ' ' || *line == '\t')
2123     {
2124       /* Continuation. This won't happen too often as it is not
2125          recommended.  We use a straightforward implementaion. */
2126       if (!hd->headers)
2127         return GPG_ERR_PROTOCOL_VIOLATION;
2128       n += strlen (hd->headers->value);
2129       p = xtrymalloc (n+1);
2130       if (!p)
2131         return gpg_err_code_from_syserror ();
2132       strcpy (stpcpy (p, hd->headers->value), line);
2133       xfree (hd->headers->value);
2134       hd->headers->value = p;
2135       return 0;
2136     }
2137
2138   capitalize_header_name (line);
2139   p = strchr (line, ':');
2140   if (!p)
2141     return GPG_ERR_PROTOCOL_VIOLATION;
2142   *p++ = 0;
2143   while (*p == ' ' || *p == '\t')
2144     p++;
2145   value = p;
2146
2147   for (h=hd->headers; h; h = h->next)
2148     if ( !strcmp (h->name, line) )
2149       break;
2150   if (h)
2151     {
2152       /* We have already seen a line with that name.  Thus we assume
2153          it is a comma separated list and merge them.  */
2154       p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1);
2155       if (!p)
2156         return gpg_err_code_from_syserror ();
2157       strcpy (stpcpy (stpcpy (p, h->value), ","), value);
2158       xfree (h->value);
2159       h->value = p;
2160       return 0;
2161     }
2162
2163   /* Append a new header. */
2164   h = xtrymalloc (sizeof *h + strlen (line));
2165   if (!h)
2166     return gpg_err_code_from_syserror ();
2167   strcpy (h->name, line);
2168   h->value = xtrymalloc (strlen (value)+1);
2169   if (!h->value)
2170     {
2171       xfree (h);
2172       return gpg_err_code_from_syserror ();
2173     }
2174   strcpy (h->value, value);
2175   h->next = hd->headers;
2176   hd->headers = h;
2177
2178   return 0;
2179 }
2180
2181
2182 /* Return the header NAME from the last response.  The returned value
2183    is valid as along as HD has not been closed and no other request
2184    has been send. If the header was not found, NULL is returned.  NAME
2185    must be canonicalized, that is the first letter of each dash
2186    delimited part must be uppercase and all other letters lowercase.  */
2187 const char *
2188 http_get_header (http_t hd, const char *name)
2189 {
2190   header_t h;
2191
2192   for (h=hd->headers; h; h = h->next)
2193     if ( !strcmp (h->name, name) )
2194       return h->value;
2195   return NULL;
2196 }
2197
2198
2199 /* Return a newly allocated and NULL terminated array with pointers to
2200    header names.  The array must be released with xfree() and its
2201    content is only values as long as no other request has been
2202    send.  */
2203 const char **
2204 http_get_header_names (http_t hd)
2205 {
2206   const char **array;
2207   size_t n;
2208   header_t h;
2209
2210   for (n=0, h = hd->headers; h; h = h->next)
2211     n++;
2212   array = xtrycalloc (n+1, sizeof *array);
2213   if (array)
2214     {
2215       for (n=0, h = hd->headers; h; h = h->next)
2216         array[n++] = h->name;
2217     }
2218
2219   return array;
2220 }
2221
2222
2223 /*
2224  * Parse the response from a server.
2225  * Returns: Errorcode and sets some files in the handle
2226  */
2227 static gpg_err_code_t
2228 parse_response (http_t hd)
2229 {
2230   char *line, *p, *p2;
2231   size_t maxlen, len;
2232   cookie_t cookie = hd->read_cookie;
2233   const char *s;
2234
2235   /* Delete old header lines.  */
2236   while (hd->headers)
2237     {
2238       header_t tmp = hd->headers->next;
2239       xfree (hd->headers->value);
2240       xfree (hd->headers);
2241       hd->headers = tmp;
2242     }
2243
2244   /* Wait for the status line. */
2245   do
2246     {
2247       maxlen = MAX_LINELEN;
2248       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2249       line = hd->buffer;
2250       if (!line)
2251         return gpg_err_code_from_syserror (); /* Out of core. */
2252       if (!maxlen)
2253         return GPG_ERR_TRUNCATED; /* Line has been truncated. */
2254       if (!len)
2255         return GPG_ERR_EOF;
2256
2257       if ((hd->flags & HTTP_FLAG_LOG_RESP))
2258         log_debug_with_string (line, "http.c:response:\n");
2259     }
2260   while (!*line);
2261
2262   if ((p = strchr (line, '/')))
2263     *p++ = 0;
2264   if (!p || strcmp (line, "HTTP"))
2265     return 0; /* Assume http 0.9. */
2266
2267   if ((p2 = strpbrk (p, " \t")))
2268     {
2269       *p2++ = 0;
2270       p2 += strspn (p2, " \t");
2271     }
2272   if (!p2)
2273     return 0; /* Also assume http 0.9. */
2274   p = p2;
2275   /* TODO: Add HTTP version number check. */
2276   if ((p2 = strpbrk (p, " \t")))
2277     *p2++ = 0;
2278   if (!isdigit ((unsigned int)p[0]) || !isdigit ((unsigned int)p[1])
2279       || !isdigit ((unsigned int)p[2]) || p[3])
2280     {
2281       /* Malformed HTTP status code - assume http 0.9. */
2282       hd->is_http_0_9 = 1;
2283       hd->status_code = 200;
2284       return 0;
2285     }
2286   hd->status_code = atoi (p);
2287
2288   /* Skip all the header lines and wait for the empty line. */
2289   do
2290     {
2291       maxlen = MAX_LINELEN;
2292       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2293       line = hd->buffer;
2294       if (!line)
2295         return gpg_err_code_from_syserror (); /* Out of core. */
2296       /* Note, that we can silently ignore truncated lines. */
2297       if (!len)
2298         return GPG_ERR_EOF;
2299       /* Trim line endings of empty lines. */
2300       if ((*line == '\r' && line[1] == '\n') || *line == '\n')
2301         *line = 0;
2302       if ((hd->flags & HTTP_FLAG_LOG_RESP))
2303         log_info ("http.c:RESP: '%.*s'\n",
2304                   (int)strlen(line)-(*line&&line[1]?2:0),line);
2305       if (*line)
2306         {
2307           gpg_err_code_t ec = store_header (hd, line);
2308           if (ec)
2309             return ec;
2310         }
2311     }
2312   while (len && *line);
2313
2314   cookie->content_length_valid = 0;
2315   if (!(hd->flags & HTTP_FLAG_IGNORE_CL))
2316     {
2317       s = http_get_header (hd, "Content-Length");
2318       if (s)
2319         {
2320           cookie->content_length_valid = 1;
2321           cookie->content_length = string_to_u64 (s);
2322         }
2323     }
2324
2325   return 0;
2326 }
2327
2328 #if 0
2329 static int
2330 start_server ()
2331 {
2332   struct sockaddr_in mya;
2333   struct sockaddr_in peer;
2334   int fd, client;
2335   fd_set rfds;
2336   int addrlen;
2337   int i;
2338
2339   if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
2340     {
2341       log_error ("socket() failed: %s\n", strerror (errno));
2342       return -1;
2343     }
2344   i = 1;
2345   if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (byte *) & i, sizeof (i)))
2346     log_info ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno));
2347
2348   mya.sin_family = AF_INET;
2349   memset (&mya.sin_addr, 0, sizeof (mya.sin_addr));
2350   mya.sin_port = htons (11371);
2351
2352   if (bind (fd, (struct sockaddr *) &mya, sizeof (mya)))
2353     {
2354       log_error ("bind to port 11371 failed: %s\n", strerror (errno));
2355       sock_close (fd);
2356       return -1;
2357     }
2358
2359   if (listen (fd, 5))
2360     {
2361       log_error ("listen failed: %s\n", strerror (errno));
2362       sock_close (fd);
2363       return -1;
2364     }
2365
2366   for (;;)
2367     {
2368       FD_ZERO (&rfds);
2369       FD_SET (fd, &rfds);
2370
2371       if (my_select (fd + 1, &rfds, NULL, NULL, NULL) <= 0)
2372         continue;               /* ignore any errors */
2373
2374       if (!FD_ISSET (fd, &rfds))
2375         continue;
2376
2377       addrlen = sizeof peer;
2378       client = my_accept (fd, (struct sockaddr *) &peer, &addrlen);
2379       if (client == -1)
2380         continue;               /* oops */
2381
2382       log_info ("connect from %s\n", inet_ntoa (peer.sin_addr));
2383
2384       fflush (stdout);
2385       fflush (stderr);
2386       if (!fork ())
2387         {
2388           int c;
2389           FILE *fp;
2390
2391           fp = fdopen (client, "r");
2392           while ((c = getc (fp)) != EOF)
2393             putchar (c);
2394           fclose (fp);
2395           exit (0);
2396         }
2397       sock_close (client);
2398     }
2399
2400
2401   return 0;
2402 }
2403 #endif
2404
2405
2406
2407 /* Return true if SOCKS shall be used.  This is the case if tor_mode
2408  * is enabled and the desired address is not the loopback address.
2409  * This function is basically a copy of the same internal fucntion in
2410  * Libassuan.  */
2411 static int
2412 use_socks (struct sockaddr *addr)
2413 {
2414   int mode;
2415
2416   if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
2417     return 0;  /* Not in Tor mode.  */
2418   else if (addr->sa_family == AF_INET6)
2419     {
2420       struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr;
2421       const unsigned char *s;
2422       int i;
2423
2424       s = (unsigned char *)&addr_in6->sin6_addr.s6_addr;
2425       if (s[15] != 1)
2426         return 1;   /* Last octet is not 1 - not the loopback address.  */
2427       for (i=0; i < 15; i++, s++)
2428         if (*s)
2429           return 1; /* Non-zero octet found - not the loopback address.  */
2430
2431       return 0; /* This is the loopback address.  */
2432     }
2433   else if (addr->sa_family == AF_INET)
2434     {
2435       struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
2436
2437       if (*(unsigned char*)&addr_in->sin_addr.s_addr == 127)
2438         return 0; /* Loopback (127.0.0.0/8) */
2439
2440       return 1;
2441     }
2442   else
2443     return 0;
2444 }
2445
2446
2447 /* Wrapper around assuan_sock_new which takes the domain from an
2448  * address parameter.  */
2449 static assuan_fd_t
2450 my_sock_new_for_addr (struct sockaddr *addr, int type, int proto)
2451 {
2452   int domain;
2453
2454   if (use_socks (addr))
2455     {
2456       /* Libassaun always uses 127.0.0.1 to connect to the socks
2457        * server (i.e. the Tor daemon).  */
2458       domain = AF_INET;
2459     }
2460   else
2461     domain = addr->sa_family;
2462
2463   return assuan_sock_new (domain, type, proto);
2464 }
2465
2466
2467 /* Actually connect to a server.  On success 0 is returned and the
2468  * file descriptor for the socket is stored at R_SOCK; on error an
2469  * error code is returned and ASSUAN_INVALID_FD is stored at
2470  * R_SOCK.  */
2471 static gpg_error_t
2472 connect_server (const char *server, unsigned short port,
2473                 unsigned int flags, const char *srvtag, assuan_fd_t *r_sock)
2474 {
2475   gpg_error_t err;
2476   assuan_fd_t sock = ASSUAN_INVALID_FD;
2477   unsigned int srvcount = 0;
2478   int hostfound = 0;
2479   int anyhostaddr = 0;
2480   int srv, connected;
2481   gpg_error_t last_err = 0;
2482   struct srventry *serverlist = NULL;
2483
2484   *r_sock = ASSUAN_INVALID_FD;
2485
2486 #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
2487   init_sockets ();
2488 #endif /*Windows*/
2489
2490   /* Onion addresses require special treatment.  */
2491   if (is_onion_address (server))
2492     {
2493 #ifdef ASSUAN_SOCK_TOR
2494
2495       if (opt_debug)
2496         log_debug ("http.c:connect_server:onion: name='%s' port=%hu\n",
2497                    server, port);
2498       sock = assuan_sock_connect_byname (server, port, 0, NULL,
2499                                          ASSUAN_SOCK_TOR);
2500       if (sock == ASSUAN_INVALID_FD)
2501         {
2502           err = gpg_err_make (default_errsource,
2503                               (errno == EHOSTUNREACH)? GPG_ERR_UNKNOWN_HOST
2504                               : gpg_err_code_from_syserror ());
2505           log_error ("can't connect to '%s': %s\n", server, gpg_strerror (err));
2506           return err;
2507         }
2508
2509       notify_netactivity ();
2510       *r_sock = sock;
2511       return 0;
2512
2513 #else /*!ASSUAN_SOCK_TOR*/
2514
2515       err = gpg_err_make (default_errsource, GPG_ERR_ENETUNREACH);
2516       return ASSUAN_INVALID_FD;
2517
2518 #endif /*!HASSUAN_SOCK_TOR*/
2519     }
2520
2521   /* Do the SRV thing */
2522   if (srvtag)
2523     {
2524       err = get_dns_srv (server, srvtag, NULL, &serverlist, &srvcount);
2525       if (err)
2526         log_info ("getting '%s' SRV for '%s' failed: %s\n",
2527                   srvtag, server, gpg_strerror (err));
2528       /* Note that on error SRVCOUNT is zero.  */
2529       err = 0;
2530     }
2531
2532   if (!serverlist)
2533     {
2534       /* Either we're not using SRV, or the SRV lookup failed.  Make
2535          up a fake SRV record. */
2536       serverlist = xtrycalloc (1, sizeof *serverlist);
2537       if (!serverlist)
2538         return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2539
2540       serverlist->port = port;
2541       strncpy (serverlist->target, server, DIMof (struct srventry, target));
2542       serverlist->target[DIMof (struct srventry, target)-1] = '\0';
2543       srvcount = 1;
2544     }
2545
2546   connected = 0;
2547   for (srv=0; srv < srvcount && !connected; srv++)
2548     {
2549       dns_addrinfo_t aibuf, ai;
2550
2551       if (opt_debug)
2552         log_debug ("http.c:connect_server: trying name='%s' port=%hu\n",
2553                    serverlist[srv].target, port);
2554       err = resolve_dns_name (serverlist[srv].target, port, 0, SOCK_STREAM,
2555                               &aibuf, NULL);
2556       if (err)
2557         {
2558           log_info ("resolving '%s' failed: %s\n",
2559                     serverlist[srv].target, gpg_strerror (err));
2560           last_err = err;
2561           continue; /* Not found - try next one. */
2562         }
2563       hostfound = 1;
2564
2565       for (ai = aibuf; ai && !connected; ai = ai->next)
2566         {
2567           if (ai->family == AF_INET && (flags & HTTP_FLAG_IGNORE_IPv4))
2568             continue;
2569           if (ai->family == AF_INET6 && (flags & HTTP_FLAG_IGNORE_IPv6))
2570             continue;
2571
2572           if (sock != ASSUAN_INVALID_FD)
2573             assuan_sock_close (sock);
2574           sock = my_sock_new_for_addr (ai->addr, ai->socktype, ai->protocol);
2575           if (sock == ASSUAN_INVALID_FD)
2576             {
2577               err = gpg_err_make (default_errsource,
2578                                   gpg_err_code_from_syserror ());
2579               log_error ("error creating socket: %s\n", gpg_strerror (err));
2580               free_dns_addrinfo (aibuf);
2581               xfree (serverlist);
2582               return err;
2583             }
2584
2585           anyhostaddr = 1;
2586           if (assuan_sock_connect (sock, ai->addr, ai->addrlen))
2587             {
2588               last_err = gpg_err_make (default_errsource,
2589                                        gpg_err_code_from_syserror ());
2590             }
2591           else
2592             {
2593               connected = 1;
2594               notify_netactivity ();
2595             }
2596         }
2597       free_dns_addrinfo (aibuf);
2598     }
2599
2600   xfree (serverlist);
2601
2602   if (!connected)
2603     {
2604       if (!hostfound)
2605         log_error ("can't connect to '%s': %s\n",
2606                    server, "host not found");
2607       else if (!anyhostaddr)
2608         log_error ("can't connect to '%s': %s\n",
2609                    server, "no IP address for host");
2610       else
2611         {
2612 #ifdef HAVE_W32_SYSTEM
2613         log_error ("can't connect to '%s': ec=%d\n",
2614                    server, (int)WSAGetLastError());
2615 #else
2616         log_error ("can't connect to '%s': %s\n",
2617                    server, gpg_strerror (last_err));
2618 #endif
2619         }
2620       err = last_err? last_err : gpg_err_make (default_errsource,
2621                                                GPG_ERR_UNKNOWN_HOST);
2622       if (sock != ASSUAN_INVALID_FD)
2623         assuan_sock_close (sock);
2624       return err;
2625     }
2626
2627   *r_sock = sock;
2628   return 0;
2629 }
2630
2631
2632 static gpg_error_t
2633 write_server (int sock, const char *data, size_t length)
2634 {
2635   int nleft;
2636   int nwritten;
2637
2638   nleft = length;
2639   while (nleft > 0)
2640     {
2641 #if defined(HAVE_W32_SYSTEM)
2642 # if defined(USE_NPTH)
2643       npth_unprotect ();
2644 # endif
2645       nwritten = send (sock, data, nleft, 0);
2646 # if defined(USE_NPTH)
2647       npth_protect ();
2648 # endif
2649       if ( nwritten == SOCKET_ERROR )
2650         {
2651           log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
2652           return gpg_error (GPG_ERR_NETWORK);
2653         }
2654 #else /*!HAVE_W32_SYSTEM*/
2655 # ifdef USE_NPTH
2656       nwritten = npth_write (sock, data, nleft);
2657 # else
2658       nwritten = write (sock, data, nleft);
2659 # endif
2660       if (nwritten == -1)
2661         {
2662           if (errno == EINTR)
2663             continue;
2664           if (errno == EAGAIN)
2665             {
2666               struct timeval tv;
2667
2668               tv.tv_sec = 0;
2669               tv.tv_usec = 50000;
2670               my_select (0, NULL, NULL, NULL, &tv);
2671               continue;
2672             }
2673           log_info ("network write failed: %s\n", strerror (errno));
2674           return gpg_error_from_syserror ();
2675         }
2676 #endif /*!HAVE_W32_SYSTEM*/
2677       nleft -= nwritten;
2678       data += nwritten;
2679     }
2680
2681   return 0;
2682 }
2683
2684
2685 \f
2686 /* Read handler for estream.  */
2687 static gpgrt_ssize_t
2688 cookie_read (void *cookie, void *buffer, size_t size)
2689 {
2690   cookie_t c = cookie;
2691   int nread;
2692
2693   if (c->content_length_valid)
2694     {
2695       if (!c->content_length)
2696         return 0; /* EOF */
2697       if (c->content_length < size)
2698         size = c->content_length;
2699     }
2700
2701 #if HTTP_USE_NTBTLS
2702   if (c->use_tls && c->session && c->session->tls_session)
2703     {
2704       estream_t in, out;
2705
2706       ntbtls_get_stream (c->session->tls_session, &in, &out);
2707       nread = es_fread (buffer, 1, size, in);
2708       if (opt_debug)
2709         log_debug ("TLS network read: %d/%zu\n", nread, size);
2710     }
2711   else
2712 #elif HTTP_USE_GNUTLS
2713   if (c->use_tls && c->session && c->session->tls_session)
2714     {
2715     again:
2716       nread = gnutls_record_recv (c->session->tls_session, buffer, size);
2717       if (nread < 0)
2718         {
2719           if (nread == GNUTLS_E_INTERRUPTED)
2720             goto again;
2721           if (nread == GNUTLS_E_AGAIN)
2722             {
2723               struct timeval tv;
2724
2725               tv.tv_sec = 0;
2726               tv.tv_usec = 50000;
2727               my_select (0, NULL, NULL, NULL, &tv);
2728               goto again;
2729             }
2730           if (nread == GNUTLS_E_REHANDSHAKE)
2731             goto again; /* A client is allowed to just ignore this request. */
2732           if (nread == GNUTLS_E_PREMATURE_TERMINATION)
2733             {
2734               /* The server terminated the connection.  Close the TLS
2735                  session, and indicate EOF using a short read.  */
2736               close_tls_session (c->session);
2737               return 0;
2738             }
2739           log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
2740           gpg_err_set_errno (EIO);
2741           return -1;
2742         }
2743     }
2744   else
2745 #endif /*HTTP_USE_GNUTLS*/
2746     {
2747       do
2748         {
2749 #ifdef HAVE_W32_SYSTEM
2750           /* Under Windows we need to use recv for a socket.  */
2751 # if defined(USE_NPTH)
2752           npth_unprotect ();
2753 # endif
2754           nread = recv (c->sock->fd, buffer, size, 0);
2755 # if defined(USE_NPTH)
2756           npth_protect ();
2757 # endif
2758
2759 #else /*!HAVE_W32_SYSTEM*/
2760
2761 # ifdef USE_NPTH
2762           nread = npth_read (c->sock->fd, buffer, size);
2763 # else
2764           nread = read (c->sock->fd, buffer, size);
2765 # endif
2766
2767 #endif /*!HAVE_W32_SYSTEM*/
2768         }
2769       while (nread == -1 && errno == EINTR);
2770     }
2771
2772   if (c->content_length_valid && nread > 0)
2773     {
2774       if (nread < c->content_length)
2775         c->content_length -= nread;
2776       else
2777         c->content_length = 0;
2778     }
2779
2780   return (gpgrt_ssize_t)nread;
2781 }
2782
2783 /* Write handler for estream.  */
2784 static gpgrt_ssize_t
2785 cookie_write (void *cookie, const void *buffer_arg, size_t size)
2786 {
2787   const char *buffer = buffer_arg;
2788   cookie_t c = cookie;
2789   int nwritten = 0;
2790
2791 #if HTTP_USE_NTBTLS
2792   if (c->use_tls && c->session && c->session->tls_session)
2793     {
2794       estream_t in, out;
2795
2796       ntbtls_get_stream (c->session->tls_session, &in, &out);
2797       if (size == 0)
2798         es_fflush (out);
2799       else
2800         nwritten = es_fwrite (buffer, 1, size, out);
2801       if (opt_debug)
2802         log_debug ("TLS network write: %d/%zu\n", nwritten, size);
2803     }
2804   else
2805 #elif HTTP_USE_GNUTLS
2806   if (c->use_tls && c->session && c->session->tls_session)
2807     {
2808       int nleft = size;
2809       while (nleft > 0)
2810         {
2811           nwritten = gnutls_record_send (c->session->tls_session,
2812                                          buffer, nleft);
2813           if (nwritten <= 0)
2814             {
2815               if (nwritten == GNUTLS_E_INTERRUPTED)
2816                 continue;
2817               if (nwritten == GNUTLS_E_AGAIN)
2818                 {
2819                   struct timeval tv;
2820
2821                   tv.tv_sec = 0;
2822                   tv.tv_usec = 50000;
2823                   my_select (0, NULL, NULL, NULL, &tv);
2824                   continue;
2825                 }
2826               log_info ("TLS network write failed: %s\n",
2827                         gnutls_strerror (nwritten));
2828               gpg_err_set_errno (EIO);
2829               return -1;
2830             }
2831           nleft -= nwritten;
2832           buffer += nwritten;
2833         }
2834     }
2835   else
2836 #endif /*HTTP_USE_GNUTLS*/
2837     {
2838       if ( write_server (c->sock->fd, buffer, size) )
2839         {
2840           gpg_err_set_errno (EIO);
2841           nwritten = -1;
2842         }
2843       else
2844         nwritten = size;
2845     }
2846
2847   return (gpgrt_ssize_t)nwritten;
2848 }
2849
2850
2851 #ifdef HTTP_USE_GNUTLS
2852 /* Wrapper for gnutls_bye used by my_socket_unref.  */
2853 static void
2854 send_gnutls_bye (void *opaque)
2855 {
2856   tls_session_t tls_session = opaque;
2857   int ret;
2858
2859  again:
2860   do
2861     ret = gnutls_bye (tls_session, GNUTLS_SHUT_RDWR);
2862   while (ret == GNUTLS_E_INTERRUPTED);
2863   if (ret == GNUTLS_E_AGAIN)
2864     {
2865       struct timeval tv;
2866
2867       tv.tv_sec = 0;
2868       tv.tv_usec = 50000;
2869       my_select (0, NULL, NULL, NULL, &tv);
2870       goto again;
2871     }
2872 }
2873 #endif /*HTTP_USE_GNUTLS*/
2874
2875 /* Close handler for estream.  */
2876 static int
2877 cookie_close (void *cookie)
2878 {
2879   cookie_t c = cookie;
2880
2881   if (!c)
2882     return 0;
2883
2884 #if HTTP_USE_NTBTLS
2885   if (c->use_tls && c->session && c->session->tls_session)
2886     {
2887       /* FIXME!! Possibly call ntbtls_close_notify for close
2888          of write stream.  */
2889       my_socket_unref (c->sock, NULL, NULL);
2890     }
2891   else
2892 #elif HTTP_USE_GNUTLS
2893   if (c->use_tls && c->session && c->session->tls_session)
2894     my_socket_unref (c->sock, send_gnutls_bye, c->session->tls_session);
2895   else
2896 #endif /*HTTP_USE_GNUTLS*/
2897     if (c->sock)
2898       my_socket_unref (c->sock, NULL, NULL);
2899
2900   if (c->session)
2901     http_session_unref (c->session);
2902   xfree (c);
2903   return 0;
2904 }
2905
2906
2907
2908 \f
2909 /* Verify the credentials of the server.  Returns 0 on success and
2910    store the result in the session object.  */
2911 gpg_error_t
2912 http_verify_server_credentials (http_session_t sess)
2913 {
2914 #if HTTP_USE_NTBTLS
2915   (void)sess;
2916   return 0;  /* FIXME!! */
2917 #elif HTTP_USE_GNUTLS
2918   static const char const errprefix[] = "TLS verification of peer failed";
2919   int rc;
2920   unsigned int status;
2921   const char *hostname;
2922   const gnutls_datum_t *certlist;
2923   unsigned int certlistlen;
2924   gnutls_x509_crt_t cert;
2925   gpg_error_t err = 0;
2926
2927   sess->verify.done = 1;
2928   sess->verify.status = 0;
2929   sess->verify.rc = GNUTLS_E_CERTIFICATE_ERROR;
2930
2931   if (gnutls_certificate_type_get (sess->tls_session) != GNUTLS_CRT_X509)
2932     {
2933       log_error ("%s: %s\n", errprefix, "not an X.509 certificate");
2934       sess->verify.rc = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
2935       return gpg_error (GPG_ERR_GENERAL);
2936     }
2937
2938   rc = gnutls_certificate_verify_peers2 (sess->tls_session, &status);
2939   if (rc)
2940     {
2941       log_error ("%s: %s\n", errprefix, gnutls_strerror (rc));
2942       if (!err)
2943         err = gpg_error (GPG_ERR_GENERAL);
2944     }
2945   else if (status)
2946     {
2947       log_error ("%s: status=0x%04x\n", errprefix, status);
2948 #if GNUTLS_VERSION_NUMBER >= 0x030104
2949       {
2950         gnutls_datum_t statusdat;
2951
2952         if (!gnutls_certificate_verification_status_print
2953             (status, GNUTLS_CRT_X509, &statusdat, 0))
2954           {
2955             log_info ("%s: %s\n", errprefix, statusdat.data);
2956             gnutls_free (statusdat.data);
2957           }
2958       }
2959 #endif /*gnutls >= 3.1.4*/
2960
2961       sess->verify.status = status;
2962       if (!err)
2963         err = gpg_error (GPG_ERR_GENERAL);
2964     }
2965
2966   hostname = sess->servername;
2967   if (!hostname || !strchr (hostname, '.'))
2968     {
2969       log_error ("%s: %s\n", errprefix, "hostname missing");
2970       if (!err)
2971         err = gpg_error (GPG_ERR_GENERAL);
2972     }
2973
2974   certlist = gnutls_certificate_get_peers (sess->tls_session, &certlistlen);
2975   if (!certlistlen)
2976     {
2977       log_error ("%s: %s\n", errprefix, "server did not send a certificate");
2978       if (!err)
2979         err = gpg_error (GPG_ERR_GENERAL);
2980
2981       /* Need to stop here.  */
2982       if (err)
2983         return err;
2984     }
2985
2986   rc = gnutls_x509_crt_init (&cert);
2987   if (rc < 0)
2988     {
2989       if (!err)
2990         err = gpg_error (GPG_ERR_GENERAL);
2991       if (err)
2992         return err;
2993     }
2994
2995   rc = gnutls_x509_crt_import (cert, &certlist[0], GNUTLS_X509_FMT_DER);
2996   if (rc < 0)
2997     {
2998       log_error ("%s: %s: %s\n", errprefix, "error importing certificate",
2999                  gnutls_strerror (rc));
3000       if (!err)
3001         err = gpg_error (GPG_ERR_GENERAL);
3002     }
3003
3004   if (!gnutls_x509_crt_check_hostname (cert, hostname))
3005     {
3006       log_error ("%s: %s\n", errprefix, "hostname does not match");
3007       if (!err)
3008         err = gpg_error (GPG_ERR_GENERAL);
3009     }
3010
3011   gnutls_x509_crt_deinit (cert);
3012
3013   if (!err)
3014     sess->verify.rc = 0;
3015
3016   if (sess->cert_log_cb)
3017     {
3018       const void *bufarr[10];
3019       size_t buflenarr[10];
3020       size_t n;
3021
3022       for (n = 0; n < certlistlen && n < DIM (bufarr)-1; n++)
3023         {
3024           bufarr[n] = certlist[n].data;
3025           buflenarr[n] = certlist[n].size;
3026         }
3027       bufarr[n] = NULL;
3028       buflenarr[n] = 0;
3029       sess->cert_log_cb (sess, err, hostname, bufarr, buflenarr);
3030     }
3031
3032   return err;
3033 #else /*!HTTP_USE_GNUTLS*/
3034   (void)sess;
3035   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
3036 #endif
3037 }
3038
3039 /* Return the first query variable with the specified key.  If there
3040    is no such variable, return NULL.  */
3041 struct uri_tuple_s *
3042 uri_query_lookup (parsed_uri_t uri, const char *key)
3043 {
3044   struct uri_tuple_s *t;
3045
3046   for (t = uri->query; t; t = t->next)
3047     if (strcmp (t->name, key) == 0)
3048       return t;
3049
3050   return NULL;
3051 }