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