Support to read response headers. Required for redirection support in the
[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 gpg_error_from_errno (save_errno);
876     }
877
878 #ifdef HTTP_USE_GNUTLS
879   if (hd->uri->use_tls)
880     {
881       int rc;
882
883       gnutls_transport_set_ptr (tls_session, (gnutls_transport_ptr_t)hd->sock);
884       do
885         {
886           rc = gnutls_handshake (tls_session);
887         }
888       while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
889       if (rc < 0)
890         {
891           log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
892           xfree (proxy_authstr);
893           return gpg_error (GPG_ERR_NETWORK);
894         }
895
896       if (tls_callback)
897         {
898           err = tls_callback (hd, tls_session, 0);
899           if (err)
900             {
901               log_info ("TLS connection authentication failed: %s\n",
902                         gpg_strerror (err));
903               xfree (proxy_authstr);
904               return err;
905             }
906         }
907     }
908 #endif /*HTTP_USE_GNUTLS*/
909
910   if (auth || hd->uri->auth)
911     {
912       char *myauth;
913       
914       if (auth)
915         {
916           myauth = xtrystrdup (auth);
917           if (!myauth)
918             {
919               xfree (proxy_authstr);
920               return gpg_error_from_errno (errno);
921             }
922           remove_escapes (myauth);
923         }
924       else
925         {
926           remove_escapes (hd->uri->auth);
927           myauth = hd->uri->auth;
928         }
929
930       authstr = make_header_line ("Authorization: Basic %s", "\r\n",
931                                   myauth, strlen (myauth));
932       if (auth)
933         xfree (myauth);
934
935       if (!authstr)
936         {
937           xfree (proxy_authstr);
938           return gpg_error_from_errno (errno);
939         }
940     }
941   
942   p = build_rel_path (hd->uri);
943   if (!p)
944     return gpg_error_from_errno (errno);
945
946   request = xtrymalloc (2 * strlen (server) 
947                         + strlen (p)
948                         + (authstr?strlen(authstr):0)
949                         + (proxy_authstr?strlen(proxy_authstr):0)
950                         + 100);
951   if (!request)
952     {
953       err = gpg_error_from_errno (errno);
954       xfree (p);
955       xfree (authstr);
956       xfree (proxy_authstr);
957       return err;
958     }
959
960   if (http_proxy && *http_proxy)
961     {
962       sprintf (request, "%s http://%s:%hu%s%s HTTP/1.0\r\n%s%s",
963                hd->req_type == HTTP_REQ_GET ? "GET" :
964                hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
965                hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
966                server, port, *p == '/' ? "" : "/", p,
967                authstr ? authstr : "",
968                proxy_authstr ? proxy_authstr : "");
969     }
970   else
971     {
972       char portstr[35];
973         
974       if (port == 80)
975         *portstr = 0;
976       else
977         sprintf (portstr, ":%u", port);
978
979       sprintf (request, "%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
980                hd->req_type == HTTP_REQ_GET ? "GET" :
981                hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
982                hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
983                *p == '/' ? "" : "/", p, server, portstr,
984                authstr? authstr:"");
985     }
986   xfree (p);
987
988
989 #ifdef HTTP_USE_ESTREAM
990   /* First setup estream so that we can write even the first line
991      using estream.  This is also required for the sake of gnutls. */
992   {
993     cookie_t cookie;
994
995     cookie = xtrycalloc (1, sizeof *cookie);
996     if (!cookie)
997       {
998         err = gpg_error_from_errno (errno);
999         goto leave;
1000       }
1001     cookie->fd = hd->sock;
1002     if (hd->uri->use_tls)
1003       {
1004         cookie->tls_session = tls_session;
1005         hd->write_cookie = cookie;
1006       }
1007
1008     hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1009     if (!hd->fp_write)
1010       {
1011         xfree (cookie);
1012         err = gpg_error_from_errno (errno);
1013       }
1014     else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
1015       err = gpg_error_from_errno (errno);
1016     else
1017       err = 0;
1018   }
1019
1020  leave:
1021
1022 #else /*!HTTP_USE_ESTREAM*/
1023   /* We send out the start of the request through our own send
1024      function and only then assign a stdio stream.  This allows for
1025      better error reporting that through standard stdio means. */
1026   err = write_server (hd->sock, request, strlen (request));
1027   if (!err)
1028     {
1029       hd->fp_write = fdopen (hd->sock, "w");
1030       if (!hd->fp_write)
1031         err = gpg_error_from_errno (errno);
1032     }
1033 #endif /*!HTTP_USE_ESTREAM*/
1034
1035   xfree (request);
1036   xfree (authstr);
1037   xfree (proxy_authstr);
1038
1039   return err;
1040 }
1041
1042
1043 /*
1044  * Build the relative path from the parsed URI.  Minimal
1045  * implementation.  May return NULL in case of memory failure; errno
1046  * is then set accordingly.
1047  */
1048 static char *
1049 build_rel_path (parsed_uri_t uri)
1050 {
1051   uri_tuple_t r;
1052   char *rel_path, *p;
1053   int n;
1054
1055   /* Count the needed space. */
1056   n = insert_escapes (NULL, uri->path, "%;?&");
1057   /* TODO: build params. */
1058   for (r = uri->query; r; r = r->next)
1059     {
1060       n++; /* '?'/'&' */
1061       n += insert_escapes (NULL, r->name, "%;?&=");
1062       if (!r->no_value)
1063         {
1064           n++; /* '=' */
1065           n += insert_escapes (NULL, r->value, "%;?&=");
1066         }
1067     }
1068   n++;
1069
1070   /* Now allocate and copy. */
1071   p = rel_path = xtrymalloc (n);
1072   if (!p)
1073     return NULL;
1074   n = insert_escapes (p, uri->path, "%;?&");
1075   p += n;
1076   /* TODO: add params. */
1077   for (r = uri->query; r; r = r->next)
1078     {
1079       *p++ = r == uri->query ? '?' : '&';
1080       n = insert_escapes (p, r->name, "%;?&=");
1081       p += n;
1082       if (!r->no_value)
1083         {
1084           *p++ = '=';
1085           /* TODO: Use valuelen. */
1086           n = insert_escapes (p, r->value, "%;?&=");
1087           p += n;
1088         }
1089     }
1090   *p = 0;
1091   return rel_path;
1092 }
1093
1094
1095
1096 /*
1097    Same as fgets() but if the buffer is too short a larger one will be
1098    allocated up to some limit *MAX_LENGTH.  A line is considered a
1099    byte stream ending in a LF.  Returns the length of the line. EOF is
1100    indicated by a line of length zero. The last LF may be missing due
1101    to an EOF.  If MAX_LENGTH is zero on return, the line has been
1102    truncated.  If the returned buffer is NULL, not enough memory was
1103    enable to increase it, the return value will also be 0 and some
1104    bytes might have been lost which should be no problem becuase
1105    out-of-memory is pretty fatal for most applications.
1106
1107    If a line has been truncated, the file pointer is internally moved
1108    forward to the end of the line.
1109
1110    Note: The returned buffer is allocated with enough extra space to
1111    append a CR,LF,Nul
1112  */
1113 static size_t
1114 my_read_line (
1115 #ifdef HTTP_USE_ESTREAM
1116               estream_t fp,
1117 #else
1118               FILE *fp,
1119 #endif
1120               char **addr_of_buffer,
1121               size_t *length_of_buffer, size_t *max_length)
1122 {
1123   int c;
1124   char *buffer = *addr_of_buffer;
1125   size_t length = *length_of_buffer;
1126   size_t nbytes = 0;
1127   size_t maxlen = *max_length;
1128   char *p;
1129
1130   if (!buffer) /* Must allocate a new buffer. */
1131     {           
1132       length = 256;
1133       buffer = xtrymalloc (length);
1134       *addr_of_buffer = buffer;
1135       if (!buffer)
1136         {
1137           *length_of_buffer = *max_length = 0;
1138           return 0;
1139         }
1140       *length_of_buffer = length;
1141     }
1142
1143   length -= 3; /* Reserve 3 bytes (cr,lf,eol). */
1144   p = buffer;
1145   while ((c = P_ES(getc) (fp)) != EOF)
1146     {
1147       if (nbytes == length) /* Increase the buffer. */
1148         {                       
1149           if (length > maxlen) /* Limit reached. */
1150             {
1151               /* Skip the rest of the line. */
1152               while (c != '\n' && (c = P_ES(getc) (fp)) != EOF)
1153                 ;
1154               *p++ = '\n'; /* Always append a LF (we reserved some space). */
1155               nbytes++;
1156               *max_length = 0; /* Indicate truncation */
1157               break; /*(the while loop)*/
1158             }
1159           length += 3; /* Adjust for the reserved bytes. */
1160           length += length < 1024 ? 256 : 1024;
1161           *addr_of_buffer = xtryrealloc (buffer, length);
1162           if (!*addr_of_buffer)
1163             {
1164               int save_errno = errno;
1165               xfree (buffer);
1166               *length_of_buffer = *max_length = 0;
1167               errno = save_errno;
1168               return 0;
1169             }
1170           buffer = *addr_of_buffer;
1171           *length_of_buffer = length;
1172           length -= 3; /* And re-adjust for the reservation. */
1173           p = buffer + nbytes;
1174         }
1175       *p++ = c;
1176       nbytes++;
1177       if (c == '\n')
1178         break;
1179     }
1180   *p = 0; /* Make sure the line is a string. */
1181
1182   return nbytes;
1183 }
1184
1185
1186 /* Transform a header name into a standard capitalized format; e.g.
1187    "Content-Type".  Conversion stops at the colon.  As usual we don't
1188    use the localized versions of ctype.h. */
1189 static void
1190 capitalize_header_name (char *name)
1191 {
1192   int first = 1;
1193
1194   for (; *name && *name != ':'; name++)
1195     {
1196       if (*name == '-')
1197         first = 1;
1198       else if (first)
1199         {
1200           if (*name >= 'a' && *name <= 'z')
1201             *name = *name - 'a' + 'A';
1202           first = 0;
1203         }
1204       else if (*name >= 'A' && *name <= 'Z')
1205         *name = *name - 'A' + 'a';
1206     }
1207 }
1208
1209
1210 /* Store an HTTP header line in LINE away.  Line continuation is
1211    supported as well as merging of headers with the same name. This
1212    function may modify LINE. */
1213 static gpg_error_t
1214 store_header (http_t hd, char *line)
1215 {
1216   size_t n;
1217   char *p, *value;
1218   header_t h;
1219
1220   n = strlen (line);
1221   if (n && line[n-1] == '\n')
1222     {
1223       line[--n] = 0;
1224       if (n && line[n-1] == '\r')
1225         line[--n] = 0;
1226     }
1227   if (!n)  /* we are never called to hit this. */
1228     return gpg_error (GPG_ERR_BUG);
1229   if (*line == ' ' || *line == '\t')
1230     {
1231       /* Continuation. This won't happen too often as it is not
1232          recommended.  We use a straightforward implementaion. */
1233       if (!hd->headers)
1234         return gpg_error (GPG_ERR_PROTOCOL_VIOLATION);
1235       n += strlen (hd->headers->value);
1236       p = xtrymalloc (n+1);
1237       if (!p)
1238         return gpg_error_from_errno (errno);
1239       strcpy (stpcpy (p, hd->headers->value), line);
1240       xfree (hd->headers->value);
1241       hd->headers->value = p;
1242       return 0;
1243     }
1244
1245   capitalize_header_name (line);
1246   p = strchr (line, ':');
1247   if (!p)
1248     return gpg_error (GPG_ERR_PROTOCOL_VIOLATION);
1249   *p++ = 0;
1250   while (*p == ' ' || *p == '\t')
1251     p++;
1252   value = p;
1253   
1254   for (h=hd->headers; h; h = h->next)
1255     if ( !strcmp (h->name, line) )
1256       break;
1257   if (h)
1258     {
1259       /* We have already seen a line with that name.  Thus we assume
1260          it is a comma separated list and merge them.  */
1261       p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1);
1262       if (!p)
1263         return gpg_error_from_errno (errno);
1264       strcpy (stpcpy (stpcpy (p, h->value), ","), value);
1265       xfree (h->value);
1266       h->value = p;
1267       return 0;
1268     }
1269
1270   /* Append a new header. */
1271   h = xtrymalloc (sizeof *h + strlen (line));
1272   if (!h)
1273     return gpg_error_from_errno (errno);
1274   strcpy (h->name, line);
1275   h->value = xtrymalloc (strlen (value)+1);
1276   if (!h->value)
1277     {
1278       xfree (h);
1279       return gpg_error_from_errno (errno);
1280     }
1281   strcpy (h->value, value);
1282   h->next = hd->headers;
1283   hd->headers = h;
1284
1285   return 0;
1286 }
1287
1288
1289 /* Return the header NAME from the last response.  The returned value
1290    is valid as along as HD has not been closed and no othe request has
1291    been send. If the header was not found, NULL is returned.  Name
1292    must be canonicalized, that is the first letter of each dash
1293    delimited part must be uppercase and all other letters lowercase.
1294    Note that the context must have been opened with the
1295    HTTP_FLAG_NEED_HEADER. */
1296 const char *
1297 http_get_header (http_t hd, const char *name)
1298 {
1299   header_t h;
1300
1301   for (h=hd->headers; h; h = h->next)
1302     if ( !strcmp (h->name, name) )
1303       return h->value;
1304   return NULL;
1305 }
1306
1307
1308
1309 /*
1310  * Parse the response from a server.
1311  * Returns: Errorcode and sets some files in the handle
1312  */
1313 static gpg_error_t
1314 parse_response (http_t hd)
1315 {
1316   char *line, *p, *p2;
1317   size_t maxlen, len;
1318
1319   /* Delete old header lines.  */
1320   while (hd->headers)
1321     {
1322       header_t tmp = hd->headers->next;
1323       xfree (hd->headers->value);
1324       xfree (hd->headers);
1325       hd->headers = tmp;
1326     }
1327
1328   /* Wait for the status line. */
1329   do
1330     {
1331       maxlen = MAX_LINELEN;
1332       len = my_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
1333       line = hd->buffer;
1334       if (!line)
1335         return gpg_error_from_errno (errno); /* Out of core. */
1336       if (!maxlen)
1337         return gpg_error (GPG_ERR_TRUNCATED); /* Line has been truncated. */
1338       if (!len)
1339         return gpg_error (GPG_ERR_EOF);
1340       if ( (hd->flags & HTTP_FLAG_LOG_RESP) )
1341         log_info ("RESP: `%.*s'\n",
1342                   (int)strlen(line)-(*line&&line[1]?2:0),line);
1343     }
1344   while (!*line);
1345
1346   if ((p = strchr (line, '/')))
1347     *p++ = 0;
1348   if (!p || strcmp (line, "HTTP"))
1349     return 0; /* Assume http 0.9. */
1350
1351   if ((p2 = strpbrk (p, " \t")))
1352     {
1353       *p2++ = 0;
1354       p2 += strspn (p2, " \t");
1355     }
1356   if (!p2)
1357     return 0; /* Also assume http 0.9. */
1358   p = p2;
1359   /* TODO: Add HTTP version number check. */
1360   if ((p2 = strpbrk (p, " \t")))
1361     *p2++ = 0;
1362   if (!isdigit ((unsigned int)p[0]) || !isdigit ((unsigned int)p[1])
1363       || !isdigit ((unsigned int)p[2]) || p[3])
1364     {
1365       /* Malformed HTTP status code - assume http 0.9. */
1366       hd->is_http_0_9 = 1;
1367       hd->status_code = 200;
1368       return 0;
1369     }
1370   hd->status_code = atoi (p);
1371
1372   /* Skip all the header lines and wait for the empty line. */
1373   do
1374     {
1375       maxlen = MAX_LINELEN;
1376       len = my_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
1377       line = hd->buffer;
1378       if (!line)
1379         return gpg_error_from_errno (errno); /* Out of core. */
1380       /* Note, that we can silently ignore truncated lines. */
1381       if (!len)
1382         return gpg_error (GPG_ERR_EOF);
1383       /* Trim line endings of empty lines. */
1384       if ((*line == '\r' && line[1] == '\n') || *line == '\n')
1385         *line = 0;
1386       if ( (hd->flags & HTTP_FLAG_LOG_RESP) )
1387         log_info ("RESP: `%.*s'\n",
1388                   (int)strlen(line)-(*line&&line[1]?2:0),line);
1389       if ( (hd->flags & HTTP_FLAG_NEED_HEADER) && *line )
1390         {
1391           gpg_error_t err = store_header (hd, line);
1392           if (err)
1393             return err;
1394         }
1395     }
1396   while (len && *line);
1397
1398   return 0;
1399 }
1400
1401 #if 0
1402 static int
1403 start_server ()
1404 {
1405   struct sockaddr_in mya;
1406   struct sockaddr_in peer;
1407   int fd, client;
1408   fd_set rfds;
1409   int addrlen;
1410   int i;
1411
1412   if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
1413     {
1414       log_error ("socket() failed: %s\n", strerror (errno));
1415       return -1;
1416     }
1417   i = 1;
1418   if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (byte *) & i, sizeof (i)))
1419     log_info ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno));
1420
1421   mya.sin_family = AF_INET;
1422   memset (&mya.sin_addr, 0, sizeof (mya.sin_addr));
1423   mya.sin_port = htons (11371);
1424
1425   if (bind (fd, (struct sockaddr *) &mya, sizeof (mya)))
1426     {
1427       log_error ("bind to port 11371 failed: %s\n", strerror (errno));
1428       sock_close (fd);
1429       return -1;
1430     }
1431
1432   if (listen (fd, 5))
1433     {
1434       log_error ("listen failed: %s\n", strerror (errno));
1435       sock_close (fd);
1436       return -1;
1437     }
1438
1439   for (;;)
1440     {
1441       FD_ZERO (&rfds);
1442       FD_SET (fd, &rfds);
1443
1444       if (select (fd + 1, &rfds, NULL, NULL, NULL) <= 0)
1445         continue;               /* ignore any errors */
1446
1447       if (!FD_ISSET (fd, &rfds))
1448         continue;
1449
1450       addrlen = sizeof peer;
1451       client = accept (fd, (struct sockaddr *) &peer, &addrlen);
1452       if (client == -1)
1453         continue;               /* oops */
1454
1455       log_info ("connect from %s\n", inet_ntoa (peer.sin_addr));
1456
1457       fflush (stdout);
1458       fflush (stderr);
1459       if (!fork ())
1460         {
1461           int c;
1462           FILE *fp;
1463
1464           fp = fdopen (client, "r");
1465           while ((c = getc (fp)) != EOF)
1466             putchar (c);
1467           fclose (fp);
1468           exit (0);
1469         }
1470       sock_close (client);
1471     }
1472
1473
1474   return 0;
1475 }
1476 #endif
1477
1478 /* Actually connect to a server.  Returns the file descripto or -1 on
1479    error.  ERRNO is set on error. */
1480 static int
1481 connect_server (const char *server, unsigned short port,
1482                 unsigned int flags, const char *srvtag)
1483 {
1484   int sock = -1;
1485   int srvcount = 0;
1486   int hostfound = 0;
1487   int srv, connected;
1488   int last_errno = 0;
1489   struct srventry *serverlist = NULL;
1490
1491 #ifdef HAVE_W32_SYSTEM
1492   unsigned long inaddr;
1493
1494   init_sockets();
1495   /* Win32 gethostbyname doesn't handle IP addresses internally, so we
1496      try inet_addr first on that platform only. */
1497   inaddr = inet_addr(server);
1498   if ( inaddr != INADDR_NONE )
1499     {
1500       struct sockaddr_in addr;
1501       
1502       memset(&addr,0,sizeof(addr));
1503       
1504       sock = socket(AF_INET,SOCK_STREAM,0);
1505       if ( sock==INVALID_SOCKET )
1506         {
1507           log_error("error creating socket: ec=%d\n",(int)WSAGetLastError());
1508           return -1;
1509         }
1510
1511       addr.sin_family = AF_INET; 
1512       addr.sin_port = htons(port);
1513       memcpy (&addr.sin_addr,&inaddr,sizeof(inaddr));      
1514
1515       if (!connect (sock,(struct sockaddr *)&addr,sizeof(addr)) )
1516         return sock;
1517       sock_close(sock);
1518       return -1;
1519     }
1520 #endif /*HAVE_W32_SYSTEM*/
1521
1522 #ifdef USE_DNS_SRV
1523   /* Do the SRV thing */
1524   if ((flags & HTTP_FLAG_TRY_SRV) && srvtag)
1525     {
1526       /* We're using SRV, so append the tags. */
1527       if (1+strlen (srvtag) + 6 + strlen (server) + 1 <= MAXDNAME)
1528         {
1529           char srvname[MAXDNAME];
1530
1531           stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srvtag),
1532                            "._tcp."), server);
1533           srvcount = getsrv (srvname, &serverlist);
1534         }
1535     }
1536 #endif /*USE_DNS_SRV*/
1537
1538   if (!serverlist)
1539     {
1540       /* Either we're not using SRV, or the SRV lookup failed.  Make
1541          up a fake SRV record. */
1542       serverlist = xtrycalloc (1, sizeof *serverlist);
1543       if (!serverlist)
1544         return -1; /* Out of core.  */
1545       serverlist->port = port;
1546       strncpy (serverlist->target, server, MAXDNAME);
1547       serverlist->target[MAXDNAME-1] = '\0';
1548       srvcount = 1;
1549     }
1550
1551 #ifdef HAVE_GETADDRINFO
1552   connected = 0;
1553   for (srv=0; srv < srvcount && !connected; srv++)
1554     {
1555       struct addrinfo hints, *res, *ai;
1556       char portstr[35];
1557
1558       sprintf (portstr, "%hu", port);
1559       memset (&hints, 0, sizeof (hints));
1560       hints.ai_socktype = SOCK_STREAM;
1561       if (getaddrinfo (serverlist[srv].target, portstr, &hints, &res))
1562         continue; /* Not found - try next one. */
1563       hostfound = 1;
1564
1565       for (ai = res; ai && !connected; ai = ai->ai_next)
1566         {
1567           if (sock != -1)
1568             sock_close (sock);
1569           sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
1570           if (sock == -1)
1571             {
1572               int save_errno = errno;
1573               log_error ("error creating socket: %s\n", strerror (errno));
1574               freeaddrinfo (res);
1575               xfree (serverlist);
1576               errno = save_errno;
1577               return -1;
1578             }
1579           
1580           if (connect (sock, ai->ai_addr, ai->ai_addrlen))
1581             last_errno = errno;
1582           else
1583             connected = 1;
1584         }
1585       freeaddrinfo (res);
1586     }
1587 #else /* !HAVE_GETADDRINFO */
1588   connected = 0;
1589   for (srv=0; srv < srvcount && !connected; srv++)
1590     {
1591       int i;
1592       struct hostent *host = NULL;
1593       struct sockaddr_in addr;
1594
1595       /* Note: This code is not thread-safe.  */
1596
1597       memset (&addr, 0, sizeof (addr));
1598       host = gethostbyname (serverlist[srv].target);
1599       if (!host)
1600         continue;
1601       hostfound = 1;
1602
1603       if (sock != -1)
1604         sock_close (sock);
1605       sock = socket (host->h_addrtype, SOCK_STREAM, 0);
1606       if (sock == -1)
1607         {
1608           log_error (_("error creating socket: %s\n"), strerror (errno));
1609           xfree (serverlist);
1610           return -1;
1611         }
1612       
1613       addr.sin_family = host->h_addrtype;
1614       if (addr.sin_family != AF_INET)
1615         {
1616           log_error ("unknown address family for `%s'\n",
1617                      serverlist[srv].target);
1618           xfree (serverlist);
1619           return -1;
1620         }
1621       addr.sin_port = htons (serverlist[srv].port);
1622       if (host->h_length != 4)
1623         {
1624           log_error ("illegal address length for `%s'\n",
1625                      serverlist[srv].target);
1626           xfree (serverlist);
1627           return -1;
1628         }
1629
1630       /* Try all A records until one responds. */
1631       for (i = 0; host->h_addr_list[i] && !connected; i++)
1632         {
1633           memcpy (&addr.sin_addr, host->h_addr_list[i], host->h_length);
1634           if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)))
1635             last_errno = errno;
1636           else
1637             {
1638               connected = 1;
1639               break;
1640             }
1641         }
1642     }
1643 #endif /* !HAVE_GETADDRINFO */
1644
1645   xfree (serverlist);
1646
1647   if (!connected)
1648     {
1649 #ifdef HAVE_W32_SYSTEM
1650       log_error ("can't connect to `%s': %s%sec=%d\n",
1651                    server,
1652                    hostfound? "":_("host not found"),
1653                    hostfound? "":" - ", (int)WSAGetLastError());
1654 #else
1655       log_error ("can't connect to `%s': %s\n",
1656                  server,
1657                  hostfound? strerror (last_errno):"host not found");
1658 #endif
1659       if (sock != -1)
1660         sock_close (sock);
1661       errno = last_errno;
1662       return -1;
1663     }
1664   return sock;
1665 }
1666
1667
1668 static gpg_error_t
1669 write_server (int sock, const char *data, size_t length)
1670 {
1671   int nleft;
1672
1673   nleft = length;
1674   while (nleft > 0)
1675     {
1676 #ifdef HAVE_W32_SYSTEM
1677       int nwritten;
1678       
1679       nwritten = send (sock, data, nleft, 0);
1680       if ( nwritten == SOCKET_ERROR ) 
1681         {
1682           log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
1683           return G10ERR_NETWORK;
1684         }
1685 #else /*!HAVE_W32_SYSTEM*/
1686       int nwritten = write (sock, data, nleft);
1687       if (nwritten == -1)
1688         {
1689           if (errno == EINTR)
1690             continue;
1691           if (errno == EAGAIN)
1692             {
1693               struct timeval tv;
1694
1695               tv.tv_sec = 0;
1696               tv.tv_usec = 50000;
1697               select (0, NULL, NULL, NULL, &tv);
1698               continue;
1699             }
1700           log_info ("network write failed: %s\n", strerror (errno));
1701           return gpg_error_from_errno (errno);
1702         }
1703 #endif /*!HAVE_W32_SYSTEM*/
1704       nleft -= nwritten;
1705       data += nwritten;
1706     }
1707
1708   return 0;
1709 }
1710
1711
1712 \f
1713 #ifdef HTTP_USE_ESTREAM
1714 /* Read handler for estream.  */
1715 static ssize_t
1716 cookie_read (void *cookie, void *buffer, size_t size)
1717 {
1718   cookie_t c = cookie;
1719   int nread;
1720
1721 #ifdef HTTP_USE_GNUTLS
1722   if (c->tls_session)
1723     {
1724     again:
1725       nread = gnutls_record_recv (c->tls_session, buffer, size);
1726       if (nread < 0)
1727         {
1728           if (nread == GNUTLS_E_INTERRUPTED)
1729             goto again;
1730           if (nread == GNUTLS_E_AGAIN)
1731             {
1732               struct timeval tv;
1733               
1734               tv.tv_sec = 0;
1735               tv.tv_usec = 50000;
1736               select (0, NULL, NULL, NULL, &tv);
1737               goto again;
1738             }
1739           if (nread == GNUTLS_E_REHANDSHAKE)
1740             goto again; /* A client is allowed to just ignore this request. */
1741           log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
1742           errno = EIO;
1743           return -1;
1744         }
1745     }
1746   else
1747 #endif /*HTTP_USE_GNUTLS*/
1748     {
1749       do
1750         {
1751           nread = read (c->fd, buffer, size);
1752         }
1753       while (nread == -1 && errno == EINTR);
1754     }
1755
1756   return nread;
1757 }
1758
1759 /* Write handler for estream.  */
1760 static ssize_t
1761 cookie_write (void *cookie, const void *buffer, size_t size)
1762 {
1763   cookie_t c = cookie;
1764   int nwritten = 0;
1765
1766 #ifdef HTTP_USE_GNUTLS
1767   if (c->tls_session)
1768     {
1769       int nleft = size;
1770       while (nleft > 0)
1771         {
1772           nwritten = gnutls_record_send (c->tls_session, buffer, nleft); 
1773           if (nwritten <= 0)
1774             {
1775               if (nwritten == GNUTLS_E_INTERRUPTED)
1776                 continue;
1777               if (nwritten == GNUTLS_E_AGAIN)
1778                 {
1779                   struct timeval tv;
1780                   
1781                   tv.tv_sec = 0;
1782                   tv.tv_usec = 50000;
1783                   select (0, NULL, NULL, NULL, &tv);
1784                   continue;
1785                 }
1786               log_info ("TLS network write failed: %s\n",
1787                         gnutls_strerror (nwritten));
1788               errno = EIO;
1789               return -1;
1790             }
1791           nleft -= nwritten;
1792           buffer += nwritten;
1793         }
1794     }
1795   else
1796 #endif /*HTTP_USE_GNUTLS*/
1797     {
1798       if ( write_server (c->fd, buffer, size) )
1799         {
1800           errno = EIO;
1801           nwritten = -1;
1802         }
1803       else
1804         nwritten = size;
1805     }
1806
1807   return nwritten;
1808 }
1809
1810 /* Close handler for estream.  */
1811 static int
1812 cookie_close (void *cookie)
1813 {
1814   cookie_t c = cookie;
1815
1816   if (!c)
1817     return 0;
1818
1819  #ifdef HTTP_USE_GNUTLS
1820   if (c->tls_session && !c->keep_socket)
1821     {
1822       gnutls_bye (c->tls_session, GNUTLS_SHUT_RDWR);
1823     }
1824 #endif /*HTTP_USE_GNUTLS*/
1825   if (c->fd != -1 && !c->keep_socket)
1826     close (c->fd);
1827
1828   xfree (c);
1829   return 0;
1830 }
1831 #endif /*HTTP_USE_ESTREAM*/
1832
1833
1834
1835 \f
1836 /**** Test code ****/
1837 #ifdef TEST
1838
1839 static gpg_error_t
1840 verify_callback (http_t hd, void *tls_context, int reserved)
1841 {
1842   log_info ("verification of certificates skipped\n");
1843   return 0;
1844 }
1845
1846
1847
1848 /* static void */
1849 /* my_gnutls_log (int level, const char *text) */
1850 /* { */
1851 /*   fprintf (stderr, "gnutls:L%d: %s", level, text); */
1852 /* } */
1853
1854 int
1855 main (int argc, char **argv)
1856 {
1857   int rc;
1858   parsed_uri_t uri;
1859   uri_tuple_t r;
1860   http_t hd;
1861   int c;
1862   gnutls_session_t tls_session = NULL;
1863 #ifdef HTTP_USE_GNUTLS
1864   gnutls_certificate_credentials certcred;
1865   const int certprio[] = { GNUTLS_CRT_X509, 0 };
1866 #endif /*HTTP_USE_GNUTLS*/
1867   header_t hdr;
1868
1869 #ifdef HTTP_USE_ESTREAM
1870   es_init ();
1871 #endif
1872   log_set_prefix ("http-test", 1 | 4);
1873   if (argc == 1)
1874     {
1875       /*start_server (); */
1876       return 0;
1877     }
1878
1879   if (argc != 2)
1880     {
1881       fprintf (stderr, "usage: http-test uri\n");
1882       return 1;
1883     }
1884   argc--;
1885   argv++;
1886
1887 #ifdef HTTP_USE_GNUTLS
1888   rc = gnutls_global_init ();
1889   if (rc)
1890     log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc));
1891   rc = gnutls_certificate_allocate_credentials (&certcred);
1892   if (rc)
1893     log_error ("gnutls_certificate_allocate_credentials failed: %s\n",
1894                gnutls_strerror (rc));
1895 /*   rc = gnutls_certificate_set_x509_trust_file */
1896 /*     (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */
1897 /*   if (rc) */
1898 /*     log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */
1899 /*                gnutls_strerror (rc)); */
1900   rc = gnutls_init (&tls_session, GNUTLS_CLIENT);
1901   if (rc)
1902     log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc));
1903   rc = gnutls_set_default_priority (tls_session);
1904   if (rc)
1905     log_error ("gnutls_set_default_priority failed: %s\n",
1906                gnutls_strerror (rc));
1907   rc = gnutls_certificate_type_set_priority (tls_session, certprio);
1908   if (rc)
1909     log_error ("gnutls_certificate_type_set_priority failed: %s\n",
1910                gnutls_strerror (rc));
1911   rc = gnutls_credentials_set (tls_session, GNUTLS_CRD_CERTIFICATE, certcred);
1912   if (rc)
1913     log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc));
1914 /*   gnutls_global_set_log_function (my_gnutls_log); */
1915 /*   gnutls_global_set_log_level (4); */
1916
1917   http_register_tls_callback (verify_callback);
1918 #endif /*HTTP_USE_GNUTLS*/
1919
1920   rc = http_parse_uri (&uri, *argv);
1921   if (rc)
1922     {
1923       log_error ("`%s': %s\n", *argv, gpg_strerror (rc));
1924       http_release_parsed_uri (uri);
1925       return 1;
1926     }
1927
1928   printf ("Scheme: %s\n", uri->scheme);
1929   printf ("Host  : %s\n", uri->host);
1930   printf ("Port  : %u\n", uri->port);
1931   printf ("Path  : %s\n", uri->path);
1932   for (r = uri->params; r; r = r->next)
1933     {
1934       printf ("Params: %s", r->name);
1935       if (!r->no_value)
1936         {
1937           printf ("=%s", r->value);
1938           if (strlen (r->value) != r->valuelen)
1939             printf (" [real length=%d]", (int) r->valuelen);
1940         }
1941       putchar ('\n');
1942     }
1943   for (r = uri->query; r; r = r->next)
1944     {
1945       printf ("Query : %s", r->name);
1946       if (!r->no_value)
1947         {
1948           printf ("=%s", r->value);
1949           if (strlen (r->value) != r->valuelen)
1950             printf (" [real length=%d]", (int) r->valuelen);
1951         }
1952       putchar ('\n');
1953     }
1954   http_release_parsed_uri (uri);
1955   uri = NULL;
1956
1957   rc = http_open_document (&hd, *argv, NULL, 
1958                            HTTP_FLAG_NO_SHUTDOWN | HTTP_FLAG_NEED_HEADER,
1959                            NULL, tls_session);
1960   if (rc)
1961     {
1962       log_error ("can't get `%s': %s\n", *argv, gpg_strerror (rc));
1963       return 1;
1964     }
1965   log_info ("open_http_document succeeded; status=%u\n",
1966             http_get_status_code (hd));
1967   for (hdr = hd->headers; hdr; hdr = hdr->next)
1968     printf ("HDR: %s: %s\n", hdr->name, hdr->value);
1969   switch (http_get_status_code (hd))
1970     {
1971     case 200:
1972       while ((c = P_ES(getc) (http_get_read_ptr (hd))) != EOF)
1973         putchar (c);
1974       break;
1975     case 301:
1976     case 302:
1977       printf ("Redirected to `%s'\n", http_get_header (hd, "Location"));
1978       break;
1979     }
1980   http_close (hd, 0);
1981
1982 #ifdef HTTP_USE_GNUTLS
1983   gnutls_deinit (tls_session);
1984   gnutls_certificate_free_credentials (certcred);
1985   gnutls_global_deinit ();
1986 #endif /*HTTP_USE_GNUTLS*/
1987
1988   return 0;
1989 }
1990 #endif /*TEST*/
1991
1992
1993 /*
1994 Local Variables:
1995 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"
1996 End:
1997 */