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