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