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