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