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