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