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