dirmngr: Allow building with libassuan < 2.3.
[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       int mode;
755
756 #if ASSUAN_VERSION_NUMBER >= 0x020300 /* >= 2.3.0 */
757       if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
758 #endif
759         {
760           log_error ("TOR support is not available\n");
761           return gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
762         }
763     }
764
765   /* Create the handle. */
766   hd = xtrycalloc (1, sizeof *hd);
767   if (!hd)
768     return gpg_error_from_syserror ();
769   hd->req_type = HTTP_REQ_OPAQUE;
770   hd->flags = flags;
771
772   /* Connect.  */
773   {
774     assuan_fd_t sock;
775
776     sock = connect_server (server, port, hd->flags, srvtag, &hnf);
777     if (sock == ASSUAN_INVALID_FD)
778       {
779         err = gpg_err_make (default_errsource,
780                             (hnf? GPG_ERR_UNKNOWN_HOST
781                              : gpg_err_code_from_syserror ()));
782         xfree (hd);
783         return err;
784       }
785     hd->sock = my_socket_new (sock);
786     if (!hd->sock)
787       {
788         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
789         xfree (hd);
790         return err;
791       }
792   }
793
794   /* Setup estreams for reading and writing.  */
795   cookie = xtrycalloc (1, sizeof *cookie);
796   if (!cookie)
797     {
798       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
799       goto leave;
800     }
801   cookie->sock = my_socket_ref (hd->sock);
802   hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
803   if (!hd->fp_write)
804     {
805       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
806       my_socket_unref (cookie->sock, NULL, NULL);
807       xfree (cookie);
808       goto leave;
809     }
810   hd->write_cookie = cookie; /* Cookie now owned by FP_WRITE.  */
811
812   cookie = xtrycalloc (1, sizeof *cookie);
813   if (!cookie)
814     {
815       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
816       goto leave;
817     }
818   cookie->sock = my_socket_ref (hd->sock);
819   hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
820   if (!hd->fp_read)
821     {
822       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
823       my_socket_unref (cookie->sock, NULL, NULL);
824       xfree (cookie);
825       goto leave;
826     }
827   hd->read_cookie = cookie; /* Cookie now owned by FP_READ.  */
828
829   /* Register close notification to interlock the use of es_fclose in
830      http_close and in user code.  */
831   err = es_onclose (hd->fp_write, 1, fp_onclose_notification, hd);
832   if (!err)
833     err = es_onclose (hd->fp_read, 1, fp_onclose_notification, hd);
834
835  leave:
836   if (err)
837     {
838       if (hd->fp_read)
839         es_fclose (hd->fp_read);
840       if (hd->fp_write)
841         es_fclose (hd->fp_write);
842       my_socket_unref (hd->sock, NULL, NULL);
843       xfree (hd);
844     }
845   else
846     *r_hd = hd;
847   return err;
848 }
849
850
851
852
853 void
854 http_start_data (http_t hd)
855 {
856   if (!hd->in_data)
857     {
858       es_fputs ("\r\n", hd->fp_write);
859       es_fflush (hd->fp_write);
860       hd->in_data = 1;
861     }
862   else
863     es_fflush (hd->fp_write);
864 }
865
866
867 gpg_error_t
868 http_wait_response (http_t hd)
869 {
870   gpg_error_t err;
871   cookie_t cookie;
872
873   /* Make sure that we are in the data. */
874   http_start_data (hd);
875
876   /* Close the write stream.  Note that the reference counted socket
877      object keeps the actual system socket open.  */
878   cookie = hd->write_cookie;
879   if (!cookie)
880     return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
881
882   es_fclose (hd->fp_write);
883   hd->fp_write = NULL;
884   /* The close has released the cookie and thus we better set it to NULL.  */
885   hd->write_cookie = NULL;
886
887   /* Shutdown one end of the socket is desired.  As per HTTP/1.0 this
888      is not required but some very old servers (e.g. the original pksd
889      key server didn't worked without it.  */
890   if ((hd->flags & HTTP_FLAG_SHUTDOWN))
891     shutdown (hd->sock->fd, 1);
892   hd->in_data = 0;
893
894   /* Create a new cookie and a stream for reading.  */
895   cookie = xtrycalloc (1, sizeof *cookie);
896   if (!cookie)
897     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
898   cookie->sock = my_socket_ref (hd->sock);
899   cookie->session = http_session_ref (hd->session);
900   cookie->use_tls = hd->uri->use_tls;
901
902   hd->read_cookie = cookie;
903   hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
904   if (!hd->fp_read)
905     {
906       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
907       my_socket_unref (cookie->sock, NULL, NULL);
908       http_session_unref (cookie->session);
909       xfree (cookie);
910       hd->read_cookie = NULL;
911       return err;
912     }
913
914   err = parse_response (hd);
915
916   if (!err)
917     err = es_onclose (hd->fp_read, 1, fp_onclose_notification, hd);
918
919   return err;
920 }
921
922
923 /* Convenience function to send a request and wait for the response.
924    Closes the handle on error.  If PROXY is not NULL, this value will
925    be used as an HTTP proxy and any enabled $http_proxy gets
926    ignored. */
927 gpg_error_t
928 http_open_document (http_t *r_hd, const char *document,
929                     const char *auth, unsigned int flags, const char *proxy,
930                     http_session_t session,
931                     const char *srvtag, strlist_t headers)
932 {
933   gpg_error_t err;
934
935   err = http_open (r_hd, HTTP_REQ_GET, document, NULL, auth, flags,
936                    proxy, session, srvtag, headers);
937   if (err)
938     return err;
939
940   err = http_wait_response (*r_hd);
941   if (err)
942     http_close (*r_hd, 0);
943
944   return err;
945 }
946
947
948 void
949 http_close (http_t hd, int keep_read_stream)
950 {
951   if (!hd)
952     return;
953
954   /* First remove the close notifications for the streams.  */
955   if (hd->fp_read)
956     es_onclose (hd->fp_read, 0, fp_onclose_notification, hd);
957   if (hd->fp_write)
958     es_onclose (hd->fp_write, 0, fp_onclose_notification, hd);
959
960   /* Now we can close the streams.  */
961   my_socket_unref (hd->sock, NULL, NULL);
962   if (hd->fp_read && !keep_read_stream)
963     es_fclose (hd->fp_read);
964   if (hd->fp_write)
965     es_fclose (hd->fp_write);
966   http_session_unref (hd->session);
967   http_release_parsed_uri (hd->uri);
968   while (hd->headers)
969     {
970       header_t tmp = hd->headers->next;
971       xfree (hd->headers->value);
972       xfree (hd->headers);
973       hd->headers = tmp;
974     }
975   xfree (hd->buffer);
976   xfree (hd);
977 }
978
979
980 estream_t
981 http_get_read_ptr (http_t hd)
982 {
983   return hd?hd->fp_read:NULL;
984 }
985
986 estream_t
987 http_get_write_ptr (http_t hd)
988 {
989   return hd?hd->fp_write:NULL;
990 }
991
992 unsigned int
993 http_get_status_code (http_t hd)
994 {
995   return hd?hd->status_code:0;
996 }
997
998 /* Return information pertaining to TLS.  If TLS is not in use for HD,
999    NULL is returned.  WHAT is used ask for specific information:
1000
1001      (NULL) := Only check whether TLS is is use.  Returns an
1002                unspecified string if TLS is in use.  That string may
1003                even be the empty string.
1004  */
1005 const char *
1006 http_get_tls_info (http_t hd, const char *what)
1007 {
1008   (void)what;
1009
1010   if (!hd)
1011     return NULL;
1012
1013   return hd->uri->use_tls? "":NULL;
1014 }
1015
1016
1017 \f
1018 static gpg_error_t
1019 parse_uri (parsed_uri_t *ret_uri, const char *uri,
1020            int no_scheme_check, int force_tls)
1021 {
1022   gpg_err_code_t ec;
1023
1024   *ret_uri = xtrycalloc (1, sizeof **ret_uri + strlen (uri));
1025   if (!*ret_uri)
1026     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1027   strcpy ((*ret_uri)->buffer, uri);
1028   ec = do_parse_uri (*ret_uri, 0, no_scheme_check, force_tls);
1029   if (ec)
1030     {
1031       xfree (*ret_uri);
1032       *ret_uri = NULL;
1033     }
1034   return gpg_err_make (default_errsource, ec);
1035 }
1036
1037
1038 /*
1039  * Parse an URI and put the result into the newly allocated RET_URI.
1040  * On success the caller must use http_release_parsed_uri() to
1041  * releases the resources.  If NO_SCHEME_CHECK is set, the function
1042  * tries to parse the URL in the same way it would do for an HTTP
1043  * style URI.
1044  */
1045 gpg_error_t
1046 http_parse_uri (parsed_uri_t *ret_uri, const char *uri,
1047                 int no_scheme_check)
1048 {
1049   return parse_uri (ret_uri, uri, no_scheme_check, 0);
1050 }
1051
1052
1053 void
1054 http_release_parsed_uri (parsed_uri_t uri)
1055 {
1056   if (uri)
1057     {
1058       uri_tuple_t r, r2;
1059
1060       for (r = uri->query; r; r = r2)
1061         {
1062           r2 = r->next;
1063           xfree (r);
1064         }
1065       xfree (uri);
1066     }
1067 }
1068
1069
1070 static gpg_err_code_t
1071 do_parse_uri (parsed_uri_t uri, int only_local_part,
1072               int no_scheme_check, int force_tls)
1073 {
1074   uri_tuple_t *tail;
1075   char *p, *p2, *p3, *pp;
1076   int n;
1077
1078   p = uri->buffer;
1079   n = strlen (uri->buffer);
1080
1081   /* Initialize all fields to an empty string or an empty list. */
1082   uri->scheme = uri->host = uri->path = p + n;
1083   uri->port = 0;
1084   uri->params = uri->query = NULL;
1085   uri->use_tls = 0;
1086   uri->is_http = 0;
1087   uri->opaque = 0;
1088   uri->v6lit = 0;
1089
1090   /* A quick validity check. */
1091   if (strspn (p, VALID_URI_CHARS) != n)
1092     return GPG_ERR_BAD_URI;     /* Invalid characters found. */
1093
1094   if (!only_local_part)
1095     {
1096       /* Find the scheme. */
1097       if (!(p2 = strchr (p, ':')) || p2 == p)
1098         return GPG_ERR_BAD_URI; /* No scheme. */
1099       *p2++ = 0;
1100       for (pp=p; *pp; pp++)
1101        *pp = tolower (*(unsigned char*)pp);
1102       uri->scheme = p;
1103       if (!strcmp (uri->scheme, "http") && !force_tls)
1104         {
1105           uri->port = 80;
1106           uri->is_http = 1;
1107         }
1108       else if (!strcmp (uri->scheme, "hkp") && !force_tls)
1109         {
1110           uri->port = 11371;
1111           uri->is_http = 1;
1112         }
1113 #ifdef USE_TLS
1114       else if (!strcmp (uri->scheme, "https") || !strcmp (uri->scheme,"hkps")
1115                || (force_tls && (!strcmp (uri->scheme, "http")
1116                                  || !strcmp (uri->scheme,"hkp"))))
1117         {
1118           uri->port = 443;
1119           uri->is_http = 1;
1120           uri->use_tls = 1;
1121         }
1122 #endif /*USE_TLS*/
1123       else if (!no_scheme_check)
1124         return GPG_ERR_INV_URI; /* Unsupported scheme */
1125
1126       p = p2;
1127
1128       if (*p == '/' && p[1] == '/' ) /* There seems to be a hostname. */
1129         {
1130           p += 2;
1131           if ((p2 = strchr (p, '/')))
1132             *p2++ = 0;
1133
1134           /* Check for username/password encoding */
1135           if ((p3 = strchr (p, '@')))
1136             {
1137               uri->auth = p;
1138               *p3++ = '\0';
1139               p = p3;
1140             }
1141
1142           for (pp=p; *pp; pp++)
1143             *pp = tolower (*(unsigned char*)pp);
1144
1145           /* Handle an IPv6 literal */
1146           if( *p == '[' && (p3=strchr( p, ']' )) )
1147             {
1148               *p3++ = '\0';
1149               /* worst case, uri->host should have length 0, points to \0 */
1150               uri->host = p + 1;
1151               uri->v6lit = 1;
1152               p = p3;
1153             }
1154           else
1155             uri->host = p;
1156
1157           if ((p3 = strchr (p, ':')))
1158             {
1159               *p3++ = '\0';
1160               uri->port = atoi (p3);
1161             }
1162
1163           if ((n = remove_escapes (uri->host)) < 0)
1164             return GPG_ERR_BAD_URI;
1165           if (n != strlen (uri->host))
1166             return GPG_ERR_BAD_URI;     /* Hostname incudes a Nul. */
1167           p = p2 ? p2 : NULL;
1168         }
1169       else if (uri->is_http)
1170         return GPG_ERR_INV_URI; /* No Leading double slash for HTTP.  */
1171       else
1172         {
1173           uri->opaque = 1;
1174           uri->path = p;
1175           return 0;
1176         }
1177
1178     } /* End global URI part. */
1179
1180   /* Parse the pathname part */
1181   if (!p || !*p)
1182     return 0;  /* We don't have a path.  Okay. */
1183
1184   /* TODO: Here we have to check params. */
1185
1186   /* Do we have a query part? */
1187   if ((p2 = strchr (p, '?')))
1188     *p2++ = 0;
1189
1190   uri->path = p;
1191   if ((n = remove_escapes (p)) < 0)
1192     return GPG_ERR_BAD_URI;
1193   if (n != strlen (p))
1194     return GPG_ERR_BAD_URI;     /* Path includes a Nul. */
1195   p = p2 ? p2 : NULL;
1196
1197   if (!p || !*p)
1198     return 0; /* We don't have a query string.  Okay. */
1199
1200   /* Now parse the query string. */
1201   tail = &uri->query;
1202   for (;;)
1203     {
1204       uri_tuple_t elem;
1205
1206       if ((p2 = strchr (p, '&')))
1207         *p2++ = 0;
1208       if (!(elem = parse_tuple (p)))
1209         return GPG_ERR_BAD_URI;
1210       *tail = elem;
1211       tail = &elem->next;
1212
1213       if (!p2)
1214         break; /* Ready. */
1215       p = p2;
1216     }
1217
1218   return 0;
1219 }
1220
1221
1222 /*
1223  * Remove all %xx escapes; this is done in-place.  Returns: New length
1224  * of the string.
1225  */
1226 static int
1227 remove_escapes (char *string)
1228 {
1229   int n = 0;
1230   unsigned char *p, *s;
1231
1232   for (p = s = (unsigned char*)string; *s; s++)
1233     {
1234       if (*s == '%')
1235         {
1236           if (s[1] && s[2] && isxdigit (s[1]) && isxdigit (s[2]))
1237             {
1238               s++;
1239               *p = *s >= '0' && *s <= '9' ? *s - '0' :
1240                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
1241               *p <<= 4;
1242               s++;
1243               *p |= *s >= '0' && *s <= '9' ? *s - '0' :
1244                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
1245               p++;
1246               n++;
1247             }
1248           else
1249             {
1250               *p++ = *s++;
1251               if (*s)
1252                 *p++ = *s++;
1253               if (*s)
1254                 *p++ = *s++;
1255               if (*s)
1256                 *p = 0;
1257               return -1; /* Bad URI. */
1258             }
1259         }
1260       else
1261         {
1262           *p++ = *s;
1263           n++;
1264         }
1265     }
1266   *p = 0; /* Make sure to keep a string terminator. */
1267   return n;
1268 }
1269
1270
1271 /* If SPECIAL is NULL this function escapes in forms mode.  */
1272 static size_t
1273 escape_data (char *buffer, const void *data, size_t datalen,
1274              const char *special)
1275 {
1276   int forms = !special;
1277   const unsigned char *s;
1278   size_t n = 0;
1279
1280   if (forms)
1281     special = "%;?&=";
1282
1283   for (s = data; datalen; s++, datalen--)
1284     {
1285       if (forms && *s == ' ')
1286         {
1287           if (buffer)
1288             *buffer++ = '+';
1289           n++;
1290         }
1291       else if (forms && *s == '\n')
1292         {
1293           if (buffer)
1294             memcpy (buffer, "%0D%0A", 6);
1295           n += 6;
1296         }
1297       else if (forms && *s == '\r' && datalen > 1 && s[1] == '\n')
1298         {
1299           if (buffer)
1300             memcpy (buffer, "%0D%0A", 6);
1301           n += 6;
1302           s++;
1303           datalen--;
1304         }
1305       else if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
1306         {
1307           if (buffer)
1308             *(unsigned char*)buffer++ = *s;
1309           n++;
1310         }
1311       else
1312         {
1313           if (buffer)
1314             {
1315               snprintf (buffer, 4, "%%%02X", *s);
1316               buffer += 3;
1317             }
1318           n += 3;
1319         }
1320     }
1321   return n;
1322 }
1323
1324
1325 static int
1326 insert_escapes (char *buffer, const char *string,
1327                 const char *special)
1328 {
1329   return escape_data (buffer, string, strlen (string), special);
1330 }
1331
1332
1333 /* Allocate a new string from STRING using standard HTTP escaping as
1334    well as escaping of characters given in SPECIALS.  A common pattern
1335    for SPECIALS is "%;?&=". However it depends on the needs, for
1336    example "+" and "/: often needs to be escaped too.  Returns NULL on
1337    failure and sets ERRNO.  If SPECIAL is NULL a dedicated forms
1338    encoding mode is used. */
1339 char *
1340 http_escape_string (const char *string, const char *specials)
1341 {
1342   int n;
1343   char *buf;
1344
1345   n = insert_escapes (NULL, string, specials);
1346   buf = xtrymalloc (n+1);
1347   if (buf)
1348     {
1349       insert_escapes (buf, string, specials);
1350       buf[n] = 0;
1351     }
1352   return buf;
1353 }
1354
1355 /* Allocate a new string from {DATA,DATALEN} using standard HTTP
1356    escaping as well as escaping of characters given in SPECIALS.  A
1357    common pattern for SPECIALS is "%;?&=".  However it depends on the
1358    needs, for example "+" and "/: often needs to be escaped too.
1359    Returns NULL on failure and sets ERRNO.  If SPECIAL is NULL a
1360    dedicated forms encoding mode is used. */
1361 char *
1362 http_escape_data (const void *data, size_t datalen, const char *specials)
1363 {
1364   int n;
1365   char *buf;
1366
1367   n = escape_data (NULL, data, datalen, specials);
1368   buf = xtrymalloc (n+1);
1369   if (buf)
1370     {
1371       escape_data (buf, data, datalen, specials);
1372       buf[n] = 0;
1373     }
1374   return buf;
1375 }
1376
1377
1378 static uri_tuple_t
1379 parse_tuple (char *string)
1380 {
1381   char *p = string;
1382   char *p2;
1383   int n;
1384   uri_tuple_t tuple;
1385
1386   if ((p2 = strchr (p, '=')))
1387     *p2++ = 0;
1388   if ((n = remove_escapes (p)) < 0)
1389     return NULL; /* Bad URI. */
1390   if (n != strlen (p))
1391     return NULL; /* Name with a Nul in it. */
1392   tuple = xtrycalloc (1, sizeof *tuple);
1393   if (!tuple)
1394     return NULL; /* Out of core. */
1395   tuple->name = p;
1396   if (!p2) /* We have only the name, so we assume an empty value string. */
1397     {
1398       tuple->value = p + strlen (p);
1399       tuple->valuelen = 0;
1400       tuple->no_value = 1; /* Explicitly mark that we have seen no '='. */
1401     }
1402   else /* Name and value. */
1403     {
1404       if ((n = remove_escapes (p2)) < 0)
1405         {
1406           xfree (tuple);
1407           return NULL; /* Bad URI. */
1408         }
1409       tuple->value = p2;
1410       tuple->valuelen = n;
1411     }
1412   return tuple;
1413 }
1414
1415
1416 /* Return true if STRING is likely "hostname:port" or only "hostname".  */
1417 static int
1418 is_hostname_port (const char *string)
1419 {
1420   int colons = 0;
1421
1422   if (!string || !*string)
1423     return 0;
1424   for (; *string; string++)
1425     {
1426       if (*string == ':')
1427         {
1428           if (colons)
1429             return 0;
1430           if (!string[1])
1431             return 0;
1432           colons++;
1433         }
1434       else if (!colons && strchr (" \t\f\n\v_@[]/", *string))
1435         return 0; /* Invalid characters in hostname. */
1436       else if (colons && !digitp (string))
1437         return 0; /* Not a digit in the port.  */
1438     }
1439   return 1;
1440 }
1441
1442
1443 /*
1444  * Send a HTTP request to the server
1445  * Returns 0 if the request was successful
1446  */
1447 static gpg_error_t
1448 send_request (http_t hd, const char *httphost, const char *auth,
1449               const char *proxy, const char *srvtag, strlist_t headers)
1450 {
1451   gpg_error_t err;
1452   const char *server;
1453   char *request, *p;
1454   unsigned short port;
1455   const char *http_proxy = NULL;
1456   char *proxy_authstr = NULL;
1457   char *authstr = NULL;
1458   int sock;
1459   int hnf;
1460
1461   if (hd->uri->use_tls && !hd->session)
1462     {
1463       log_error ("TLS requested but no session object provided\n");
1464       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1465     }
1466 #ifdef USE_TLS
1467   if (hd->uri->use_tls && !hd->session->tls_session)
1468     {
1469       log_error ("TLS requested but no GNUTLS context available\n");
1470       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1471     }
1472 #endif /*USE_TLS*/
1473
1474   if ((hd->flags & HTTP_FLAG_FORCE_TOR))
1475     {
1476       int mode;
1477
1478 #if ASSUAN_VERSION_NUMBER >= 0x020300 /* >= 2.3.0 */
1479       if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
1480 #endif
1481         {
1482           log_error ("TOR support is not available\n");
1483           return gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1484         }
1485     }
1486
1487   server = *hd->uri->host ? hd->uri->host : "localhost";
1488   port = hd->uri->port ? hd->uri->port : 80;
1489
1490   /* Try to use SNI.  */
1491 #ifdef USE_TLS
1492   if (hd->uri->use_tls)
1493     {
1494 # if HTTP_USE_GNUTLS
1495       int rc;
1496 # endif
1497
1498       xfree (hd->session->servername);
1499       hd->session->servername = xtrystrdup (httphost? httphost : server);
1500       if (!hd->session->servername)
1501         {
1502           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1503           return err;
1504         }
1505
1506 # if HTTP_USE_NTBTLS
1507       err = ntbtls_set_hostname (hd->session->tls_session,
1508                                  hd->session->servername);
1509       if (err)
1510         {
1511           log_info ("ntbtls_set_hostname failed: %s\n", gpg_strerror (err));
1512           return err;
1513         }
1514 # elif HTTP_USE_GNUTLS
1515       rc = gnutls_server_name_set (hd->session->tls_session,
1516                                    GNUTLS_NAME_DNS,
1517                                    hd->session->servername,
1518                                    strlen (hd->session->servername));
1519       if (rc < 0)
1520         log_info ("gnutls_server_name_set failed: %s\n", gnutls_strerror (rc));
1521 # endif /*HTTP_USE_GNUTLS*/
1522     }
1523 #endif /*USE_TLS*/
1524
1525   if ( (proxy && *proxy)
1526        || ( (hd->flags & HTTP_FLAG_TRY_PROXY)
1527             && (http_proxy = getenv (HTTP_PROXY_ENV))
1528             && *http_proxy ))
1529     {
1530       parsed_uri_t uri;
1531       int save_errno;
1532
1533       if (proxy)
1534         http_proxy = proxy;
1535
1536       err = parse_uri (&uri, http_proxy, 0, 0);
1537       if (gpg_err_code (err) == GPG_ERR_INV_URI
1538           && is_hostname_port (http_proxy))
1539         {
1540           /* Retry assuming a "hostname:port" string.  */
1541           char *tmpname = strconcat ("http://", http_proxy, NULL);
1542           if (tmpname && !parse_uri (&uri, tmpname, 0, 0))
1543             err = 0;
1544           xfree (tmpname);
1545         }
1546
1547       if (err)
1548         ;
1549       else if (!strcmp (uri->scheme, "http") || !strcmp (uri->scheme, "socks4"))
1550         ;
1551       else if (!strcmp (uri->scheme, "socks5h"))
1552         err = gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1553       else
1554         err = gpg_err_make (default_errsource, GPG_ERR_INV_URI);
1555
1556       if (err)
1557         {
1558           log_error ("invalid HTTP proxy (%s): %s\n",
1559                      http_proxy, gpg_strerror (err));
1560           return gpg_err_make (default_errsource, GPG_ERR_CONFIGURATION);
1561         }
1562
1563       if (uri->auth)
1564         {
1565           remove_escapes (uri->auth);
1566           proxy_authstr = make_header_line ("Proxy-Authorization: Basic ",
1567                                             "\r\n",
1568                                             uri->auth, strlen(uri->auth));
1569           if (!proxy_authstr)
1570             {
1571               err = gpg_err_make (default_errsource,
1572                                   gpg_err_code_from_syserror ());
1573               http_release_parsed_uri (uri);
1574               return err;
1575             }
1576         }
1577
1578       sock = connect_server (*uri->host ? uri->host : "localhost",
1579                              uri->port ? uri->port : 80,
1580                              hd->flags, srvtag, &hnf);
1581       save_errno = errno;
1582       http_release_parsed_uri (uri);
1583       if (sock == ASSUAN_INVALID_FD)
1584         gpg_err_set_errno (save_errno);
1585     }
1586   else
1587     {
1588       sock = connect_server (server, port, hd->flags, srvtag, &hnf);
1589     }
1590
1591   if (sock == ASSUAN_INVALID_FD)
1592     {
1593       xfree (proxy_authstr);
1594       return gpg_err_make (default_errsource,
1595                            (hnf? GPG_ERR_UNKNOWN_HOST
1596                                : gpg_err_code_from_syserror ()));
1597     }
1598   hd->sock = my_socket_new (sock);
1599   if (!hd->sock)
1600     {
1601       xfree (proxy_authstr);
1602       return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1603     }
1604
1605
1606
1607 #if HTTP_USE_NTBTLS
1608   if (hd->uri->use_tls)
1609     {
1610       my_socket_ref (hd->sock);
1611
1612       while ((err = ntbtls_handshake (hd->session->tls_session)))
1613         {
1614           switch (err)
1615             {
1616             default:
1617               log_info ("TLS handshake failed: %s <%s>\n",
1618                         gpg_strerror (err), gpg_strsource (err));
1619               xfree (proxy_authstr);
1620               return err;
1621             }
1622         }
1623
1624       hd->session->verify.done = 0;
1625       if (tls_callback)
1626         err = tls_callback (hd, hd->session, 0);
1627       else
1628         err = http_verify_server_credentials (hd->session);
1629       if (err)
1630         {
1631           log_info ("TLS connection authentication failed: %s <%s>\n",
1632                     gpg_strerror (err), gpg_strsource (err));
1633           xfree (proxy_authstr);
1634           return err;
1635         }
1636     }
1637 #elif HTTP_USE_GNUTLS
1638   if (hd->uri->use_tls)
1639     {
1640       int rc;
1641
1642       my_socket_ref (hd->sock);
1643       gnutls_transport_set_ptr (hd->session->tls_session, hd->sock);
1644 #ifdef USE_NPTH
1645       gnutls_transport_set_pull_function (hd->session->tls_session,
1646                                           my_npth_read);
1647       gnutls_transport_set_push_function (hd->session->tls_session,
1648                                           my_npth_write);
1649 #endif
1650
1651       do
1652         {
1653           rc = gnutls_handshake (hd->session->tls_session);
1654         }
1655       while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
1656       if (rc < 0)
1657         {
1658           if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED
1659               || rc == GNUTLS_E_FATAL_ALERT_RECEIVED)
1660             {
1661               gnutls_alert_description_t alertno;
1662               const char *alertstr;
1663
1664               alertno = gnutls_alert_get (hd->session->tls_session);
1665               alertstr = gnutls_alert_get_name (alertno);
1666               log_info ("TLS handshake failed: %s (alert %d)\n",
1667                         alertstr, (int)alertno);
1668               if (alertno == GNUTLS_A_UNRECOGNIZED_NAME && server)
1669                 log_info ("  (sent server name '%s')\n", server);
1670             }
1671           else
1672             log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
1673           xfree (proxy_authstr);
1674           return gpg_err_make (default_errsource, GPG_ERR_NETWORK);
1675         }
1676
1677       hd->session->verify.done = 0;
1678       if (tls_callback)
1679         err = tls_callback (hd, hd->session, 0);
1680       else
1681         err = http_verify_server_credentials (hd->session);
1682       if (err)
1683         {
1684           log_info ("TLS connection authentication failed: %s\n",
1685                     gpg_strerror (err));
1686           xfree (proxy_authstr);
1687           return err;
1688         }
1689     }
1690 #endif /*HTTP_USE_GNUTLS*/
1691
1692   if (auth || hd->uri->auth)
1693     {
1694       char *myauth;
1695
1696       if (auth)
1697         {
1698           myauth = xtrystrdup (auth);
1699           if (!myauth)
1700             {
1701               xfree (proxy_authstr);
1702               return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1703             }
1704           remove_escapes (myauth);
1705         }
1706       else
1707         {
1708           remove_escapes (hd->uri->auth);
1709           myauth = hd->uri->auth;
1710         }
1711
1712       authstr = make_header_line ("Authorization: Basic ", "\r\n",
1713                                   myauth, strlen (myauth));
1714       if (auth)
1715         xfree (myauth);
1716
1717       if (!authstr)
1718         {
1719           xfree (proxy_authstr);
1720           return gpg_err_make (default_errsource,
1721                                gpg_err_code_from_syserror ());
1722         }
1723     }
1724
1725   p = build_rel_path (hd->uri);
1726   if (!p)
1727     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1728
1729   if (http_proxy && *http_proxy)
1730     {
1731       request = es_bsprintf
1732         ("%s %s://%s:%hu%s%s HTTP/1.0\r\n%s%s",
1733          hd->req_type == HTTP_REQ_GET ? "GET" :
1734          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
1735          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
1736          hd->uri->use_tls? "https" : "http",
1737          httphost? httphost : server,
1738          port, *p == '/' ? "" : "/", p,
1739          authstr ? authstr : "",
1740          proxy_authstr ? proxy_authstr : "");
1741     }
1742   else
1743     {
1744       char portstr[35];
1745
1746       if (port == 80)
1747         *portstr = 0;
1748       else
1749         snprintf (portstr, sizeof portstr, ":%u", port);
1750
1751       request = es_bsprintf
1752         ("%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
1753          hd->req_type == HTTP_REQ_GET ? "GET" :
1754          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
1755          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
1756          *p == '/' ? "" : "/", p,
1757          httphost? httphost : server,
1758          portstr,
1759          authstr? authstr:"");
1760     }
1761   xfree (p);
1762   if (!request)
1763     {
1764       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1765       xfree (authstr);
1766       xfree (proxy_authstr);
1767       return err;
1768     }
1769
1770   /* log_debug ("request:\n%s\nEND request\n", request); */
1771
1772   /* First setup estream so that we can write even the first line
1773      using estream.  This is also required for the sake of gnutls. */
1774   {
1775     cookie_t cookie;
1776
1777     cookie = xtrycalloc (1, sizeof *cookie);
1778     if (!cookie)
1779       {
1780         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1781         goto leave;
1782       }
1783     cookie->sock = my_socket_ref (hd->sock);
1784     hd->write_cookie = cookie;
1785     cookie->use_tls = hd->uri->use_tls;
1786     cookie->session = http_session_ref (hd->session);
1787
1788     hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1789     if (!hd->fp_write)
1790       {
1791         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1792         my_socket_unref (cookie->sock, NULL, NULL);
1793         xfree (cookie);
1794         hd->write_cookie = NULL;
1795       }
1796     else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
1797       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1798     else
1799       err = 0;
1800
1801   if (!err)
1802     {
1803       for (;headers; headers=headers->next)
1804         {
1805           if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write))
1806               || (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write)))
1807             {
1808               err = gpg_err_make (default_errsource,
1809                                   gpg_err_code_from_syserror ());
1810               break;
1811             }
1812         }
1813     }
1814   }
1815
1816  leave:
1817   es_free (request);
1818   xfree (authstr);
1819   xfree (proxy_authstr);
1820
1821   return err;
1822 }
1823
1824
1825 /*
1826  * Build the relative path from the parsed URI.  Minimal
1827  * implementation.  May return NULL in case of memory failure; errno
1828  * is then set accordingly.
1829  */
1830 static char *
1831 build_rel_path (parsed_uri_t uri)
1832 {
1833   uri_tuple_t r;
1834   char *rel_path, *p;
1835   int n;
1836
1837   /* Count the needed space. */
1838   n = insert_escapes (NULL, uri->path, "%;?&");
1839   /* TODO: build params. */
1840   for (r = uri->query; r; r = r->next)
1841     {
1842       n++; /* '?'/'&' */
1843       n += insert_escapes (NULL, r->name, "%;?&=");
1844       if (!r->no_value)
1845         {
1846           n++; /* '=' */
1847           n += insert_escapes (NULL, r->value, "%;?&=");
1848         }
1849     }
1850   n++;
1851
1852   /* Now allocate and copy. */
1853   p = rel_path = xtrymalloc (n);
1854   if (!p)
1855     return NULL;
1856   n = insert_escapes (p, uri->path, "%;?&");
1857   p += n;
1858   /* TODO: add params. */
1859   for (r = uri->query; r; r = r->next)
1860     {
1861       *p++ = r == uri->query ? '?' : '&';
1862       n = insert_escapes (p, r->name, "%;?&=");
1863       p += n;
1864       if (!r->no_value)
1865         {
1866           *p++ = '=';
1867           /* TODO: Use valuelen. */
1868           n = insert_escapes (p, r->value, "%;?&=");
1869           p += n;
1870         }
1871     }
1872   *p = 0;
1873   return rel_path;
1874 }
1875
1876
1877 /* Transform a header name into a standard capitalized format; e.g.
1878    "Content-Type".  Conversion stops at the colon.  As usual we don't
1879    use the localized versions of ctype.h. */
1880 static void
1881 capitalize_header_name (char *name)
1882 {
1883   int first = 1;
1884
1885   for (; *name && *name != ':'; name++)
1886     {
1887       if (*name == '-')
1888         first = 1;
1889       else if (first)
1890         {
1891           if (*name >= 'a' && *name <= 'z')
1892             *name = *name - 'a' + 'A';
1893           first = 0;
1894         }
1895       else if (*name >= 'A' && *name <= 'Z')
1896         *name = *name - 'A' + 'a';
1897     }
1898 }
1899
1900
1901 /* Store an HTTP header line in LINE away.  Line continuation is
1902    supported as well as merging of headers with the same name. This
1903    function may modify LINE. */
1904 static gpg_err_code_t
1905 store_header (http_t hd, char *line)
1906 {
1907   size_t n;
1908   char *p, *value;
1909   header_t h;
1910
1911   n = strlen (line);
1912   if (n && line[n-1] == '\n')
1913     {
1914       line[--n] = 0;
1915       if (n && line[n-1] == '\r')
1916         line[--n] = 0;
1917     }
1918   if (!n)  /* we are never called to hit this. */
1919     return GPG_ERR_BUG;
1920   if (*line == ' ' || *line == '\t')
1921     {
1922       /* Continuation. This won't happen too often as it is not
1923          recommended.  We use a straightforward implementaion. */
1924       if (!hd->headers)
1925         return GPG_ERR_PROTOCOL_VIOLATION;
1926       n += strlen (hd->headers->value);
1927       p = xtrymalloc (n+1);
1928       if (!p)
1929         return gpg_err_code_from_syserror ();
1930       strcpy (stpcpy (p, hd->headers->value), line);
1931       xfree (hd->headers->value);
1932       hd->headers->value = p;
1933       return 0;
1934     }
1935
1936   capitalize_header_name (line);
1937   p = strchr (line, ':');
1938   if (!p)
1939     return GPG_ERR_PROTOCOL_VIOLATION;
1940   *p++ = 0;
1941   while (*p == ' ' || *p == '\t')
1942     p++;
1943   value = p;
1944
1945   for (h=hd->headers; h; h = h->next)
1946     if ( !strcmp (h->name, line) )
1947       break;
1948   if (h)
1949     {
1950       /* We have already seen a line with that name.  Thus we assume
1951          it is a comma separated list and merge them.  */
1952       p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1);
1953       if (!p)
1954         return gpg_err_code_from_syserror ();
1955       strcpy (stpcpy (stpcpy (p, h->value), ","), value);
1956       xfree (h->value);
1957       h->value = p;
1958       return 0;
1959     }
1960
1961   /* Append a new header. */
1962   h = xtrymalloc (sizeof *h + strlen (line));
1963   if (!h)
1964     return gpg_err_code_from_syserror ();
1965   strcpy (h->name, line);
1966   h->value = xtrymalloc (strlen (value)+1);
1967   if (!h->value)
1968     {
1969       xfree (h);
1970       return gpg_err_code_from_syserror ();
1971     }
1972   strcpy (h->value, value);
1973   h->next = hd->headers;
1974   hd->headers = h;
1975
1976   return 0;
1977 }
1978
1979
1980 /* Return the header NAME from the last response.  The returned value
1981    is valid as along as HD has not been closed and no other request
1982    has been send. If the header was not found, NULL is returned.  NAME
1983    must be canonicalized, that is the first letter of each dash
1984    delimited part must be uppercase and all other letters lowercase.  */
1985 const char *
1986 http_get_header (http_t hd, const char *name)
1987 {
1988   header_t h;
1989
1990   for (h=hd->headers; h; h = h->next)
1991     if ( !strcmp (h->name, name) )
1992       return h->value;
1993   return NULL;
1994 }
1995
1996
1997 /* Return a newly allocated and NULL terminated array with pointers to
1998    header names.  The array must be released with xfree() and its
1999    content is only values as long as no other request has been
2000    send.  */
2001 const char **
2002 http_get_header_names (http_t hd)
2003 {
2004   const char **array;
2005   size_t n;
2006   header_t h;
2007
2008   for (n=0, h = hd->headers; h; h = h->next)
2009     n++;
2010   array = xtrycalloc (n+1, sizeof *array);
2011   if (array)
2012     {
2013       for (n=0, h = hd->headers; h; h = h->next)
2014         array[n++] = h->name;
2015     }
2016
2017   return array;
2018 }
2019
2020
2021 /*
2022  * Parse the response from a server.
2023  * Returns: Errorcode and sets some files in the handle
2024  */
2025 static gpg_err_code_t
2026 parse_response (http_t hd)
2027 {
2028   char *line, *p, *p2;
2029   size_t maxlen, len;
2030   cookie_t cookie = hd->read_cookie;
2031   const char *s;
2032
2033   /* Delete old header lines.  */
2034   while (hd->headers)
2035     {
2036       header_t tmp = hd->headers->next;
2037       xfree (hd->headers->value);
2038       xfree (hd->headers);
2039       hd->headers = tmp;
2040     }
2041
2042   /* Wait for the status line. */
2043   do
2044     {
2045       maxlen = MAX_LINELEN;
2046       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2047       line = hd->buffer;
2048       if (!line)
2049         return gpg_err_code_from_syserror (); /* Out of core. */
2050       if (!maxlen)
2051         return GPG_ERR_TRUNCATED; /* Line has been truncated. */
2052       if (!len)
2053         return GPG_ERR_EOF;
2054
2055       if ((hd->flags & HTTP_FLAG_LOG_RESP))
2056         log_info ("RESP: '%.*s'\n",
2057                   (int)strlen(line)-(*line&&line[1]?2:0),line);
2058     }
2059   while (!*line);
2060
2061   if ((p = strchr (line, '/')))
2062     *p++ = 0;
2063   if (!p || strcmp (line, "HTTP"))
2064     return 0; /* Assume http 0.9. */
2065
2066   if ((p2 = strpbrk (p, " \t")))
2067     {
2068       *p2++ = 0;
2069       p2 += strspn (p2, " \t");
2070     }
2071   if (!p2)
2072     return 0; /* Also assume http 0.9. */
2073   p = p2;
2074   /* TODO: Add HTTP version number check. */
2075   if ((p2 = strpbrk (p, " \t")))
2076     *p2++ = 0;
2077   if (!isdigit ((unsigned int)p[0]) || !isdigit ((unsigned int)p[1])
2078       || !isdigit ((unsigned int)p[2]) || p[3])
2079     {
2080       /* Malformed HTTP status code - assume http 0.9. */
2081       hd->is_http_0_9 = 1;
2082       hd->status_code = 200;
2083       return 0;
2084     }
2085   hd->status_code = atoi (p);
2086
2087   /* Skip all the header lines and wait for the empty line. */
2088   do
2089     {
2090       maxlen = MAX_LINELEN;
2091       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2092       line = hd->buffer;
2093       if (!line)
2094         return gpg_err_code_from_syserror (); /* Out of core. */
2095       /* Note, that we can silently ignore truncated lines. */
2096       if (!len)
2097         return GPG_ERR_EOF;
2098       /* Trim line endings of empty lines. */
2099       if ((*line == '\r' && line[1] == '\n') || *line == '\n')
2100         *line = 0;
2101       if ((hd->flags & HTTP_FLAG_LOG_RESP))
2102         log_info ("RESP: '%.*s'\n",
2103                   (int)strlen(line)-(*line&&line[1]?2:0),line);
2104       if (*line)
2105         {
2106           gpg_err_code_t ec = store_header (hd, line);
2107           if (ec)
2108             return ec;
2109         }
2110     }
2111   while (len && *line);
2112
2113   cookie->content_length_valid = 0;
2114   if (!(hd->flags & HTTP_FLAG_IGNORE_CL))
2115     {
2116       s = http_get_header (hd, "Content-Length");
2117       if (s)
2118         {
2119           cookie->content_length_valid = 1;
2120           cookie->content_length = counter_strtoul (s);
2121         }
2122     }
2123
2124   return 0;
2125 }
2126
2127 #if 0
2128 static int
2129 start_server ()
2130 {
2131   struct sockaddr_in mya;
2132   struct sockaddr_in peer;
2133   int fd, client;
2134   fd_set rfds;
2135   int addrlen;
2136   int i;
2137
2138   if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
2139     {
2140       log_error ("socket() failed: %s\n", strerror (errno));
2141       return -1;
2142     }
2143   i = 1;
2144   if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (byte *) & i, sizeof (i)))
2145     log_info ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno));
2146
2147   mya.sin_family = AF_INET;
2148   memset (&mya.sin_addr, 0, sizeof (mya.sin_addr));
2149   mya.sin_port = htons (11371);
2150
2151   if (bind (fd, (struct sockaddr *) &mya, sizeof (mya)))
2152     {
2153       log_error ("bind to port 11371 failed: %s\n", strerror (errno));
2154       sock_close (fd);
2155       return -1;
2156     }
2157
2158   if (listen (fd, 5))
2159     {
2160       log_error ("listen failed: %s\n", strerror (errno));
2161       sock_close (fd);
2162       return -1;
2163     }
2164
2165   for (;;)
2166     {
2167       FD_ZERO (&rfds);
2168       FD_SET (fd, &rfds);
2169
2170       if (my_select (fd + 1, &rfds, NULL, NULL, NULL) <= 0)
2171         continue;               /* ignore any errors */
2172
2173       if (!FD_ISSET (fd, &rfds))
2174         continue;
2175
2176       addrlen = sizeof peer;
2177       client = my_accept (fd, (struct sockaddr *) &peer, &addrlen);
2178       if (client == -1)
2179         continue;               /* oops */
2180
2181       log_info ("connect from %s\n", inet_ntoa (peer.sin_addr));
2182
2183       fflush (stdout);
2184       fflush (stderr);
2185       if (!fork ())
2186         {
2187           int c;
2188           FILE *fp;
2189
2190           fp = fdopen (client, "r");
2191           while ((c = getc (fp)) != EOF)
2192             putchar (c);
2193           fclose (fp);
2194           exit (0);
2195         }
2196       sock_close (client);
2197     }
2198
2199
2200   return 0;
2201 }
2202 #endif
2203
2204 /* Actually connect to a server.  Returns the file descriptor or -1 on
2205    error.  ERRNO is set on error. */
2206 static assuan_fd_t
2207 connect_server (const char *server, unsigned short port,
2208                 unsigned int flags, const char *srvtag, int *r_host_not_found)
2209 {
2210   assuan_fd_t sock = ASSUAN_INVALID_FD;
2211   int srvcount = 0;
2212   int hostfound = 0;
2213   int anyhostaddr = 0;
2214   int srv, connected;
2215   int last_errno = 0;
2216   struct srventry *serverlist = NULL;
2217 #ifdef HAVE_W32_SYSTEM
2218   unsigned long inaddr;
2219 #endif
2220   int ret;
2221
2222   *r_host_not_found = 0;
2223 #ifdef HAVE_W32_SYSTEM
2224
2225 #ifndef HTTP_NO_WSASTARTUP
2226   init_sockets ();
2227 #endif
2228   /* Win32 gethostbyname doesn't handle IP addresses internally, so we
2229      try inet_addr first on that platform only. */
2230   inaddr = inet_addr(server);
2231   if ( inaddr != INADDR_NONE )
2232     {
2233       struct sockaddr_in addr;
2234
2235       memset(&addr,0,sizeof(addr));
2236
2237       sock = assuan_sock_new (AF_INET, SOCK_STREAM, 0);
2238       if (sock == ASSUAN_INVALID_FD)
2239         {
2240           log_error ("error creating socket: %s\n", strerror (errno));
2241           return ASSUAN_INVALID_FD;
2242         }
2243
2244       addr.sin_family = AF_INET;
2245       addr.sin_port = htons(port);
2246       memcpy (&addr.sin_addr,&inaddr,sizeof(inaddr));
2247
2248       my_unprotect ();
2249       ret = assuan_sock_connect (sock,(struct sockaddr *)&addr,sizeof(addr));
2250       my_protect ();
2251       if (!ret)
2252         return sock;
2253       assuan_sock_close (sock);
2254       return ASSUAN_INVALID_FD;
2255     }
2256 #endif /*HAVE_W32_SYSTEM*/
2257
2258 #ifdef USE_DNS_SRV
2259   /* Do the SRV thing */
2260   if (srvtag)
2261     {
2262       /* We're using SRV, so append the tags. */
2263       if (1+strlen (srvtag) + 6 + strlen (server) + 1 <= MAXDNAME)
2264         {
2265           char srvname[MAXDNAME];
2266
2267           stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srvtag),
2268                            "._tcp."), server);
2269           srvcount = getsrv (srvname, &serverlist);
2270         }
2271     }
2272 #else
2273   (void)flags;
2274   (void)srvtag;
2275 #endif /*USE_DNS_SRV*/
2276
2277   if (!serverlist)
2278     {
2279       /* Either we're not using SRV, or the SRV lookup failed.  Make
2280          up a fake SRV record. */
2281       serverlist = xtrycalloc (1, sizeof *serverlist);
2282       if (!serverlist)
2283         return -1; /* Out of core.  */
2284       serverlist->port = port;
2285       strncpy (serverlist->target, server, MAXDNAME);
2286       serverlist->target[MAXDNAME-1] = '\0';
2287       srvcount = 1;
2288     }
2289
2290 #ifdef HAVE_GETADDRINFO
2291   connected = 0;
2292   for (srv=0; srv < srvcount && !connected; srv++)
2293     {
2294       struct addrinfo hints, *res, *ai;
2295       char portstr[35];
2296
2297       snprintf (portstr, sizeof portstr, "%hu", port);
2298       memset (&hints, 0, sizeof (hints));
2299       hints.ai_socktype = SOCK_STREAM;
2300       if (getaddrinfo (serverlist[srv].target, portstr, &hints, &res))
2301         continue; /* Not found - try next one. */
2302       hostfound = 1;
2303
2304       for (ai = res; ai && !connected; ai = ai->ai_next)
2305         {
2306           if (ai->ai_family == AF_INET && (flags & HTTP_FLAG_IGNORE_IPv4))
2307             continue;
2308           if (ai->ai_family == AF_INET6 && (flags & HTTP_FLAG_IGNORE_IPv6))
2309             continue;
2310
2311           if (sock != ASSUAN_INVALID_FD)
2312             assuan_sock_close (sock);
2313           sock = assuan_sock_new (ai->ai_family, ai->ai_socktype,
2314                                   ai->ai_protocol);
2315           if (sock == ASSUAN_INVALID_FD)
2316             {
2317               int save_errno = errno;
2318               log_error ("error creating socket: %s\n", strerror (errno));
2319               freeaddrinfo (res);
2320               xfree (serverlist);
2321               errno = save_errno;
2322               return ASSUAN_INVALID_FD;
2323             }
2324
2325           anyhostaddr = 1;
2326           my_unprotect ();
2327           ret = assuan_sock_connect (sock, ai->ai_addr, ai->ai_addrlen);
2328           my_protect ();
2329           if (ret)
2330             last_errno = errno;
2331           else
2332             connected = 1;
2333         }
2334       freeaddrinfo (res);
2335     }
2336 #else /* !HAVE_GETADDRINFO */
2337   connected = 0;
2338   for (srv=0; srv < srvcount && !connected; srv++)
2339     {
2340       int i;
2341       struct hostent *host = NULL;
2342       struct sockaddr_in addr;
2343
2344       /* Note: This code is not thread-safe.  */
2345
2346       memset (&addr, 0, sizeof (addr));
2347       host = gethostbyname (serverlist[srv].target);
2348       if (!host)
2349         continue;
2350       hostfound = 1;
2351
2352       if (sock != ASSUAN_INVALID_FD)
2353         assuan_sock_close (sock);
2354       sock = assuan_sock_new (host->h_addrtype, SOCK_STREAM, 0);
2355       if (sock == ASSUAN_INVALID_FD)
2356         {
2357           log_error ("error creating socket: %s\n", strerror (errno));
2358           xfree (serverlist);
2359           return ASSUAN_INVALID_FD;
2360         }
2361
2362       addr.sin_family = host->h_addrtype;
2363       if (addr.sin_family != AF_INET)
2364         {
2365           log_error ("unknown address family for '%s'\n",
2366                      serverlist[srv].target);
2367           xfree (serverlist);
2368           return ASSUAN_INVALID_FD;
2369         }
2370       addr.sin_port = htons (serverlist[srv].port);
2371       if (host->h_length != 4)
2372         {
2373           log_error ("illegal address length for '%s'\n",
2374                      serverlist[srv].target);
2375           xfree (serverlist);
2376           return ASSUAN_INVALID_FD;
2377         }
2378
2379       /* Try all A records until one responds. */
2380       for (i = 0; host->h_addr_list[i] && !connected; i++)
2381         {
2382           anyhostaddr = 1;
2383           memcpy (&addr.sin_addr, host->h_addr_list[i], host->h_length);
2384           my_unprotect ();
2385           ret = assuan_sock_connect (sock,
2386                                      (struct sockaddr *) &addr, sizeof (addr));
2387           my_protect ();
2388           if (ret)
2389             last_errno = errno;
2390           else
2391             {
2392               connected = 1;
2393               break;
2394             }
2395         }
2396     }
2397 #endif /* !HAVE_GETADDRINFO */
2398
2399   xfree (serverlist);
2400
2401   if (!connected)
2402     {
2403       if (!hostfound)
2404         log_error ("can't connect to '%s': %s\n",
2405                    server, "host not found");
2406       else if (!anyhostaddr)
2407         log_error ("can't connect to '%s': %s\n",
2408                    server, "no IP address for host");
2409       else
2410         {
2411 #ifdef HAVE_W32_SYSTEM
2412         log_error ("can't connect to '%s': ec=%d\n",
2413                    server, (int)WSAGetLastError());
2414 #else
2415         log_error ("can't connect to '%s': %s\n",
2416                    server, strerror (last_errno));
2417 #endif
2418         }
2419       if (!hostfound || (hostfound && !anyhostaddr))
2420         *r_host_not_found = 1;
2421       if (sock != ASSUAN_INVALID_FD)
2422         assuan_sock_close (sock);
2423       gpg_err_set_errno (last_errno);
2424       return ASSUAN_INVALID_FD;
2425     }
2426   return sock;
2427 }
2428
2429
2430 static gpg_error_t
2431 write_server (int sock, const char *data, size_t length)
2432 {
2433   int nleft;
2434   int nwritten;
2435
2436   nleft = length;
2437   while (nleft > 0)
2438     {
2439 #if defined(HAVE_W32_SYSTEM)
2440 # if defined(USE_NPTH)
2441       npth_unprotect ();
2442 # endif
2443       nwritten = send (sock, data, nleft, 0);
2444 # if defined(USE_NPTH)
2445       npth_protect ();
2446 # endif
2447       if ( nwritten == SOCKET_ERROR )
2448         {
2449           log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
2450           return gpg_error (GPG_ERR_NETWORK);
2451         }
2452 #else /*!HAVE_W32_SYSTEM*/
2453 # ifdef USE_NPTH
2454       nwritten = npth_write (sock, data, nleft);
2455 # else
2456       nwritten = write (sock, data, nleft);
2457 # endif
2458       if (nwritten == -1)
2459         {
2460           if (errno == EINTR)
2461             continue;
2462           if (errno == EAGAIN)
2463             {
2464               struct timeval tv;
2465
2466               tv.tv_sec = 0;
2467               tv.tv_usec = 50000;
2468               my_select (0, NULL, NULL, NULL, &tv);
2469               continue;
2470             }
2471           log_info ("network write failed: %s\n", strerror (errno));
2472           return gpg_error_from_syserror ();
2473         }
2474 #endif /*!HAVE_W32_SYSTEM*/
2475       nleft -= nwritten;
2476       data += nwritten;
2477     }
2478
2479   return 0;
2480 }
2481
2482
2483 \f
2484 /* Read handler for estream.  */
2485 static ssize_t
2486 cookie_read (void *cookie, void *buffer, size_t size)
2487 {
2488   cookie_t c = cookie;
2489   int nread;
2490
2491   if (c->content_length_valid)
2492     {
2493       if (!c->content_length)
2494         return 0; /* EOF */
2495       if (c->content_length < size)
2496         size = c->content_length;
2497     }
2498
2499 #ifdef HTTP_USE_GNUTLS
2500   if (c->use_tls && c->session && c->session->tls_session)
2501     {
2502     again:
2503       nread = gnutls_record_recv (c->session->tls_session, buffer, size);
2504       if (nread < 0)
2505         {
2506           if (nread == GNUTLS_E_INTERRUPTED)
2507             goto again;
2508           if (nread == GNUTLS_E_AGAIN)
2509             {
2510               struct timeval tv;
2511
2512               tv.tv_sec = 0;
2513               tv.tv_usec = 50000;
2514               my_select (0, NULL, NULL, NULL, &tv);
2515               goto again;
2516             }
2517           if (nread == GNUTLS_E_REHANDSHAKE)
2518             goto again; /* A client is allowed to just ignore this request. */
2519           log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
2520           gpg_err_set_errno (EIO);
2521           return -1;
2522         }
2523     }
2524   else
2525 #endif /*HTTP_USE_GNUTLS*/
2526     {
2527       do
2528         {
2529 #ifdef HAVE_W32_SYSTEM
2530           /* Under Windows we need to use recv for a socket.  */
2531 # if defined(USE_NPTH)
2532           npth_unprotect ();
2533 # endif
2534           nread = recv (c->sock->fd, buffer, size, 0);
2535 # if defined(USE_NPTH)
2536           npth_protect ();
2537 # endif
2538
2539 #else /*!HAVE_W32_SYSTEM*/
2540
2541 # ifdef USE_NPTH
2542           nread = npth_read (c->sock->fd, buffer, size);
2543 # else
2544           nread = read (c->sock->fd, buffer, size);
2545 # endif
2546
2547 #endif /*!HAVE_W32_SYSTEM*/
2548         }
2549       while (nread == -1 && errno == EINTR);
2550     }
2551
2552   if (c->content_length_valid && nread > 0)
2553     {
2554       if (nread < c->content_length)
2555         c->content_length -= nread;
2556       else
2557         c->content_length = 0;
2558     }
2559
2560   return nread;
2561 }
2562
2563 /* Write handler for estream.  */
2564 static ssize_t
2565 cookie_write (void *cookie, const void *buffer_arg, size_t size)
2566 {
2567   const char *buffer = buffer_arg;
2568   cookie_t c = cookie;
2569   int nwritten = 0;
2570
2571 #ifdef HTTP_USE_GNUTLS
2572   if (c->use_tls && c->session && c->session->tls_session)
2573     {
2574       int nleft = size;
2575       while (nleft > 0)
2576         {
2577           nwritten = gnutls_record_send (c->session->tls_session,
2578                                          buffer, nleft);
2579           if (nwritten <= 0)
2580             {
2581               if (nwritten == GNUTLS_E_INTERRUPTED)
2582                 continue;
2583               if (nwritten == GNUTLS_E_AGAIN)
2584                 {
2585                   struct timeval tv;
2586
2587                   tv.tv_sec = 0;
2588                   tv.tv_usec = 50000;
2589                   my_select (0, NULL, NULL, NULL, &tv);
2590                   continue;
2591                 }
2592               log_info ("TLS network write failed: %s\n",
2593                         gnutls_strerror (nwritten));
2594               gpg_err_set_errno (EIO);
2595               return -1;
2596             }
2597           nleft -= nwritten;
2598           buffer += nwritten;
2599         }
2600     }
2601   else
2602 #endif /*HTTP_USE_GNUTLS*/
2603     {
2604       if ( write_server (c->sock->fd, buffer, size) )
2605         {
2606           gpg_err_set_errno (EIO);
2607           nwritten = -1;
2608         }
2609       else
2610         nwritten = size;
2611     }
2612
2613   return nwritten;
2614 }
2615
2616
2617 #ifdef HTTP_USE_GNUTLS
2618 /* Wrapper for gnutls_bye used by my_socket_unref.  */
2619 static void
2620 send_gnutls_bye (void *opaque)
2621 {
2622   tls_session_t tls_session = opaque;
2623   int ret;
2624
2625  again:
2626   do
2627     ret = gnutls_bye (tls_session, GNUTLS_SHUT_RDWR);
2628   while (ret == GNUTLS_E_INTERRUPTED);
2629   if (ret == GNUTLS_E_AGAIN)
2630     {
2631       struct timeval tv;
2632
2633       tv.tv_sec = 0;
2634       tv.tv_usec = 50000;
2635       my_select (0, NULL, NULL, NULL, &tv);
2636       goto again;
2637     }
2638 }
2639 #endif /*HTTP_USE_GNUTLS*/
2640
2641 /* Close handler for estream.  */
2642 static int
2643 cookie_close (void *cookie)
2644 {
2645   cookie_t c = cookie;
2646
2647   if (!c)
2648     return 0;
2649
2650 #ifdef HTTP_USE_GNUTLS
2651   if (c->use_tls && c->session && c->session->tls_session)
2652     my_socket_unref (c->sock, send_gnutls_bye, c->session->tls_session);
2653   else
2654 #endif /*HTTP_USE_GNUTLS*/
2655     if (c->sock)
2656       my_socket_unref (c->sock, NULL, NULL);
2657
2658   if (c->session)
2659     http_session_unref (c->session);
2660   xfree (c);
2661   return 0;
2662 }
2663
2664
2665
2666 \f
2667 /* Verify the credentials of the server.  Returns 0 on success and
2668    store the result in the session object.  */
2669 gpg_error_t
2670 http_verify_server_credentials (http_session_t sess)
2671 {
2672 #if HTTP_USE_NTBTLS
2673   (void)sess;
2674   return 0;  /* FIXME!! */
2675 #elif HTTP_USE_GNUTLS
2676   static const char const errprefix[] = "TLS verification of peer failed";
2677   int rc;
2678   unsigned int status;
2679   const char *hostname;
2680   const gnutls_datum_t *certlist;
2681   unsigned int certlistlen;
2682   gnutls_x509_crt_t cert;
2683   gpg_error_t err = 0;
2684
2685   sess->verify.done = 1;
2686   sess->verify.status = 0;
2687   sess->verify.rc = GNUTLS_E_CERTIFICATE_ERROR;
2688
2689   if (gnutls_certificate_type_get (sess->tls_session) != GNUTLS_CRT_X509)
2690     {
2691       log_error ("%s: %s\n", errprefix, "not an X.509 certificate");
2692       sess->verify.rc = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
2693       return gpg_error (GPG_ERR_GENERAL);
2694     }
2695
2696   rc = gnutls_certificate_verify_peers2 (sess->tls_session, &status);
2697   if (rc)
2698     {
2699       log_error ("%s: %s\n", errprefix, gnutls_strerror (rc));
2700       if (!err)
2701         err = gpg_error (GPG_ERR_GENERAL);
2702     }
2703   else if (status)
2704     {
2705       log_error ("%s: status=0x%04x\n", errprefix, status);
2706 #if GNUTLS_VERSION_NUMBER >= 0x030104
2707       {
2708         gnutls_datum_t statusdat;
2709
2710         if (!gnutls_certificate_verification_status_print
2711             (status, GNUTLS_CRT_X509, &statusdat, 0))
2712           {
2713             log_info ("%s: %s\n", errprefix, statusdat.data);
2714             gnutls_free (statusdat.data);
2715           }
2716       }
2717 #endif /*gnutls >= 3.1.4*/
2718
2719       sess->verify.status = status;
2720       if (!err)
2721         err = gpg_error (GPG_ERR_GENERAL);
2722     }
2723
2724   hostname = sess->servername;
2725   if (!hostname || !strchr (hostname, '.'))
2726     {
2727       log_error ("%s: %s\n", errprefix, "hostname missing");
2728       if (!err)
2729         err = gpg_error (GPG_ERR_GENERAL);
2730     }
2731
2732   certlist = gnutls_certificate_get_peers (sess->tls_session, &certlistlen);
2733   if (!certlistlen)
2734     {
2735       log_error ("%s: %s\n", errprefix, "server did not send a certificate");
2736       if (!err)
2737         err = gpg_error (GPG_ERR_GENERAL);
2738
2739       /* Need to stop here.  */
2740       if (err)
2741         return err;
2742     }
2743
2744   rc = gnutls_x509_crt_init (&cert);
2745   if (rc < 0)
2746     {
2747       if (!err)
2748         err = gpg_error (GPG_ERR_GENERAL);
2749       if (err)
2750         return err;
2751     }
2752
2753   rc = gnutls_x509_crt_import (cert, &certlist[0], GNUTLS_X509_FMT_DER);
2754   if (rc < 0)
2755     {
2756       log_error ("%s: %s: %s\n", errprefix, "error importing certificate",
2757                  gnutls_strerror (rc));
2758       if (!err)
2759         err = gpg_error (GPG_ERR_GENERAL);
2760     }
2761
2762   if (!gnutls_x509_crt_check_hostname (cert, hostname))
2763     {
2764       log_error ("%s: %s\n", errprefix, "hostname does not match");
2765       if (!err)
2766         err = gpg_error (GPG_ERR_GENERAL);
2767     }
2768
2769   gnutls_x509_crt_deinit (cert);
2770
2771   if (!err)
2772     sess->verify.rc = 0;
2773
2774   if (sess->cert_log_cb)
2775     {
2776       const void *bufarr[10];
2777       size_t buflenarr[10];
2778       size_t n;
2779
2780       for (n = 0; n < certlistlen && n < DIM (bufarr)-1; n++)
2781         {
2782           bufarr[n] = certlist[n].data;
2783           buflenarr[n] = certlist[n].size;
2784         }
2785       bufarr[n] = NULL;
2786       buflenarr[n] = 0;
2787       sess->cert_log_cb (sess, err, hostname, bufarr, buflenarr);
2788     }
2789
2790   return err;
2791 #else /*!HTTP_USE_GNUTLS*/
2792   (void)sess;
2793   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2794 #endif
2795 }
2796
2797 /* Return the first query variable with the specified key.  If there
2798    is no such variable, return NULL.  */
2799 struct uri_tuple_s *
2800 uri_query_lookup (parsed_uri_t uri, const char *key)
2801 {
2802   struct uri_tuple_s *t;
2803
2804   for (t = uri->query; t; t = t->next)
2805     if (strcmp (t->name, key) == 0)
2806       return t;
2807
2808   return NULL;
2809 }