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