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