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