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