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