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