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