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