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