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