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