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