Exporting secret keys via gpg-agent is now basically supported.
[gnupg.git] / common / http.c
1 /* http.c  -  HTTP protocol handler
2  * Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006,
3  *               2009, 2010 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /* Simple HTTP client implementation.  We try to keep the code as
22    self-contained as possible.  There are some contraints however:
23
24   - estream is required.  We now require estream because it provides a
25     very useful and portable asprintf implementation and the fopencookie
26     function.
27   - stpcpy is required
28   - fixme: list other requirements.
29
30
31   - With HTTP_USE_GNUTLS support for https is provided (this also
32     requires estream).
33   - With HTTP_NO_WSASTARTUP the socket initialization is not done
34     under Windows.  This is useful if the socket layer has already
35     been initialized elsewhere.  This also avoids the installation of
36     an exit handler to cleanup the socket layer.
37 */
38
39 #ifdef HAVE_CONFIG_H
40 # include <config.h>
41 #endif
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <stdarg.h>
45 #include <string.h>
46 #include <ctype.h>
47 #include <errno.h>
48 #include <unistd.h>
49
50 #ifdef HAVE_W32_SYSTEM
51 # include <windows.h>
52 #else /*!HAVE_W32_SYSTEM*/
53 # include <sys/types.h>
54 # include <sys/socket.h>
55 # include <sys/time.h>
56 # include <time.h>
57 # include <netinet/in.h>
58 # include <arpa/inet.h>
59 # include <netdb.h>
60 #endif /*!HAVE_W32_SYSTEM*/
61
62 #ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth.  */
63 # undef HAVE_PTH
64 # undef USE_GNU_PTH
65 #endif
66
67 #ifdef HAVE_PTH
68 # include <pth.h>
69 #endif
70
71
72 #ifdef HTTP_USE_GNUTLS
73 # include <gnutls/gnutls.h>
74 /* For non-understandable reasons GNUTLS dropped the _t suffix from
75    all types. yes, ISO-C might be read as this but there are still
76    other name space conflicts and using _t is actually a Good
77    Thing. */
78 typedef gnutls_session gnutls_session_t;
79 typedef gnutls_transport_ptr gnutls_transport_ptr_t;
80 #endif /*HTTP_USE_GNUTLS*/
81
82 #ifdef TEST
83 #undef USE_DNS_SRV
84 #endif
85
86 #include "util.h"
87 #include "i18n.h"
88 #include "http.h"
89 #ifdef USE_DNS_SRV
90 # include "srv.h"
91 #else /*!USE_DNS_SRV*/
92   /* If we are not compiling with SRV record support we provide stub
93      data structures. */
94 # ifndef MAXDNAME
95 #  define MAXDNAME 1025
96 # endif
97 struct srventry
98 {
99   unsigned short priority;
100   unsigned short weight;
101   unsigned short port;
102   int run_count;
103   char target[MAXDNAME];
104 };
105 #endif/*!USE_DNS_SRV*/
106
107
108 #ifdef HAVE_W32_SYSTEM
109 #define sock_close(a)  closesocket(a)
110 #else
111 #define sock_close(a)  close(a)
112 #endif
113
114 #ifndef EAGAIN
115 #define EAGAIN  EWOULDBLOCK
116 #endif
117 #ifndef INADDR_NONE  /* Slowaris is missing that.  */
118 #define INADDR_NONE  ((unsigned long)(-1))
119 #endif /*INADDR_NONE*/
120
121 #define HTTP_PROXY_ENV           "http_proxy"
122 #define MAX_LINELEN 20000  /* Max. length of a HTTP header line. */
123 #define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz"   \
124                         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"   \
125                         "01234567890@"                 \
126                         "!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~"
127
128 /* A long counter type.  */
129 #ifdef HAVE_STRTOULL
130 typedef unsigned long long longcounter_t;
131 # define counter_strtoul(a) strtoull ((a), NULL, 10)
132 #else
133 typedef unsigned long longcounter_t;
134 # define counter_strtoul(a) strtoul ((a), NULL, 10)
135 #endif
136
137 #ifndef HTTP_USE_GNUTLS
138 typedef void * gnutls_session_t;
139 #endif
140
141 static gpg_err_code_t do_parse_uri (parsed_uri_t uri, int only_local_part);
142 static int remove_escapes (char *string);
143 static int insert_escapes (char *buffer, const char *string,
144                            const char *special);
145 static uri_tuple_t parse_tuple (char *string);
146 static gpg_error_t send_request (http_t hd, const char *auth,const char *proxy,
147                                  const char *srvtag,strlist_t headers,
148                                  gpg_err_source_t errsource);
149 static char *build_rel_path (parsed_uri_t uri);
150 static gpg_error_t parse_response (http_t hd);
151
152 static int connect_server (const char *server, unsigned short port,
153                            unsigned int flags, const char *srvtag);
154 static gpg_error_t write_server (int sock, const char *data, size_t length);
155
156 static ssize_t cookie_read (void *cookie, void *buffer, size_t size);
157 static ssize_t cookie_write (void *cookie, const void *buffer, size_t size);
158 static int cookie_close (void *cookie);
159
160 static es_cookie_io_functions_t cookie_functions =
161   {
162     cookie_read,
163     cookie_write,
164     NULL,
165     cookie_close
166   };
167
168 struct cookie_s 
169 {
170   /* File descriptor or -1 if already closed. */
171   int fd;
172
173   /* TLS session context or NULL if not used. */
174   gnutls_session_t tls_session; 
175
176   /* The remaining content length and a flag telling whether to use
177      the content length.  */
178   longcounter_t content_length;  
179   unsigned int content_length_valid:1;
180
181   /* Flag to communicate with the close handler. */
182   unsigned int keep_socket:1; 
183 };
184 typedef struct cookie_s *cookie_t;
185
186 #ifdef HTTP_USE_GNUTLS
187 static gpg_error_t (*tls_callback) (http_t, gnutls_session_t, int);
188 #endif /*HTTP_USE_GNUTLS*/
189
190
191 /* An object to save header lines. */
192 struct header_s
193 {
194   struct header_s *next;
195   char *value;    /* The value of the header (malloced).  */
196   char name[1];   /* The name of the header (canonicalized). */
197 };
198 typedef struct header_s *header_t;
199
200
201 /* Our handle context. */
202 struct http_context_s 
203 {
204   unsigned int status_code;
205   int sock;
206   unsigned int in_data:1;
207   unsigned int is_http_0_9:1;
208   estream_t fp_read;
209   estream_t fp_write;
210   void *write_cookie;
211   void *read_cookie;
212   void *tls_context;
213   parsed_uri_t uri;
214   http_req_t req_type;
215   char *buffer;          /* Line buffer. */
216   size_t buffer_size;
217   unsigned int flags;
218   header_t headers;      /* Received headers. */
219 };
220
221
222
223 \f
224 #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
225
226 #if GNUPG_MAJOR_VERSION == 1
227 #define REQ_WINSOCK_MAJOR  1
228 #define REQ_WINSOCK_MINOR  1
229 #else
230 #define REQ_WINSOCK_MAJOR  2
231 #define REQ_WINSOCK_MINOR  2
232 #endif
233
234
235 static void
236 deinit_sockets (void)
237 {
238   WSACleanup();
239 }
240
241 static void
242 init_sockets (void)
243 {
244   static int initialized;
245   static WSADATA wsdata;
246
247   if (initialized)
248     return;
249
250   if ( WSAStartup( MAKEWORD (REQ_WINSOCK_MINOR, REQ_WINSOCK_MAJOR), &wsdata ) ) 
251     {
252       log_error ("error initializing socket library: ec=%d\n", 
253                  (int)WSAGetLastError () );
254       return;
255     }
256   if ( LOBYTE(wsdata.wVersion) != REQ_WINSOCK_MAJOR  
257        || HIBYTE(wsdata.wVersion) != REQ_WINSOCK_MINOR ) 
258     {
259       log_error ("socket library version is %x.%x - but %d.%d needed\n",
260                  LOBYTE(wsdata.wVersion), HIBYTE(wsdata.wVersion),
261                  REQ_WINSOCK_MAJOR, REQ_WINSOCK_MINOR);
262       WSACleanup();
263       return;
264     }
265   atexit ( deinit_sockets );
266   initialized = 1;
267 }
268 #endif /*HAVE_W32_SYSTEM && !HTTP_NO_WSASTARTUP*/
269
270
271
272 /*
273  * Helper function to create an HTTP header with hex encoded data.  A
274  * new buffer is returned.  This buffer is the concatenation of the
275  * string PREFIX, the hex-encoded DATA of length LEN and the string
276  * SUFFIX.  On error NULL is returned and ERRNO set.
277  */
278 static char *
279 make_header_line (const char *prefix, const char *suffix,
280                    const void *data, size_t len )
281 {
282   static unsigned char bintoasc[] = 
283     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
284     "abcdefghijklmnopqrstuvwxyz"
285     "0123456789+/";
286   const unsigned int *s = data;
287   char *buffer, *p;
288
289   buffer = xtrymalloc (strlen (prefix) + (len+2)/3*4 + strlen (suffix) + 1);
290   if (!buffer)
291     return NULL;
292   p = stpcpy (buffer, prefix);
293   for ( ; len >= 3 ; len -= 3, s += 3 )
294     {
295       *p++ = bintoasc[(s[0] >> 2) & 077];
296       *p++ = bintoasc[(((s[0] <<4)&060)|((s[1] >> 4)&017))&077];
297       *p++ = bintoasc[(((s[1]<<2)&074)|((s[2]>>6)&03))&077];
298       *p++ = bintoasc[s[2]&077];
299     }
300   if ( len == 2 ) 
301     {
302       *p++ = bintoasc[(s[0] >> 2) & 077];
303       *p++ = bintoasc[(((s[0] <<4)&060)|((s[1] >> 4)&017))&077];
304       *p++ = bintoasc[((s[1]<<2)&074)];
305       *p++ = '=';
306     }
307   else if ( len == 1 )
308     {
309       *p++ = bintoasc[(s[0] >> 2) & 077];
310       *p++ = bintoasc[(s[0] <<4)&060];
311       *p++ = '=';
312       *p++ = '=';
313     }
314   strcpy (p, suffix);
315   return buffer;
316 }
317
318
319
320 \f
321 void
322 http_register_tls_callback ( gpg_error_t (*cb) (http_t, void *, int) )
323 {
324 #ifdef HTTP_USE_GNUTLS
325   tls_callback = (gpg_error_t (*) (http_t, gnutls_session_t, int))cb;
326 #else
327   (void)cb;
328 #endif  
329 }
330
331
332
333 /* Start a HTTP retrieval and return on success in R_HD a context
334    pointer for completing the the request and to wait for the
335    response. */
336 gpg_error_t
337 _http_open (http_t *r_hd, http_req_t reqtype, const char *url, 
338             const char *auth, unsigned int flags, const char *proxy,
339             void *tls_context, const char *srvtag, strlist_t headers,
340             gpg_err_source_t errsource)
341 {
342   gpg_error_t err;
343   http_t hd;
344   
345   *r_hd = NULL;
346
347   if (!(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST))
348     return gpg_err_make (errsource, GPG_ERR_INV_ARG);
349
350   /* Create the handle. */
351   hd = xtrycalloc (1, sizeof *hd);
352   if (!hd)
353     return gpg_error_from_syserror ();
354   hd->sock = -1;
355   hd->req_type = reqtype;
356   hd->flags = flags;
357   hd->tls_context = tls_context;
358
359   err = _http_parse_uri (&hd->uri, url, errsource);
360   if (!err)
361     err = send_request (hd, auth, proxy, srvtag, headers, errsource);
362   
363   if (err)
364     {
365       if (!hd->fp_read && !hd->fp_write && hd->sock != -1)
366         sock_close (hd->sock);
367       if (hd->fp_read)
368         es_fclose (hd->fp_read);
369       if (hd->fp_write)
370         es_fclose (hd->fp_write);
371       http_release_parsed_uri (hd->uri);
372       xfree (hd);
373     }
374   else
375     *r_hd = hd;
376   return err;
377 }
378
379
380 void
381 http_start_data (http_t hd)
382 {
383   if (!hd->in_data)
384     {
385       es_fputs ("\r\n", hd->fp_write);
386       es_fflush (hd->fp_write);
387       hd->in_data = 1;
388     }
389   else
390     es_fflush (hd->fp_write);
391 }
392
393
394 gpg_error_t
395 _http_wait_response (http_t hd, gpg_err_source_t errsource)
396 {
397   gpg_error_t err;
398   cookie_t cookie;
399
400   /* Make sure that we are in the data. */
401   http_start_data (hd); 
402
403   /* Close the write stream but keep the socket open.  */
404   cookie = hd->write_cookie;
405   if (!cookie)
406     return gpg_err_make (errsource, GPG_ERR_INTERNAL);
407
408   cookie->keep_socket = 1;
409   es_fclose (hd->fp_write);
410   hd->fp_write = NULL;
411   /* The close has released the cookie and thus we better set it to NULL.  */
412   hd->write_cookie = NULL;
413
414   /* Shutdown one end of the socket is desired.  As per HTTP/1.0 this
415      is not required but some very old servers (e.g. the original pksd
416      key server didn't worked without it.  */
417   if ((hd->flags & HTTP_FLAG_SHUTDOWN))
418     shutdown (hd->sock, 1);
419   hd->in_data = 0;
420
421   /* Create a new cookie and a stream for reading.  */
422   cookie = xtrycalloc (1, sizeof *cookie);
423   if (!cookie)
424     return gpg_err_make (errsource, gpg_err_code_from_syserror ());
425   cookie->fd = hd->sock;
426   if (hd->uri->use_tls)
427     cookie->tls_session = hd->tls_context;
428
429   hd->read_cookie = cookie;
430   hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
431   if (!hd->fp_read)
432     {
433       xfree (cookie);
434       hd->read_cookie = NULL;
435       return gpg_err_make (errsource, gpg_err_code_from_syserror ());
436     }
437
438   err = parse_response (hd);
439   return err;
440 }
441
442
443 /* Convenience function to send a request and wait for the response.
444    Closes the handle on error.  If PROXY is not NULL, this value will
445    be used as an HTTP proxy and any enabled $http_proxy gets
446    ignored. */
447 gpg_error_t
448 _http_open_document (http_t *r_hd, const char *document, 
449                      const char *auth, unsigned int flags, const char *proxy,
450                      void *tls_context, const char *srvtag, strlist_t headers,
451                      gpg_err_source_t errsource)
452 {
453   gpg_error_t err;
454
455   err = _http_open (r_hd, HTTP_REQ_GET, document, auth, flags,
456                     proxy, tls_context, srvtag, headers, errsource);
457   if (err)
458     return err;
459
460   err = _http_wait_response (*r_hd, errsource);
461   if (err)
462     http_close (*r_hd, 0);
463
464   return err;
465 }
466
467
468 void
469 http_close (http_t hd, int keep_read_stream)
470 {
471   if (!hd)
472     return;
473   if (!hd->fp_read && !hd->fp_write && hd->sock != -1)
474     sock_close (hd->sock);
475   if (hd->fp_read && !keep_read_stream)
476     es_fclose (hd->fp_read);
477   if (hd->fp_write)
478     es_fclose (hd->fp_write);
479   http_release_parsed_uri (hd->uri);
480   while (hd->headers)
481     {
482       header_t tmp = hd->headers->next;
483       xfree (hd->headers->value);
484       xfree (hd->headers);
485       hd->headers = tmp;
486     }
487   xfree (hd->buffer);
488   xfree (hd);
489 }
490
491
492 estream_t
493 http_get_read_ptr (http_t hd)
494 {
495   return hd?hd->fp_read:NULL;
496 }
497
498 estream_t
499 http_get_write_ptr (http_t hd)
500 {
501   return hd?hd->fp_write:NULL;
502 }
503
504 unsigned int
505 http_get_status_code (http_t hd)
506 {
507   return hd?hd->status_code:0;
508 }
509
510
511 \f
512 /*
513  * Parse an URI and put the result into the newly allocated RET_URI.
514  * The caller must always use release_parsed_uri() to releases the
515  * resources (even on error).
516  */
517 gpg_error_t
518 _http_parse_uri (parsed_uri_t * ret_uri, const char *uri,
519                  gpg_err_source_t errsource)
520 {
521   *ret_uri = xtrycalloc (1, sizeof **ret_uri + strlen (uri));
522   if (!*ret_uri)
523     return gpg_err_make (errsource, gpg_err_code_from_syserror ());
524   strcpy ((*ret_uri)->buffer, uri);
525   return gpg_err_make (errsource, do_parse_uri (*ret_uri, 0));
526 }
527
528 void
529 http_release_parsed_uri (parsed_uri_t uri)
530 {
531   if (uri)
532     {
533       uri_tuple_t r, r2;
534
535       for (r = uri->query; r; r = r2)
536         {
537           r2 = r->next;
538           xfree (r);
539         }
540       xfree (uri);
541     }
542 }
543
544
545 static gpg_err_code_t
546 do_parse_uri (parsed_uri_t uri, int only_local_part)
547 {
548   uri_tuple_t *tail;
549   char *p, *p2, *p3, *pp;
550   int n;
551
552   p = uri->buffer;
553   n = strlen (uri->buffer);
554
555   /* Initialize all fields to an empty string or an empty list. */
556   uri->scheme = uri->host = uri->path = p + n;
557   uri->port = 0;
558   uri->params = uri->query = NULL;
559   uri->use_tls = 0;
560
561   /* A quick validity check. */
562   if (strspn (p, VALID_URI_CHARS) != n)
563     return GPG_ERR_BAD_URI;     /* Invalid characters found. */
564
565   if (!only_local_part)
566     {
567       /* Find the scheme. */
568       if (!(p2 = strchr (p, ':')) || p2 == p)
569         return GPG_ERR_BAD_URI; /* No scheme. */
570       *p2++ = 0;
571       for (pp=p; *pp; pp++)
572        *pp = tolower (*(unsigned char*)pp);
573       uri->scheme = p;
574       if (!strcmp (uri->scheme, "http"))
575         uri->port = 80;
576 #ifdef HTTP_USE_GNUTLS
577       else if (!strcmp (uri->scheme, "https"))
578         {
579           uri->port = 443;
580           uri->use_tls = 1;
581         }
582 #endif
583       else
584         return GPG_ERR_INV_URI; /* Unsupported scheme */
585
586       p = p2;
587
588       /* Find the hostname */
589       if (*p != '/')
590         return GPG_ERR_INV_URI; /* Does not start with a slash. */
591
592       p++;
593       if (*p == '/') /* There seems to be a hostname. */
594         { 
595           p++;
596           if ((p2 = strchr (p, '/')))
597             *p2++ = 0;
598
599           /* Check for username/password encoding */
600           if ((p3 = strchr (p, '@')))
601             {
602               uri->auth = p;
603               *p3++ = '\0';
604               p = p3;
605             }
606
607           for (pp=p; *pp; pp++)
608             *pp = tolower (*(unsigned char*)pp);
609
610           /* Handle an IPv6 literal */
611           if( *p == '[' && (p3=strchr( p, ']' )) )
612             {
613               *p3++ = '\0';
614               /* worst case, uri->host should have length 0, points to \0 */
615               uri->host = p + 1;
616               p = p3;
617             }
618           else
619             uri->host = p;
620
621           if ((p3 = strchr (p, ':')))
622             {
623               *p3++ = '\0';
624               uri->port = atoi (p3);
625             }
626
627           if ((n = remove_escapes (uri->host)) < 0)
628             return GPG_ERR_BAD_URI;
629           if (n != strlen (uri->host))
630             return GPG_ERR_BAD_URI;     /* Hostname incudes a Nul. */
631           p = p2 ? p2 : NULL;
632         }
633     } /* End global URI part. */
634
635   /* Parse the pathname part */
636   if (!p || !*p)
637     return 0;  /* We don't have a path.  Okay. */
638
639   /* TODO: Here we have to check params. */
640
641   /* Do we have a query part? */
642   if ((p2 = strchr (p, '?')))
643     *p2++ = 0;
644
645   uri->path = p;
646   if ((n = remove_escapes (p)) < 0)
647     return GPG_ERR_BAD_URI;
648   if (n != strlen (p))
649     return GPG_ERR_BAD_URI;     /* Path includes a Nul. */
650   p = p2 ? p2 : NULL;
651
652   if (!p || !*p)        
653     return 0; /* We don't have a query string.  Okay. */
654
655   /* Now parse the query string. */
656   tail = &uri->query;
657   for (;;)
658     {
659       uri_tuple_t elem;
660
661       if ((p2 = strchr (p, '&')))
662         *p2++ = 0;
663       if (!(elem = parse_tuple (p)))
664         return GPG_ERR_BAD_URI;
665       *tail = elem;
666       tail = &elem->next;
667
668       if (!p2)
669         break; /* Ready. */
670       p = p2;
671     }
672
673   return 0;
674 }
675
676
677 /*
678  * Remove all %xx escapes; this is done in-place.  Returns: New length
679  * of the string.
680  */
681 static int
682 remove_escapes (char *string)
683 {
684   int n = 0;
685   unsigned char *p, *s;
686
687   for (p = s = (unsigned char*)string; *s; s++)
688     {
689       if (*s == '%')
690         {
691           if (s[1] && s[2] && isxdigit (s[1]) && isxdigit (s[2]))
692             {
693               s++;
694               *p = *s >= '0' && *s <= '9' ? *s - '0' :
695                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
696               *p <<= 4;
697               s++;
698               *p |= *s >= '0' && *s <= '9' ? *s - '0' :
699                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
700               p++;
701               n++;
702             }
703           else
704             {
705               *p++ = *s++;
706               if (*s)
707                 *p++ = *s++;
708               if (*s)
709                 *p++ = *s++;
710               if (*s)
711                 *p = 0;
712               return -1; /* Bad URI. */
713             }
714         }
715       else
716         {
717           *p++ = *s;
718           n++;
719         }
720     }
721   *p = 0; /* Make sure to keep a string terminator. */
722   return n;
723 }
724
725
726 static int
727 insert_escapes (char *buffer, const char *string,
728                 const char *special)
729 {
730   const unsigned char *s = (const unsigned char*)string;
731   int n = 0;
732
733   for (; *s; s++)
734     {
735       if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
736         {
737           if (buffer)
738             *(unsigned char*)buffer++ = *s;
739           n++;
740         }
741       else
742         {
743           if (buffer)
744             {
745               snprintf (buffer, 4, "%%%02X", *s);
746               buffer += 3;
747             }
748           n += 3;
749         }
750     }
751   return n;
752 }
753
754
755 /* Allocate a new string from STRING using standard HTTP escaping as
756    well as escaping of characters given in SPECIALS.  A common pattern
757    for SPECIALS is "%;?&=". However it depends on the needs, for
758    example "+" and "/: often needs to be escaped too.  Returns NULL on
759    failure and sets ERRNO. */
760 char *
761 http_escape_string (const char *string, const char *specials)
762 {
763   int n;
764   char *buf;
765
766   n = insert_escapes (NULL, string, specials);
767   buf = xtrymalloc (n+1);
768   if (buf)
769     {
770       insert_escapes (buf, string, specials);
771       buf[n] = 0;
772     }
773   return buf;
774 }
775
776
777
778 static uri_tuple_t
779 parse_tuple (char *string)
780 {
781   char *p = string;
782   char *p2;
783   int n;
784   uri_tuple_t tuple;
785
786   if ((p2 = strchr (p, '=')))
787     *p2++ = 0;
788   if ((n = remove_escapes (p)) < 0)
789     return NULL; /* Bad URI. */
790   if (n != strlen (p))
791     return NULL; /* Name with a Nul in it. */
792   tuple = xtrycalloc (1, sizeof *tuple);
793   if (!tuple)
794     return NULL; /* Out of core. */
795   tuple->name = p;
796   if (!p2) /* We have only the name, so we assume an empty value string. */
797     {
798       tuple->value = p + strlen (p);
799       tuple->valuelen = 0;
800       tuple->no_value = 1; /* Explicitly mark that we have seen no '='. */
801     }
802   else /* Name and value. */
803     {
804       if ((n = remove_escapes (p2)) < 0)
805         {
806           xfree (tuple);
807           return NULL; /* Bad URI. */
808         }
809       tuple->value = p2;
810       tuple->valuelen = n;
811     }
812   return tuple;
813 }
814
815
816 /*
817  * Send a HTTP request to the server
818  * Returns 0 if the request was successful
819  */
820 static gpg_error_t
821 send_request (http_t hd, const char *auth,
822               const char *proxy, const char *srvtag, strlist_t headers,
823               gpg_err_source_t errsource)
824 {
825   gnutls_session_t tls_session;
826   gpg_error_t err;
827   const char *server;
828   char *request, *p;
829   unsigned short port;
830   const char *http_proxy = NULL;
831   char *proxy_authstr = NULL;
832   char *authstr = NULL;
833   int save_errno;
834
835   tls_session = hd->tls_context;
836   if (hd->uri->use_tls && !tls_session)
837     {
838       log_error ("TLS requested but no GNUTLS context provided\n");
839       return gpg_err_make (errsource, GPG_ERR_INTERNAL);
840     }
841
842   server = *hd->uri->host ? hd->uri->host : "localhost";
843   port = hd->uri->port ? hd->uri->port : 80;
844
845   if ( (proxy && *proxy)
846        || ( (hd->flags & HTTP_FLAG_TRY_PROXY)
847             && (http_proxy = getenv (HTTP_PROXY_ENV)) 
848             && *http_proxy ))
849     {
850       parsed_uri_t uri;
851
852       if (proxy)
853         http_proxy = proxy;
854
855       err = _http_parse_uri (&uri, http_proxy, errsource);
856       if (err)
857         {
858           log_error ("invalid HTTP proxy (%s): %s\n",
859                      http_proxy, gpg_strerror (err));
860           http_release_parsed_uri (uri);
861           return gpg_err_make (errsource, GPG_ERR_CONFIGURATION);
862         }
863
864       if (uri->auth)
865         {
866           remove_escapes (uri->auth);
867           proxy_authstr = make_header_line ("Proxy-Authorization: Basic ",
868                                             "\r\n",
869                                             uri->auth, strlen(uri->auth));
870           if (!proxy_authstr)
871             {
872               err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
873               http_release_parsed_uri (uri);
874               return err;
875             }
876         }
877
878       hd->sock = connect_server (*uri->host ? uri->host : "localhost",
879                                  uri->port ? uri->port : 80,
880                                  hd->flags, srvtag);
881       save_errno = errno;
882       http_release_parsed_uri (uri);
883     }
884   else
885     {
886       hd->sock = connect_server (server, port, hd->flags, srvtag);
887       save_errno = errno;
888     }
889
890   if (hd->sock == -1)
891     {
892       xfree (proxy_authstr);
893       return gpg_err_make (errsource, (save_errno 
894                                        ? gpg_err_code_from_errno (save_errno)
895                                        : GPG_ERR_NOT_FOUND));
896     }
897
898 #ifdef HTTP_USE_GNUTLS
899   if (hd->uri->use_tls)
900     {
901       int rc;
902
903       gnutls_transport_set_ptr (tls_session, (gnutls_transport_ptr_t)hd->sock);
904       do
905         {
906           rc = gnutls_handshake (tls_session);
907         }
908       while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
909       if (rc < 0)
910         {
911           log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
912           xfree (proxy_authstr);
913           return gpg_err_make (errsource, GPG_ERR_NETWORK);
914         }
915
916       if (tls_callback)
917         {
918           err = tls_callback (hd, tls_session, 0);
919           if (err)
920             {
921               log_info ("TLS connection authentication failed: %s\n",
922                         gpg_strerror (err));
923               xfree (proxy_authstr);
924               return err;
925             }
926         }
927     }
928 #endif /*HTTP_USE_GNUTLS*/
929
930   if (auth || hd->uri->auth)
931     {
932       char *myauth;
933       
934       if (auth)
935         {
936           myauth = xtrystrdup (auth);
937           if (!myauth)
938             {
939               xfree (proxy_authstr);
940               return gpg_err_make (errsource, gpg_err_code_from_syserror ());
941             }
942           remove_escapes (myauth);
943         }
944       else
945         {
946           remove_escapes (hd->uri->auth);
947           myauth = hd->uri->auth;
948         }
949
950       authstr = make_header_line ("Authorization: Basic %s", "\r\n",
951                                   myauth, strlen (myauth));
952       if (auth)
953         xfree (myauth);
954
955       if (!authstr)
956         {
957           xfree (proxy_authstr);
958           return gpg_err_make (errsource, gpg_err_code_from_syserror ());
959         }
960     }
961   
962   p = build_rel_path (hd->uri);
963   if (!p)
964     return gpg_err_make (errsource, gpg_err_code_from_syserror ());
965
966   if (http_proxy && *http_proxy)
967     {
968       request = es_asprintf 
969         ("%s http://%s:%hu%s%s HTTP/1.0\r\n%s%s",
970          hd->req_type == HTTP_REQ_GET ? "GET" :
971          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
972          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
973          server, port, *p == '/' ? "" : "/", p,
974          authstr ? authstr : "",
975          proxy_authstr ? proxy_authstr : "");
976     }
977   else
978     {
979       char portstr[35];
980         
981       if (port == 80)
982         *portstr = 0;
983       else
984         snprintf (portstr, sizeof portstr, ":%u", port);
985
986       request = es_asprintf 
987         ("%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
988          hd->req_type == HTTP_REQ_GET ? "GET" :
989          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
990          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
991          *p == '/' ? "" : "/", p, server, portstr,
992          authstr? authstr:"");
993     }
994   xfree (p);
995   if (!request)
996     {
997       err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
998       xfree (authstr);
999       xfree (proxy_authstr);
1000       return err;
1001     }
1002
1003
1004   /* First setup estream so that we can write even the first line
1005      using estream.  This is also required for the sake of gnutls. */
1006   {
1007     cookie_t cookie;
1008
1009     cookie = xtrycalloc (1, sizeof *cookie);
1010     if (!cookie)
1011       {
1012         err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
1013         goto leave;
1014       }
1015     cookie->fd = hd->sock;
1016     hd->write_cookie = cookie;
1017     if (hd->uri->use_tls)
1018       cookie->tls_session = tls_session;
1019
1020     hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1021     if (!hd->fp_write)
1022       {
1023         err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
1024         xfree (cookie);
1025         hd->write_cookie = NULL;
1026       }
1027     else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
1028       err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
1029     else
1030       err = 0;
1031
1032   if (!err)
1033     {
1034       for (;headers; headers=headers->next)
1035         {
1036           if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write))
1037               || (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write)))
1038             {
1039               err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
1040               break;
1041             }
1042         }
1043     }
1044   }
1045   
1046  leave:
1047   es_free (request);
1048   xfree (authstr);
1049   xfree (proxy_authstr);
1050
1051   return err;
1052 }
1053
1054
1055 /*
1056  * Build the relative path from the parsed URI.  Minimal
1057  * implementation.  May return NULL in case of memory failure; errno
1058  * is then set accordingly.
1059  */
1060 static char *
1061 build_rel_path (parsed_uri_t uri)
1062 {
1063   uri_tuple_t r;
1064   char *rel_path, *p;
1065   int n;
1066
1067   /* Count the needed space. */
1068   n = insert_escapes (NULL, uri->path, "%;?&");
1069   /* TODO: build params. */
1070   for (r = uri->query; r; r = r->next)
1071     {
1072       n++; /* '?'/'&' */
1073       n += insert_escapes (NULL, r->name, "%;?&=");
1074       if (!r->no_value)
1075         {
1076           n++; /* '=' */
1077           n += insert_escapes (NULL, r->value, "%;?&=");
1078         }
1079     }
1080   n++;
1081
1082   /* Now allocate and copy. */
1083   p = rel_path = xtrymalloc (n);
1084   if (!p)
1085     return NULL;
1086   n = insert_escapes (p, uri->path, "%;?&");
1087   p += n;
1088   /* TODO: add params. */
1089   for (r = uri->query; r; r = r->next)
1090     {
1091       *p++ = r == uri->query ? '?' : '&';
1092       n = insert_escapes (p, r->name, "%;?&=");
1093       p += n;
1094       if (!r->no_value)
1095         {
1096           *p++ = '=';
1097           /* TODO: Use valuelen. */
1098           n = insert_escapes (p, r->value, "%;?&=");
1099           p += n;
1100         }
1101     }
1102   *p = 0;
1103   return rel_path;
1104 }
1105
1106
1107 /* Transform a header name into a standard capitalized format; e.g.
1108    "Content-Type".  Conversion stops at the colon.  As usual we don't
1109    use the localized versions of ctype.h. */
1110 static void
1111 capitalize_header_name (char *name)
1112 {
1113   int first = 1;
1114
1115   for (; *name && *name != ':'; name++)
1116     {
1117       if (*name == '-')
1118         first = 1;
1119       else if (first)
1120         {
1121           if (*name >= 'a' && *name <= 'z')
1122             *name = *name - 'a' + 'A';
1123           first = 0;
1124         }
1125       else if (*name >= 'A' && *name <= 'Z')
1126         *name = *name - 'A' + 'a';
1127     }
1128 }
1129
1130
1131 /* Store an HTTP header line in LINE away.  Line continuation is
1132    supported as well as merging of headers with the same name. This
1133    function may modify LINE. */
1134 static gpg_err_code_t
1135 store_header (http_t hd, char *line)
1136 {
1137   size_t n;
1138   char *p, *value;
1139   header_t h;
1140
1141   n = strlen (line);
1142   if (n && line[n-1] == '\n')
1143     {
1144       line[--n] = 0;
1145       if (n && line[n-1] == '\r')
1146         line[--n] = 0;
1147     }
1148   if (!n)  /* we are never called to hit this. */
1149     return GPG_ERR_BUG;
1150   if (*line == ' ' || *line == '\t')
1151     {
1152       /* Continuation. This won't happen too often as it is not
1153          recommended.  We use a straightforward implementaion. */
1154       if (!hd->headers)
1155         return GPG_ERR_PROTOCOL_VIOLATION;
1156       n += strlen (hd->headers->value);
1157       p = xtrymalloc (n+1);
1158       if (!p)
1159         return gpg_err_code_from_syserror ();
1160       strcpy (stpcpy (p, hd->headers->value), line);
1161       xfree (hd->headers->value);
1162       hd->headers->value = p;
1163       return 0;
1164     }
1165
1166   capitalize_header_name (line);
1167   p = strchr (line, ':');
1168   if (!p)
1169     return GPG_ERR_PROTOCOL_VIOLATION;
1170   *p++ = 0;
1171   while (*p == ' ' || *p == '\t')
1172     p++;
1173   value = p;
1174   
1175   for (h=hd->headers; h; h = h->next)
1176     if ( !strcmp (h->name, line) )
1177       break;
1178   if (h)
1179     {
1180       /* We have already seen a line with that name.  Thus we assume
1181          it is a comma separated list and merge them.  */
1182       p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1);
1183       if (!p)
1184         return gpg_err_code_from_syserror ();
1185       strcpy (stpcpy (stpcpy (p, h->value), ","), value);
1186       xfree (h->value);
1187       h->value = p;
1188       return 0;
1189     }
1190
1191   /* Append a new header. */
1192   h = xtrymalloc (sizeof *h + strlen (line));
1193   if (!h)
1194     return gpg_err_code_from_syserror ();
1195   strcpy (h->name, line);
1196   h->value = xtrymalloc (strlen (value)+1);
1197   if (!h->value)
1198     {
1199       xfree (h);
1200       return gpg_err_code_from_syserror ();
1201     }
1202   strcpy (h->value, value);
1203   h->next = hd->headers;
1204   hd->headers = h;
1205
1206   return 0;
1207 }
1208
1209
1210 /* Return the header NAME from the last response.  The returned value
1211    is valid as along as HD has not been closed and no othe request has
1212    been send. If the header was not found, NULL is returned.  Name
1213    must be canonicalized, that is the first letter of each dash
1214    delimited part must be uppercase and all other letters lowercase.  */
1215 const char *
1216 http_get_header (http_t hd, const char *name)
1217 {
1218   header_t h;
1219
1220   for (h=hd->headers; h; h = h->next)
1221     if ( !strcmp (h->name, name) )
1222       return h->value;
1223   return NULL;
1224 }
1225
1226
1227
1228 /*
1229  * Parse the response from a server.
1230  * Returns: Errorcode and sets some files in the handle
1231  */
1232 static gpg_err_code_t
1233 parse_response (http_t hd)
1234 {
1235   char *line, *p, *p2;
1236   size_t maxlen, len;
1237   cookie_t cookie = hd->read_cookie;
1238   const char *s;
1239
1240   /* Delete old header lines.  */
1241   while (hd->headers)
1242     {
1243       header_t tmp = hd->headers->next;
1244       xfree (hd->headers->value);
1245       xfree (hd->headers);
1246       hd->headers = tmp;
1247     }
1248
1249   /* Wait for the status line. */
1250   do
1251     {
1252       maxlen = MAX_LINELEN;
1253       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
1254       line = hd->buffer;
1255       if (!line)
1256         return gpg_err_code_from_syserror (); /* Out of core. */
1257       if (!maxlen)
1258         return GPG_ERR_TRUNCATED; /* Line has been truncated. */
1259       if (!len)
1260         return GPG_ERR_EOF;
1261
1262       if ((hd->flags & HTTP_FLAG_LOG_RESP))
1263         log_info ("RESP: `%.*s'\n",
1264                   (int)strlen(line)-(*line&&line[1]?2:0),line);
1265     }
1266   while (!*line);
1267
1268   if ((p = strchr (line, '/')))
1269     *p++ = 0;
1270   if (!p || strcmp (line, "HTTP"))
1271     return 0; /* Assume http 0.9. */
1272
1273   if ((p2 = strpbrk (p, " \t")))
1274     {
1275       *p2++ = 0;
1276       p2 += strspn (p2, " \t");
1277     }
1278   if (!p2)
1279     return 0; /* Also assume http 0.9. */
1280   p = p2;
1281   /* TODO: Add HTTP version number check. */
1282   if ((p2 = strpbrk (p, " \t")))
1283     *p2++ = 0;
1284   if (!isdigit ((unsigned int)p[0]) || !isdigit ((unsigned int)p[1])
1285       || !isdigit ((unsigned int)p[2]) || p[3])
1286     {
1287       /* Malformed HTTP status code - assume http 0.9. */
1288       hd->is_http_0_9 = 1;
1289       hd->status_code = 200;
1290       return 0;
1291     }
1292   hd->status_code = atoi (p);
1293
1294   /* Skip all the header lines and wait for the empty line. */
1295   do
1296     {
1297       maxlen = MAX_LINELEN;
1298       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
1299       line = hd->buffer;
1300       if (!line)
1301         return gpg_err_code_from_syserror (); /* Out of core. */
1302       /* Note, that we can silently ignore truncated lines. */
1303       if (!len)
1304         return GPG_ERR_EOF;
1305       /* Trim line endings of empty lines. */
1306       if ((*line == '\r' && line[1] == '\n') || *line == '\n')
1307         *line = 0;
1308       if ((hd->flags & HTTP_FLAG_LOG_RESP))
1309         log_info ("RESP: `%.*s'\n",
1310                   (int)strlen(line)-(*line&&line[1]?2:0),line);
1311       if (*line)
1312         {
1313           gpg_err_code_t ec = store_header (hd, line);
1314           if (ec)
1315             return ec;
1316         }
1317     }
1318   while (len && *line);
1319
1320   cookie->content_length_valid = 0;
1321   if (!(hd->flags & HTTP_FLAG_IGNORE_CL))
1322     {
1323       s = http_get_header (hd, "Content-Length");
1324       if (s)
1325         {
1326           cookie->content_length_valid = 1;
1327           cookie->content_length = counter_strtoul (s);
1328         }
1329     }
1330
1331   return 0;
1332 }
1333
1334 #if 0
1335 static int
1336 start_server ()
1337 {
1338   struct sockaddr_in mya;
1339   struct sockaddr_in peer;
1340   int fd, client;
1341   fd_set rfds;
1342   int addrlen;
1343   int i;
1344
1345   if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
1346     {
1347       log_error ("socket() failed: %s\n", strerror (errno));
1348       return -1;
1349     }
1350   i = 1;
1351   if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (byte *) & i, sizeof (i)))
1352     log_info ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno));
1353
1354   mya.sin_family = AF_INET;
1355   memset (&mya.sin_addr, 0, sizeof (mya.sin_addr));
1356   mya.sin_port = htons (11371);
1357
1358   if (bind (fd, (struct sockaddr *) &mya, sizeof (mya)))
1359     {
1360       log_error ("bind to port 11371 failed: %s\n", strerror (errno));
1361       sock_close (fd);
1362       return -1;
1363     }
1364
1365   if (listen (fd, 5))
1366     {
1367       log_error ("listen failed: %s\n", strerror (errno));
1368       sock_close (fd);
1369       return -1;
1370     }
1371
1372   for (;;)
1373     {
1374       FD_ZERO (&rfds);
1375       FD_SET (fd, &rfds);
1376
1377       if (select (fd + 1, &rfds, NULL, NULL, NULL) <= 0)
1378         continue;               /* ignore any errors */
1379
1380       if (!FD_ISSET (fd, &rfds))
1381         continue;
1382
1383       addrlen = sizeof peer;
1384       client = accept (fd, (struct sockaddr *) &peer, &addrlen);
1385       if (client == -1)
1386         continue;               /* oops */
1387
1388       log_info ("connect from %s\n", inet_ntoa (peer.sin_addr));
1389
1390       fflush (stdout);
1391       fflush (stderr);
1392       if (!fork ())
1393         {
1394           int c;
1395           FILE *fp;
1396
1397           fp = fdopen (client, "r");
1398           while ((c = getc (fp)) != EOF)
1399             putchar (c);
1400           fclose (fp);
1401           exit (0);
1402         }
1403       sock_close (client);
1404     }
1405
1406
1407   return 0;
1408 }
1409 #endif
1410
1411 /* Actually connect to a server.  Returns the file descriptor or -1 on
1412    error.  ERRNO is set on error. */
1413 static int
1414 connect_server (const char *server, unsigned short port,
1415                 unsigned int flags, const char *srvtag)
1416 {
1417   int sock = -1;
1418   int srvcount = 0;
1419   int hostfound = 0;
1420   int srv, connected;
1421   int last_errno = 0;
1422   struct srventry *serverlist = NULL;
1423 #ifdef HAVE_W32_SYSTEM
1424   unsigned long inaddr;
1425 #endif
1426   /* Not currently using the flags */
1427   (void)flags;
1428
1429 #ifdef HAVE_W32_SYSTEM
1430
1431 #ifndef HTTP_NO_WSASTARTUP
1432   init_sockets ();
1433 #endif
1434   /* Win32 gethostbyname doesn't handle IP addresses internally, so we
1435      try inet_addr first on that platform only. */
1436   inaddr = inet_addr(server);
1437   if ( inaddr != INADDR_NONE )
1438     {
1439       struct sockaddr_in addr;
1440       
1441       memset(&addr,0,sizeof(addr));
1442       
1443       sock = socket(AF_INET,SOCK_STREAM,0);
1444       if ( sock==INVALID_SOCKET )
1445         {
1446           log_error("error creating socket: ec=%d\n",(int)WSAGetLastError());
1447           return -1;
1448         }
1449
1450       addr.sin_family = AF_INET; 
1451       addr.sin_port = htons(port);
1452       memcpy (&addr.sin_addr,&inaddr,sizeof(inaddr));      
1453
1454       if (!connect (sock,(struct sockaddr *)&addr,sizeof(addr)) )
1455         return sock;
1456       sock_close(sock);
1457       return -1;
1458     }
1459 #endif /*HAVE_W32_SYSTEM*/
1460
1461 #ifdef USE_DNS_SRV
1462   /* Do the SRV thing */
1463   if (srvtag)
1464     {
1465       /* We're using SRV, so append the tags. */
1466       if (1+strlen (srvtag) + 6 + strlen (server) + 1 <= MAXDNAME)
1467         {
1468           char srvname[MAXDNAME];
1469
1470           stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srvtag),
1471                            "._tcp."), server);
1472           srvcount = getsrv (srvname, &serverlist);
1473         }
1474     }
1475 #else
1476   (void)flags;
1477   (void)srvtag;
1478 #endif /*USE_DNS_SRV*/
1479
1480   if (!serverlist)
1481     {
1482       /* Either we're not using SRV, or the SRV lookup failed.  Make
1483          up a fake SRV record. */
1484       serverlist = xtrycalloc (1, sizeof *serverlist);
1485       if (!serverlist)
1486         return -1; /* Out of core.  */
1487       serverlist->port = port;
1488       strncpy (serverlist->target, server, MAXDNAME);
1489       serverlist->target[MAXDNAME-1] = '\0';
1490       srvcount = 1;
1491     }
1492
1493 #ifdef HAVE_GETADDRINFO
1494   connected = 0;
1495   for (srv=0; srv < srvcount && !connected; srv++)
1496     {
1497       struct addrinfo hints, *res, *ai;
1498       char portstr[35];
1499
1500       snprintf (portstr, sizeof portstr, "%hu", port);
1501       memset (&hints, 0, sizeof (hints));
1502       hints.ai_socktype = SOCK_STREAM;
1503       if (getaddrinfo (serverlist[srv].target, portstr, &hints, &res))
1504         continue; /* Not found - try next one. */
1505       hostfound = 1;
1506
1507       for (ai = res; ai && !connected; ai = ai->ai_next)
1508         {
1509           if (sock != -1)
1510             sock_close (sock);
1511           sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
1512           if (sock == -1)
1513             {
1514               int save_errno = errno;
1515               log_error ("error creating socket: %s\n", strerror (errno));
1516               freeaddrinfo (res);
1517               xfree (serverlist);
1518               errno = save_errno;
1519               return -1;
1520             }
1521           
1522           if (connect (sock, ai->ai_addr, ai->ai_addrlen))
1523             last_errno = errno;
1524           else
1525             connected = 1;
1526         }
1527       freeaddrinfo (res);
1528     }
1529 #else /* !HAVE_GETADDRINFO */
1530   connected = 0;
1531   for (srv=0; srv < srvcount && !connected; srv++)
1532     {
1533       int i;
1534       struct hostent *host = NULL;
1535       struct sockaddr_in addr;
1536
1537       /* Note: This code is not thread-safe.  */
1538
1539       memset (&addr, 0, sizeof (addr));
1540       host = gethostbyname (serverlist[srv].target);
1541       if (!host)
1542         continue;
1543       hostfound = 1;
1544
1545       if (sock != -1)
1546         sock_close (sock);
1547       sock = socket (host->h_addrtype, SOCK_STREAM, 0);
1548       if (sock == -1)
1549         {
1550           log_error (_("error creating socket: %s\n"), strerror (errno));
1551           xfree (serverlist);
1552           return -1;
1553         }
1554       
1555       addr.sin_family = host->h_addrtype;
1556       if (addr.sin_family != AF_INET)
1557         {
1558           log_error ("unknown address family for `%s'\n",
1559                      serverlist[srv].target);
1560           xfree (serverlist);
1561           return -1;
1562         }
1563       addr.sin_port = htons (serverlist[srv].port);
1564       if (host->h_length != 4)
1565         {
1566           log_error ("illegal address length for `%s'\n",
1567                      serverlist[srv].target);
1568           xfree (serverlist);
1569           return -1;
1570         }
1571
1572       /* Try all A records until one responds. */
1573       for (i = 0; host->h_addr_list[i] && !connected; i++)
1574         {
1575           memcpy (&addr.sin_addr, host->h_addr_list[i], host->h_length);
1576           if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)))
1577             last_errno = errno;
1578           else
1579             {
1580               connected = 1;
1581               break;
1582             }
1583         }
1584     }
1585 #endif /* !HAVE_GETADDRINFO */
1586
1587   xfree (serverlist);
1588
1589   if (!connected)
1590     {
1591 #ifdef HAVE_W32_SYSTEM
1592       log_error ("can't connect to `%s': %s%sec=%d\n",
1593                    server,
1594                    hostfound? "":_("host not found"),
1595                    hostfound? "":" - ", (int)WSAGetLastError());
1596 #else
1597       log_error ("can't connect to `%s': %s\n",
1598                  server,
1599                  hostfound? strerror (last_errno):"host not found");
1600 #endif
1601       if (sock != -1)
1602         sock_close (sock);
1603       gpg_err_set_errno (last_errno);
1604       return -1;
1605     }
1606   return sock;
1607 }
1608
1609
1610 static gpg_error_t
1611 write_server (int sock, const char *data, size_t length)
1612 {
1613   int nleft;
1614   int nwritten;
1615
1616   /* FIXME: We would better use pth I/O functions.  */
1617   nleft = length;
1618   while (nleft > 0)
1619     {
1620 #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_PTH)
1621       nwritten = send (sock, data, nleft, 0);
1622       if ( nwritten == SOCKET_ERROR ) 
1623         {
1624           log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
1625           return gpg_error (GPG_ERR_NETWORK);
1626         }
1627 #else /*!HAVE_W32_SYSTEM || HAVE_PTH*/
1628 # ifdef HAVE_PTH
1629       nwritten = pth_write (sock, data, nleft);
1630 # else
1631       nwritten = write (sock, data, nleft);
1632 # endif
1633       if (nwritten == -1)
1634         {
1635           if (errno == EINTR)
1636             continue;
1637           if (errno == EAGAIN)
1638             {
1639               struct timeval tv;
1640
1641               tv.tv_sec = 0;
1642               tv.tv_usec = 50000;
1643               select (0, NULL, NULL, NULL, &tv);
1644               continue;
1645             }
1646           log_info ("network write failed: %s\n", strerror (errno));
1647           return gpg_error_from_syserror ();
1648         }
1649 #endif /*!HAVE_W32_SYSTEM || HAVE_PTH*/
1650       nleft -= nwritten;
1651       data += nwritten;
1652     }
1653
1654   return 0;
1655 }
1656
1657
1658 \f
1659 /* Read handler for estream.  */
1660 static ssize_t
1661 cookie_read (void *cookie, void *buffer, size_t size)
1662 {
1663   cookie_t c = cookie;
1664   int nread;
1665
1666   if (c->content_length_valid)
1667     {
1668       if (!c->content_length)
1669         return 0; /* EOF */
1670       if (c->content_length < size)
1671         size = c->content_length;
1672     }
1673
1674 #ifdef HTTP_USE_GNUTLS
1675   if (c->tls_session)
1676     {
1677     again:
1678       nread = gnutls_record_recv (c->tls_session, buffer, size);
1679       if (nread < 0)
1680         {
1681           if (nread == GNUTLS_E_INTERRUPTED)
1682             goto again;
1683           if (nread == GNUTLS_E_AGAIN)
1684             {
1685               struct timeval tv;
1686               
1687               tv.tv_sec = 0;
1688               tv.tv_usec = 50000;
1689               select (0, NULL, NULL, NULL, &tv);
1690               goto again;
1691             }
1692           if (nread == GNUTLS_E_REHANDSHAKE)
1693             goto again; /* A client is allowed to just ignore this request. */
1694           log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
1695           gpg_err_set_errno (EIO);
1696           return -1;
1697         }
1698     }
1699   else
1700 #endif /*HTTP_USE_GNUTLS*/
1701     {
1702       do
1703         {
1704 #ifdef HAVE_PTH
1705           nread = pth_read (c->fd, buffer, size);
1706 #elif defined(HAVE_W32_SYSTEM)
1707           /* Under Windows we need to use recv for a socket.  */
1708           nread = recv (c->fd, buffer, size, 0);
1709 #else          
1710           nread = read (c->fd, buffer, size);
1711 #endif
1712         }
1713       while (nread == -1 && errno == EINTR);
1714     }
1715
1716   if (c->content_length_valid && nread > 0)
1717     {
1718       if (nread < c->content_length)
1719         c->content_length -= nread;
1720       else
1721         c->content_length = 0;          
1722     }
1723
1724   return nread;
1725 }
1726
1727 /* Write handler for estream.  */
1728 static ssize_t
1729 cookie_write (void *cookie, const void *buffer, size_t size)
1730 {
1731   cookie_t c = cookie;
1732   int nwritten = 0;
1733
1734 #ifdef HTTP_USE_GNUTLS
1735   if (c->tls_session)
1736     {
1737       int nleft = size;
1738       while (nleft > 0)
1739         {
1740           nwritten = gnutls_record_send (c->tls_session, buffer, nleft); 
1741           if (nwritten <= 0)
1742             {
1743               if (nwritten == GNUTLS_E_INTERRUPTED)
1744                 continue;
1745               if (nwritten == GNUTLS_E_AGAIN)
1746                 {
1747                   struct timeval tv;
1748                   
1749                   tv.tv_sec = 0;
1750                   tv.tv_usec = 50000;
1751                   select (0, NULL, NULL, NULL, &tv);
1752                   continue;
1753                 }
1754               log_info ("TLS network write failed: %s\n",
1755                         gnutls_strerror (nwritten));
1756               gpg_err_set_errno (EIO);
1757               return -1;
1758             }
1759           nleft -= nwritten;
1760           buffer += nwritten;
1761         }
1762     }
1763   else
1764 #endif /*HTTP_USE_GNUTLS*/
1765     {
1766       if ( write_server (c->fd, buffer, size) )
1767         {
1768           gpg_err_set_errno (EIO);
1769           nwritten = -1;
1770         }
1771       else
1772         nwritten = size;
1773     }
1774
1775   return nwritten;
1776 }
1777
1778 /* Close handler for estream.  */
1779 static int
1780 cookie_close (void *cookie)
1781 {
1782   cookie_t c = cookie;
1783
1784   if (!c)
1785     return 0;
1786
1787 #ifdef HTTP_USE_GNUTLS
1788   if (c->tls_session && !c->keep_socket)
1789     {
1790       gnutls_bye (c->tls_session, GNUTLS_SHUT_RDWR);
1791     }
1792 #endif /*HTTP_USE_GNUTLS*/
1793   if (c->fd != -1 && !c->keep_socket)
1794     sock_close (c->fd);
1795
1796   xfree (c);
1797   return 0;
1798 }
1799
1800
1801
1802 \f
1803 /**** Test code ****/
1804 #ifdef TEST
1805
1806 static gpg_error_t
1807 verify_callback (http_t hd, void *tls_context, int reserved)
1808 {
1809   log_info ("verification of certificates skipped\n");
1810   return 0;
1811 }
1812
1813
1814
1815 /* static void */
1816 /* my_gnutls_log (int level, const char *text) */
1817 /* { */
1818 /*   fprintf (stderr, "gnutls:L%d: %s", level, text); */
1819 /* } */
1820
1821 int
1822 main (int argc, char **argv)
1823 {
1824   int rc;
1825   parsed_uri_t uri;
1826   uri_tuple_t r;
1827   http_t hd;
1828   int c;
1829   gnutls_session_t tls_session = NULL;
1830 #ifdef HTTP_USE_GNUTLS
1831   gnutls_certificate_credentials certcred;
1832   const int certprio[] = { GNUTLS_CRT_X509, 0 };
1833 #endif /*HTTP_USE_GNUTLS*/
1834   header_t hdr;
1835
1836   es_init ();
1837   log_set_prefix ("http-test", 1 | 4);
1838   if (argc == 1)
1839     {
1840       /*start_server (); */
1841       return 0;
1842     }
1843
1844   if (argc != 2)
1845     {
1846       fprintf (stderr, "usage: http-test uri\n");
1847       return 1;
1848     }
1849   argc--;
1850   argv++;
1851
1852 #ifdef HTTP_USE_GNUTLS
1853   rc = gnutls_global_init ();
1854   if (rc)
1855     log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc));
1856   rc = gnutls_certificate_allocate_credentials (&certcred);
1857   if (rc)
1858     log_error ("gnutls_certificate_allocate_credentials failed: %s\n",
1859                gnutls_strerror (rc));
1860 /*   rc = gnutls_certificate_set_x509_trust_file */
1861 /*     (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */
1862 /*   if (rc) */
1863 /*     log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */
1864 /*                gnutls_strerror (rc)); */
1865   rc = gnutls_init (&tls_session, GNUTLS_CLIENT);
1866   if (rc)
1867     log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc));
1868   rc = gnutls_set_default_priority (tls_session);
1869   if (rc)
1870     log_error ("gnutls_set_default_priority failed: %s\n",
1871                gnutls_strerror (rc));
1872   rc = gnutls_certificate_type_set_priority (tls_session, certprio);
1873   if (rc)
1874     log_error ("gnutls_certificate_type_set_priority failed: %s\n",
1875                gnutls_strerror (rc));
1876   rc = gnutls_credentials_set (tls_session, GNUTLS_CRD_CERTIFICATE, certcred);
1877   if (rc)
1878     log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc));
1879 /*   gnutls_global_set_log_function (my_gnutls_log); */
1880 /*   gnutls_global_set_log_level (4); */
1881
1882   http_register_tls_callback (verify_callback);
1883 #endif /*HTTP_USE_GNUTLS*/
1884
1885   rc = http_parse_uri (&uri, *argv);
1886   if (rc)
1887     {
1888       log_error ("`%s': %s\n", *argv, gpg_strerror (rc));
1889       http_release_parsed_uri (uri);
1890       return 1;
1891     }
1892
1893   printf ("Scheme: %s\n", uri->scheme);
1894   printf ("Host  : %s\n", uri->host);
1895   printf ("Port  : %u\n", uri->port);
1896   printf ("Path  : %s\n", uri->path);
1897   for (r = uri->params; r; r = r->next)
1898     {
1899       printf ("Params: %s", r->name);
1900       if (!r->no_value)
1901         {
1902           printf ("=%s", r->value);
1903           if (strlen (r->value) != r->valuelen)
1904             printf (" [real length=%d]", (int) r->valuelen);
1905         }
1906       putchar ('\n');
1907     }
1908   for (r = uri->query; r; r = r->next)
1909     {
1910       printf ("Query : %s", r->name);
1911       if (!r->no_value)
1912         {
1913           printf ("=%s", r->value);
1914           if (strlen (r->value) != r->valuelen)
1915             printf (" [real length=%d]", (int) r->valuelen);
1916         }
1917       putchar ('\n');
1918     }
1919   http_release_parsed_uri (uri);
1920   uri = NULL;
1921
1922   rc = http_open_document (&hd, *argv, NULL, 0, NULL, tls_session);
1923   if (rc)
1924     {
1925       log_error ("can't get `%s': %s\n", *argv, gpg_strerror (rc));
1926       return 1;
1927     }
1928   log_info ("open_http_document succeeded; status=%u\n",
1929             http_get_status_code (hd));
1930   for (hdr = hd->headers; hdr; hdr = hdr->next)
1931     printf ("HDR: %s: %s\n", hdr->name, hdr->value);
1932   switch (http_get_status_code (hd))
1933     {
1934     case 200:
1935       while ((c = es_getc (http_get_read_ptr (hd))) != EOF)
1936         putchar (c);
1937       break;
1938     case 301:
1939     case 302:
1940       printf ("Redirected to `%s'\n", http_get_header (hd, "Location"));
1941       break;
1942     }
1943   http_close (hd, 0);
1944
1945 #ifdef HTTP_USE_GNUTLS
1946   gnutls_deinit (tls_session);
1947   gnutls_certificate_free_credentials (certcred);
1948   gnutls_global_deinit ();
1949 #endif /*HTTP_USE_GNUTLS*/
1950
1951   return 0;
1952 }
1953 #endif /*TEST*/
1954
1955
1956 /*
1957 Local Variables:
1958 compile-command: "gcc -I.. -I../gl -DTEST -DHAVE_CONFIG_H -Wall -O2 -g -o http-test http.c -L. -lcommon -L../jnlib -ljnlib -lgcrypt -lpth -lgnutls"
1959 End:
1960 */