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