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