Updated to automake 1.10.
[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
588         return gpg_error (GPG_ERR_INV_URI); /* Unsupported scheme */
589
590       p = p2;
591
592       /* Find the hostname */
593       if (*p != '/')
594         return gpg_error (GPG_ERR_INV_URI); /* Does not start with a slash. */
595
596       p++;
597       if (*p == '/') /* There seems to be a hostname. */
598         { 
599           p++;
600           if ((p2 = strchr (p, '/')))
601             *p2++ = 0;
602
603           /* Check for username/password encoding */
604           if ((p3 = strchr (p, '@')))
605             {
606               uri->auth = p;
607               *p3++ = '\0';
608               p = p3;
609             }
610
611           for (pp=p; *pp; pp++)
612             *pp = tolower (*(unsigned char*)pp);
613           uri->host = p;
614           if ((p3 = strchr (p, ':')))
615             {
616               *p3++ = 0;
617               uri->port = atoi (p3);
618             }
619
620           uri->host = p;
621           if ((n = remove_escapes (uri->host)) < 0)
622             return gpg_error (GPG_ERR_BAD_URI);
623           if (n != strlen (p))
624             return gpg_error (GPG_ERR_BAD_URI); /* Hostname incudes a Nul. */
625           p = p2 ? p2 : NULL;
626         }
627     } /* End global URI part. */
628
629   /* Parse the pathname part */
630   if (!p || !*p)
631     return 0;  /* We don't have a path.  Okay. */
632
633   /* TODO: Here we have to check params. */
634
635   /* Do we have a query part? */
636   if ((p2 = strchr (p, '?')))
637     *p2++ = 0;
638
639   uri->path = p;
640   if ((n = remove_escapes (p)) < 0)
641     return gpg_error (GPG_ERR_BAD_URI);
642   if (n != strlen (p))
643     return gpg_error (GPG_ERR_BAD_URI); /* Path includes a Nul. */
644   p = p2 ? p2 : NULL;
645
646   if (!p || !*p)        
647     return 0; /* We don't have a query string.  Okay. */
648
649   /* Now parse the query string. */
650   tail = &uri->query;
651   for (;;)
652     {
653       uri_tuple_t elem;
654
655       if ((p2 = strchr (p, '&')))
656         *p2++ = 0;
657       if (!(elem = parse_tuple (p)))
658         return gpg_error (GPG_ERR_BAD_URI);
659       *tail = elem;
660       tail = &elem->next;
661
662       if (!p2)
663         break; /* Ready. */
664       p = p2;
665     }
666
667   return 0;
668 }
669
670
671 /*
672  * Remove all %xx escapes; this is done in-place.  Returns: New length
673  * of the string.
674  */
675 static int
676 remove_escapes (char *string)
677 {
678   int n = 0;
679   unsigned char *p, *s;
680
681   for (p = s = (unsigned char*)string; *s; s++)
682     {
683       if (*s == '%')
684         {
685           if (s[1] && s[2] && isxdigit (s[1]) && isxdigit (s[2]))
686             {
687               s++;
688               *p = *s >= '0' && *s <= '9' ? *s - '0' :
689                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
690               *p <<= 4;
691               s++;
692               *p |= *s >= '0' && *s <= '9' ? *s - '0' :
693                 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
694               p++;
695               n++;
696             }
697           else
698             {
699               *p++ = *s++;
700               if (*s)
701                 *p++ = *s++;
702               if (*s)
703                 *p++ = *s++;
704               if (*s)
705                 *p = 0;
706               return -1; /* Bad URI. */
707             }
708         }
709       else
710         {
711           *p++ = *s;
712           n++;
713         }
714     }
715   *p = 0; /* Make sure to keep a string terminator. */
716   return n;
717 }
718
719
720 static int
721 insert_escapes (char *buffer, const char *string,
722                 const char *special)
723 {
724   const unsigned char *s = (const unsigned char*)string;
725   int n = 0;
726
727   for (; *s; s++)
728     {
729       if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
730         {
731           if (buffer)
732             *(unsigned char*)buffer++ = *s;
733           n++;
734         }
735       else
736         {
737           if (buffer)
738             {
739               sprintf (buffer, "%%%02X", *s);
740               buffer += 3;
741             }
742           n += 3;
743         }
744     }
745   return n;
746 }
747
748
749 /* Allocate a new string from STRING using standard HTTP escaping as
750    well as escaping of characters given in SPECIALS.  A common pattern
751    for SPECIALS is "%;?&=". However it depends on the needs, for
752    example "+" and "/: often needs to be escaped too.  Returns NULL on
753    failure and sets ERRNO. */
754 char *
755 http_escape_string (const char *string, const char *specials)
756 {
757   int n;
758   char *buf;
759
760   n = insert_escapes (NULL, string, specials);
761   buf = xtrymalloc (n+1);
762   if (buf)
763     {
764       insert_escapes (buf, string, specials);
765       buf[n] = 0;
766     }
767   return buf;
768 }
769
770
771
772 static uri_tuple_t
773 parse_tuple (char *string)
774 {
775   char *p = string;
776   char *p2;
777   int n;
778   uri_tuple_t tuple;
779
780   if ((p2 = strchr (p, '=')))
781     *p2++ = 0;
782   if ((n = remove_escapes (p)) < 0)
783     return NULL; /* Bad URI. */
784   if (n != strlen (p))
785     return NULL; /* Name with a Nul in it. */
786   tuple = xtrycalloc (1, sizeof *tuple);
787   if (!tuple)
788     return NULL; /* Out of core. */
789   tuple->name = p;
790   if (!p2) /* We have only the name, so we assume an empty value string. */
791     {
792       tuple->value = p + strlen (p);
793       tuple->valuelen = 0;
794       tuple->no_value = 1; /* Explicitly mark that we have seen no '='. */
795     }
796   else /* Name and value. */
797     {
798       if ((n = remove_escapes (p2)) < 0)
799         {
800           xfree (tuple);
801           return NULL; /* Bad URI. */
802         }
803       tuple->value = p2;
804       tuple->valuelen = n;
805     }
806   return tuple;
807 }
808
809
810 /*
811  * Send a HTTP request to the server
812  * Returns 0 if the request was successful
813  */
814 static gpg_error_t
815 send_request (http_t hd, const char *auth, const char *proxy)
816 {
817   gnutls_session_t tls_session;
818   gpg_error_t err;
819   const char *server;
820   char *request, *p;
821   unsigned short port;
822   const char *http_proxy = NULL;
823   char *proxy_authstr = NULL;
824   char *authstr = NULL;
825   int save_errno;
826
827   tls_session = hd->tls_context;
828   if (hd->uri->use_tls && !tls_session)
829     {
830       log_error ("TLS requested but no GNUTLS context provided\n");
831       return gpg_error (GPG_ERR_INTERNAL);
832     }
833
834   server = *hd->uri->host ? hd->uri->host : "localhost";
835   port = hd->uri->port ? hd->uri->port : 80;
836
837   if ( (proxy && *proxy)
838        || ( (hd->flags & HTTP_FLAG_TRY_PROXY)
839             && (http_proxy = getenv (HTTP_PROXY_ENV)) 
840             && *http_proxy ))
841     {
842       parsed_uri_t uri;
843
844       if (proxy)
845         http_proxy = proxy;
846
847       err = http_parse_uri (&uri, http_proxy);
848       if (err)
849         {
850           log_error ("invalid HTTP proxy (%s): %s\n",
851                      http_proxy, gpg_strerror (err));
852           http_release_parsed_uri (uri);
853           return gpg_error (GPG_ERR_CONFIGURATION);
854
855         }
856
857       if (uri->auth)
858         {
859           remove_escapes (uri->auth);
860           proxy_authstr = make_header_line ("Proxy-Authorization: Basic ",
861                                             "\r\n",
862                                             uri->auth, strlen(uri->auth));
863           if (!proxy_authstr)
864             {
865               err = gpg_error_from_syserror ();
866               http_release_parsed_uri (uri);
867               return err;
868             }
869         }
870
871       hd->sock = connect_server (*uri->host ? uri->host : "localhost",
872                                  uri->port ? uri->port : 80,
873                                  hd->flags, hd->uri->scheme);
874       save_errno = errno;
875       http_release_parsed_uri (uri);
876     }
877   else
878     {
879       hd->sock = connect_server (server, port, hd->flags, hd->uri->scheme);
880       save_errno = errno;
881     }
882
883   if (hd->sock == -1)
884     {
885       xfree (proxy_authstr);
886       return (save_errno 
887               ? gpg_error_from_errno (save_errno)
888               : gpg_error (GPG_ERR_NOT_FOUND));
889     }
890
891 #ifdef HTTP_USE_GNUTLS
892   if (hd->uri->use_tls)
893     {
894       int rc;
895
896       gnutls_transport_set_ptr (tls_session, (gnutls_transport_ptr_t)hd->sock);
897       do
898         {
899           rc = gnutls_handshake (tls_session);
900         }
901       while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
902       if (rc < 0)
903         {
904           log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
905           xfree (proxy_authstr);
906           return gpg_error (GPG_ERR_NETWORK);
907         }
908
909       if (tls_callback)
910         {
911           err = tls_callback (hd, tls_session, 0);
912           if (err)
913             {
914               log_info ("TLS connection authentication failed: %s\n",
915                         gpg_strerror (err));
916               xfree (proxy_authstr);
917               return err;
918             }
919         }
920     }
921 #endif /*HTTP_USE_GNUTLS*/
922
923   if (auth || hd->uri->auth)
924     {
925       char *myauth;
926       
927       if (auth)
928         {
929           myauth = xtrystrdup (auth);
930           if (!myauth)
931             {
932               xfree (proxy_authstr);
933               return gpg_error_from_syserror ();
934             }
935           remove_escapes (myauth);
936         }
937       else
938         {
939           remove_escapes (hd->uri->auth);
940           myauth = hd->uri->auth;
941         }
942
943       authstr = make_header_line ("Authorization: Basic %s", "\r\n",
944                                   myauth, strlen (myauth));
945       if (auth)
946         xfree (myauth);
947
948       if (!authstr)
949         {
950           xfree (proxy_authstr);
951           return gpg_error_from_syserror ();
952         }
953     }
954   
955   p = build_rel_path (hd->uri);
956   if (!p)
957     return gpg_error_from_syserror ();
958
959   request = xtrymalloc (2 * strlen (server) 
960                         + strlen (p)
961                         + (authstr?strlen(authstr):0)
962                         + (proxy_authstr?strlen(proxy_authstr):0)
963                         + 100);
964   if (!request)
965     {
966       err = gpg_error_from_syserror ();
967       xfree (p);
968       xfree (authstr);
969       xfree (proxy_authstr);
970       return err;
971     }
972
973   if (http_proxy && *http_proxy)
974     {
975       sprintf (request, "%s http://%s:%hu%s%s HTTP/1.0\r\n%s%s",
976                hd->req_type == HTTP_REQ_GET ? "GET" :
977                hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
978                hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
979                server, port, *p == '/' ? "" : "/", p,
980                authstr ? authstr : "",
981                proxy_authstr ? proxy_authstr : "");
982     }
983   else
984     {
985       char portstr[35];
986         
987       if (port == 80)
988         *portstr = 0;
989       else
990         sprintf (portstr, ":%u", port);
991
992       sprintf (request, "%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
993                hd->req_type == HTTP_REQ_GET ? "GET" :
994                hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
995                hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
996                *p == '/' ? "" : "/", p, server, portstr,
997                authstr? authstr:"");
998     }
999   xfree (p);
1000
1001
1002 #ifdef HTTP_USE_ESTREAM
1003   /* First setup estream so that we can write even the first line
1004      using estream.  This is also required for the sake of gnutls. */
1005   {
1006     cookie_t cookie;
1007
1008     cookie = xtrycalloc (1, sizeof *cookie);
1009     if (!cookie)
1010       {
1011         err = gpg_error_from_syserror ();
1012         goto leave;
1013       }
1014     cookie->fd = hd->sock;
1015     if (hd->uri->use_tls)
1016       {
1017         cookie->tls_session = tls_session;
1018         hd->write_cookie = cookie;
1019       }
1020
1021     hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1022     if (!hd->fp_write)
1023       {
1024         xfree (cookie);
1025         err = gpg_error_from_syserror ();
1026       }
1027     else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
1028       err = gpg_error_from_syserror ();
1029     else
1030       err = 0;
1031   }
1032
1033  leave:
1034
1035 #else /*!HTTP_USE_ESTREAM*/
1036   /* We send out the start of the request through our own send
1037      function and only then assign a stdio stream.  This allows for
1038      better error reporting that through standard stdio means. */
1039   err = write_server (hd->sock, request, strlen (request));
1040   if (!err)
1041     {
1042       hd->fp_write = fdopen (hd->sock, "w");
1043       if (!hd->fp_write)
1044         err = gpg_error_from_syserror ();
1045     }
1046 #endif /*!HTTP_USE_ESTREAM*/
1047
1048   xfree (request);
1049   xfree (authstr);
1050   xfree (proxy_authstr);
1051
1052   return err;
1053 }
1054
1055
1056 /*
1057  * Build the relative path from the parsed URI.  Minimal
1058  * implementation.  May return NULL in case of memory failure; errno
1059  * is then set accordingly.
1060  */
1061 static char *
1062 build_rel_path (parsed_uri_t uri)
1063 {
1064   uri_tuple_t r;
1065   char *rel_path, *p;
1066   int n;
1067
1068   /* Count the needed space. */
1069   n = insert_escapes (NULL, uri->path, "%;?&");
1070   /* TODO: build params. */
1071   for (r = uri->query; r; r = r->next)
1072     {
1073       n++; /* '?'/'&' */
1074       n += insert_escapes (NULL, r->name, "%;?&=");
1075       if (!r->no_value)
1076         {
1077           n++; /* '=' */
1078           n += insert_escapes (NULL, r->value, "%;?&=");
1079         }
1080     }
1081   n++;
1082
1083   /* Now allocate and copy. */
1084   p = rel_path = xtrymalloc (n);
1085   if (!p)
1086     return NULL;
1087   n = insert_escapes (p, uri->path, "%;?&");
1088   p += n;
1089   /* TODO: add params. */
1090   for (r = uri->query; r; r = r->next)
1091     {
1092       *p++ = r == uri->query ? '?' : '&';
1093       n = insert_escapes (p, r->name, "%;?&=");
1094       p += n;
1095       if (!r->no_value)
1096         {
1097           *p++ = '=';
1098           /* TODO: Use valuelen. */
1099           n = insert_escapes (p, r->value, "%;?&=");
1100           p += n;
1101         }
1102     }
1103   *p = 0;
1104   return rel_path;
1105 }
1106
1107
1108
1109 /*
1110    Same as fgets() but if the buffer is too short a larger one will be
1111    allocated up to some limit *MAX_LENGTH.  A line is considered a
1112    byte stream ending in a LF.  Returns the length of the line. EOF is
1113    indicated by a line of length zero. The last LF may be missing due
1114    to an EOF.  If MAX_LENGTH is zero on return, the line has been
1115    truncated.  If the returned buffer is NULL, not enough memory was
1116    enable to increase it, the return value will also be 0 and some
1117    bytes might have been lost which should be no problem becuase
1118    out-of-memory is pretty fatal for most applications.
1119
1120    If a line has been truncated, the file pointer is internally moved
1121    forward to the end of the line.
1122
1123    Note: The returned buffer is allocated with enough extra space to
1124    append a CR,LF,Nul
1125  */
1126 static size_t
1127 my_read_line (
1128 #ifdef HTTP_USE_ESTREAM
1129               estream_t fp,
1130 #else
1131               FILE *fp,
1132 #endif
1133               char **addr_of_buffer,
1134               size_t *length_of_buffer, size_t *max_length)
1135 {
1136   int c;
1137   char *buffer = *addr_of_buffer;
1138   size_t length = *length_of_buffer;
1139   size_t nbytes = 0;
1140   size_t maxlen = *max_length;
1141   char *p;
1142
1143   if (!buffer) /* Must allocate a new buffer. */
1144     {           
1145       length = 256;
1146       buffer = xtrymalloc (length);
1147       *addr_of_buffer = buffer;
1148       if (!buffer)
1149         {
1150           *length_of_buffer = *max_length = 0;
1151           return 0;
1152         }
1153       *length_of_buffer = length;
1154     }
1155
1156   length -= 3; /* Reserve 3 bytes (cr,lf,eol). */
1157   p = buffer;
1158   while ((c = P_ES(getc) (fp)) != EOF)
1159     {
1160       if (nbytes == length) /* Increase the buffer. */
1161         {                       
1162           if (length > maxlen) /* Limit reached. */
1163             {
1164               /* Skip the rest of the line. */
1165               while (c != '\n' && (c = P_ES(getc) (fp)) != EOF)
1166                 ;
1167               *p++ = '\n'; /* Always append a LF (we reserved some space). */
1168               nbytes++;
1169               *max_length = 0; /* Indicate truncation */
1170               break; /*(the while loop)*/
1171             }
1172           length += 3; /* Adjust for the reserved bytes. */
1173           length += length < 1024 ? 256 : 1024;
1174           *addr_of_buffer = xtryrealloc (buffer, length);
1175           if (!*addr_of_buffer)
1176             {
1177               int save_errno = errno;
1178               xfree (buffer);
1179               *length_of_buffer = *max_length = 0;
1180               errno = save_errno;
1181               return 0;
1182             }
1183           buffer = *addr_of_buffer;
1184           *length_of_buffer = length;
1185           length -= 3; /* And re-adjust for the reservation. */
1186           p = buffer + nbytes;
1187         }
1188       *p++ = c;
1189       nbytes++;
1190       if (c == '\n')
1191         break;
1192     }
1193   *p = 0; /* Make sure the line is a string. */
1194
1195   return nbytes;
1196 }
1197
1198
1199 /* Transform a header name into a standard capitalized format; e.g.
1200    "Content-Type".  Conversion stops at the colon.  As usual we don't
1201    use the localized versions of ctype.h. */
1202 static void
1203 capitalize_header_name (char *name)
1204 {
1205   int first = 1;
1206
1207   for (; *name && *name != ':'; name++)
1208     {
1209       if (*name == '-')
1210         first = 1;
1211       else if (first)
1212         {
1213           if (*name >= 'a' && *name <= 'z')
1214             *name = *name - 'a' + 'A';
1215           first = 0;
1216         }
1217       else if (*name >= 'A' && *name <= 'Z')
1218         *name = *name - 'A' + 'a';
1219     }
1220 }
1221
1222
1223 /* Store an HTTP header line in LINE away.  Line continuation is
1224    supported as well as merging of headers with the same name. This
1225    function may modify LINE. */
1226 static gpg_error_t
1227 store_header (http_t hd, char *line)
1228 {
1229   size_t n;
1230   char *p, *value;
1231   header_t h;
1232
1233   n = strlen (line);
1234   if (n && line[n-1] == '\n')
1235     {
1236       line[--n] = 0;
1237       if (n && line[n-1] == '\r')
1238         line[--n] = 0;
1239     }
1240   if (!n)  /* we are never called to hit this. */
1241     return gpg_error (GPG_ERR_BUG);
1242   if (*line == ' ' || *line == '\t')
1243     {
1244       /* Continuation. This won't happen too often as it is not
1245          recommended.  We use a straightforward implementaion. */
1246       if (!hd->headers)
1247         return gpg_error (GPG_ERR_PROTOCOL_VIOLATION);
1248       n += strlen (hd->headers->value);
1249       p = xtrymalloc (n+1);
1250       if (!p)
1251         return gpg_error_from_syserror ();
1252       strcpy (stpcpy (p, hd->headers->value), line);
1253       xfree (hd->headers->value);
1254       hd->headers->value = p;
1255       return 0;
1256     }
1257
1258   capitalize_header_name (line);
1259   p = strchr (line, ':');
1260   if (!p)
1261     return gpg_error (GPG_ERR_PROTOCOL_VIOLATION);
1262   *p++ = 0;
1263   while (*p == ' ' || *p == '\t')
1264     p++;
1265   value = p;
1266   
1267   for (h=hd->headers; h; h = h->next)
1268     if ( !strcmp (h->name, line) )
1269       break;
1270   if (h)
1271     {
1272       /* We have already seen a line with that name.  Thus we assume
1273          it is a comma separated list and merge them.  */
1274       p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1);
1275       if (!p)
1276         return gpg_error_from_syserror ();
1277       strcpy (stpcpy (stpcpy (p, h->value), ","), value);
1278       xfree (h->value);
1279       h->value = p;
1280       return 0;
1281     }
1282
1283   /* Append a new header. */
1284   h = xtrymalloc (sizeof *h + strlen (line));
1285   if (!h)
1286     return gpg_error_from_syserror ();
1287   strcpy (h->name, line);
1288   h->value = xtrymalloc (strlen (value)+1);
1289   if (!h->value)
1290     {
1291       xfree (h);
1292       return gpg_error_from_syserror ();
1293     }
1294   strcpy (h->value, value);
1295   h->next = hd->headers;
1296   hd->headers = h;
1297
1298   return 0;
1299 }
1300
1301
1302 /* Return the header NAME from the last response.  The returned value
1303    is valid as along as HD has not been closed and no othe request has
1304    been send. If the header was not found, NULL is returned.  Name
1305    must be canonicalized, that is the first letter of each dash
1306    delimited part must be uppercase and all other letters lowercase.
1307    Note that the context must have been opened with the
1308    HTTP_FLAG_NEED_HEADER. */
1309 const char *
1310 http_get_header (http_t hd, const char *name)
1311 {
1312   header_t h;
1313
1314   for (h=hd->headers; h; h = h->next)
1315     if ( !strcmp (h->name, name) )
1316       return h->value;
1317   return NULL;
1318 }
1319
1320
1321
1322 /*
1323  * Parse the response from a server.
1324  * Returns: Errorcode and sets some files in the handle
1325  */
1326 static gpg_error_t
1327 parse_response (http_t hd)
1328 {
1329   char *line, *p, *p2;
1330   size_t maxlen, len;
1331
1332   /* Delete old header lines.  */
1333   while (hd->headers)
1334     {
1335       header_t tmp = hd->headers->next;
1336       xfree (hd->headers->value);
1337       xfree (hd->headers);
1338       hd->headers = tmp;
1339     }
1340
1341   /* Wait for the status line. */
1342   do
1343     {
1344       maxlen = MAX_LINELEN;
1345       len = my_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
1346       line = hd->buffer;
1347       if (!line)
1348         return gpg_error_from_syserror (); /* Out of core. */
1349       if (!maxlen)
1350         return gpg_error (GPG_ERR_TRUNCATED); /* Line has been truncated. */
1351       if (!len)
1352         return gpg_error (GPG_ERR_EOF);
1353       if ( (hd->flags & HTTP_FLAG_LOG_RESP) )
1354         log_info ("RESP: `%.*s'\n",
1355                   (int)strlen(line)-(*line&&line[1]?2:0),line);
1356     }
1357   while (!*line);
1358
1359   if ((p = strchr (line, '/')))
1360     *p++ = 0;
1361   if (!p || strcmp (line, "HTTP"))
1362     return 0; /* Assume http 0.9. */
1363
1364   if ((p2 = strpbrk (p, " \t")))
1365     {
1366       *p2++ = 0;
1367       p2 += strspn (p2, " \t");
1368     }
1369   if (!p2)
1370     return 0; /* Also assume http 0.9. */
1371   p = p2;
1372   /* TODO: Add HTTP version number check. */
1373   if ((p2 = strpbrk (p, " \t")))
1374     *p2++ = 0;
1375   if (!isdigit ((unsigned int)p[0]) || !isdigit ((unsigned int)p[1])
1376       || !isdigit ((unsigned int)p[2]) || p[3])
1377     {
1378       /* Malformed HTTP status code - assume http 0.9. */
1379       hd->is_http_0_9 = 1;
1380       hd->status_code = 200;
1381       return 0;
1382     }
1383   hd->status_code = atoi (p);
1384
1385   /* Skip all the header lines and wait for the empty line. */
1386   do
1387     {
1388       maxlen = MAX_LINELEN;
1389       len = my_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
1390       line = hd->buffer;
1391       if (!line)
1392         return gpg_error_from_syserror (); /* Out of core. */
1393       /* Note, that we can silently ignore truncated lines. */
1394       if (!len)
1395         return gpg_error (GPG_ERR_EOF);
1396       /* Trim line endings of empty lines. */
1397       if ((*line == '\r' && line[1] == '\n') || *line == '\n')
1398         *line = 0;
1399       if ( (hd->flags & HTTP_FLAG_LOG_RESP) )
1400         log_info ("RESP: `%.*s'\n",
1401                   (int)strlen(line)-(*line&&line[1]?2:0),line);
1402       if ( (hd->flags & HTTP_FLAG_NEED_HEADER) && *line )
1403         {
1404           gpg_error_t err = store_header (hd, line);
1405           if (err)
1406             return err;
1407         }
1408     }
1409   while (len && *line);
1410
1411   return 0;
1412 }
1413
1414 #if 0
1415 static int
1416 start_server ()
1417 {
1418   struct sockaddr_in mya;
1419   struct sockaddr_in peer;
1420   int fd, client;
1421   fd_set rfds;
1422   int addrlen;
1423   int i;
1424
1425   if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
1426     {
1427       log_error ("socket() failed: %s\n", strerror (errno));
1428       return -1;
1429     }
1430   i = 1;
1431   if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (byte *) & i, sizeof (i)))
1432     log_info ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno));
1433
1434   mya.sin_family = AF_INET;
1435   memset (&mya.sin_addr, 0, sizeof (mya.sin_addr));
1436   mya.sin_port = htons (11371);
1437
1438   if (bind (fd, (struct sockaddr *) &mya, sizeof (mya)))
1439     {
1440       log_error ("bind to port 11371 failed: %s\n", strerror (errno));
1441       sock_close (fd);
1442       return -1;
1443     }
1444
1445   if (listen (fd, 5))
1446     {
1447       log_error ("listen failed: %s\n", strerror (errno));
1448       sock_close (fd);
1449       return -1;
1450     }
1451
1452   for (;;)
1453     {
1454       FD_ZERO (&rfds);
1455       FD_SET (fd, &rfds);
1456
1457       if (select (fd + 1, &rfds, NULL, NULL, NULL) <= 0)
1458         continue;               /* ignore any errors */
1459
1460       if (!FD_ISSET (fd, &rfds))
1461         continue;
1462
1463       addrlen = sizeof peer;
1464       client = accept (fd, (struct sockaddr *) &peer, &addrlen);
1465       if (client == -1)
1466         continue;               /* oops */
1467
1468       log_info ("connect from %s\n", inet_ntoa (peer.sin_addr));
1469
1470       fflush (stdout);
1471       fflush (stderr);
1472       if (!fork ())
1473         {
1474           int c;
1475           FILE *fp;
1476
1477           fp = fdopen (client, "r");
1478           while ((c = getc (fp)) != EOF)
1479             putchar (c);
1480           fclose (fp);
1481           exit (0);
1482         }
1483       sock_close (client);
1484     }
1485
1486
1487   return 0;
1488 }
1489 #endif
1490
1491 /* Actually connect to a server.  Returns the file descripto or -1 on
1492    error.  ERRNO is set on error. */
1493 static int
1494 connect_server (const char *server, unsigned short port,
1495                 unsigned int flags, const char *srvtag)
1496 {
1497   int sock = -1;
1498   int srvcount = 0;
1499   int hostfound = 0;
1500   int srv, connected;
1501   int last_errno = 0;
1502   struct srventry *serverlist = NULL;
1503
1504 #ifdef HAVE_W32_SYSTEM
1505   unsigned long inaddr;
1506
1507   init_sockets();
1508   /* Win32 gethostbyname doesn't handle IP addresses internally, so we
1509      try inet_addr first on that platform only. */
1510   inaddr = inet_addr(server);
1511   if ( inaddr != INADDR_NONE )
1512     {
1513       struct sockaddr_in addr;
1514       
1515       memset(&addr,0,sizeof(addr));
1516       
1517       sock = socket(AF_INET,SOCK_STREAM,0);
1518       if ( sock==INVALID_SOCKET )
1519         {
1520           log_error("error creating socket: ec=%d\n",(int)WSAGetLastError());
1521           return -1;
1522         }
1523
1524       addr.sin_family = AF_INET; 
1525       addr.sin_port = htons(port);
1526       memcpy (&addr.sin_addr,&inaddr,sizeof(inaddr));      
1527
1528       if (!connect (sock,(struct sockaddr *)&addr,sizeof(addr)) )
1529         return sock;
1530       sock_close(sock);
1531       return -1;
1532     }
1533 #endif /*HAVE_W32_SYSTEM*/
1534
1535 #ifdef USE_DNS_SRV
1536   /* Do the SRV thing */
1537   if ((flags & HTTP_FLAG_TRY_SRV) && srvtag)
1538     {
1539       /* We're using SRV, so append the tags. */
1540       if (1+strlen (srvtag) + 6 + strlen (server) + 1 <= MAXDNAME)
1541         {
1542           char srvname[MAXDNAME];
1543
1544           stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srvtag),
1545                            "._tcp."), server);
1546           srvcount = getsrv (srvname, &serverlist);
1547         }
1548     }
1549 #endif /*USE_DNS_SRV*/
1550
1551   if (!serverlist)
1552     {
1553       /* Either we're not using SRV, or the SRV lookup failed.  Make
1554          up a fake SRV record. */
1555       serverlist = xtrycalloc (1, sizeof *serverlist);
1556       if (!serverlist)
1557         return -1; /* Out of core.  */
1558       serverlist->port = port;
1559       strncpy (serverlist->target, server, MAXDNAME);
1560       serverlist->target[MAXDNAME-1] = '\0';
1561       srvcount = 1;
1562     }
1563
1564 #ifdef HAVE_GETADDRINFO
1565   connected = 0;
1566   for (srv=0; srv < srvcount && !connected; srv++)
1567     {
1568       struct addrinfo hints, *res, *ai;
1569       char portstr[35];
1570
1571       sprintf (portstr, "%hu", port);
1572       memset (&hints, 0, sizeof (hints));
1573       hints.ai_socktype = SOCK_STREAM;
1574       if (getaddrinfo (serverlist[srv].target, portstr, &hints, &res))
1575         continue; /* Not found - try next one. */
1576       hostfound = 1;
1577
1578       for (ai = res; ai && !connected; ai = ai->ai_next)
1579         {
1580           if (sock != -1)
1581             sock_close (sock);
1582           sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
1583           if (sock == -1)
1584             {
1585               int save_errno = errno;
1586               log_error ("error creating socket: %s\n", strerror (errno));
1587               freeaddrinfo (res);
1588               xfree (serverlist);
1589               errno = save_errno;
1590               return -1;
1591             }
1592           
1593           if (connect (sock, ai->ai_addr, ai->ai_addrlen))
1594             last_errno = errno;
1595           else
1596             connected = 1;
1597         }
1598       freeaddrinfo (res);
1599     }
1600 #else /* !HAVE_GETADDRINFO */
1601   connected = 0;
1602   for (srv=0; srv < srvcount && !connected; srv++)
1603     {
1604       int i;
1605       struct hostent *host = NULL;
1606       struct sockaddr_in addr;
1607
1608       /* Note: This code is not thread-safe.  */
1609
1610       memset (&addr, 0, sizeof (addr));
1611       host = gethostbyname (serverlist[srv].target);
1612       if (!host)
1613         continue;
1614       hostfound = 1;
1615
1616       if (sock != -1)
1617         sock_close (sock);
1618       sock = socket (host->h_addrtype, SOCK_STREAM, 0);
1619       if (sock == -1)
1620         {
1621           log_error (_("error creating socket: %s\n"), strerror (errno));
1622           xfree (serverlist);
1623           return -1;
1624         }
1625       
1626       addr.sin_family = host->h_addrtype;
1627       if (addr.sin_family != AF_INET)
1628         {
1629           log_error ("unknown address family for `%s'\n",
1630                      serverlist[srv].target);
1631           xfree (serverlist);
1632           return -1;
1633         }
1634       addr.sin_port = htons (serverlist[srv].port);
1635       if (host->h_length != 4)
1636         {
1637           log_error ("illegal address length for `%s'\n",
1638                      serverlist[srv].target);
1639           xfree (serverlist);
1640           return -1;
1641         }
1642
1643       /* Try all A records until one responds. */
1644       for (i = 0; host->h_addr_list[i] && !connected; i++)
1645         {
1646           memcpy (&addr.sin_addr, host->h_addr_list[i], host->h_length);
1647           if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)))
1648             last_errno = errno;
1649           else
1650             {
1651               connected = 1;
1652               break;
1653             }
1654         }
1655     }
1656 #endif /* !HAVE_GETADDRINFO */
1657
1658   xfree (serverlist);
1659
1660   if (!connected)
1661     {
1662 #ifdef HAVE_W32_SYSTEM
1663       log_error ("can't connect to `%s': %s%sec=%d\n",
1664                    server,
1665                    hostfound? "":_("host not found"),
1666                    hostfound? "":" - ", (int)WSAGetLastError());
1667 #else
1668       log_error ("can't connect to `%s': %s\n",
1669                  server,
1670                  hostfound? strerror (last_errno):"host not found");
1671 #endif
1672       if (sock != -1)
1673         sock_close (sock);
1674       errno = last_errno;
1675       return -1;
1676     }
1677   return sock;
1678 }
1679
1680
1681 static gpg_error_t
1682 write_server (int sock, const char *data, size_t length)
1683 {
1684   int nleft;
1685
1686   nleft = length;
1687   while (nleft > 0)
1688     {
1689 #ifdef HAVE_W32_SYSTEM
1690       int nwritten;
1691       
1692       nwritten = send (sock, data, nleft, 0);
1693       if ( nwritten == SOCKET_ERROR ) 
1694         {
1695           log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
1696           return G10ERR_NETWORK;
1697         }
1698 #else /*!HAVE_W32_SYSTEM*/
1699       int nwritten = write (sock, data, nleft);
1700       if (nwritten == -1)
1701         {
1702           if (errno == EINTR)
1703             continue;
1704           if (errno == EAGAIN)
1705             {
1706               struct timeval tv;
1707
1708               tv.tv_sec = 0;
1709               tv.tv_usec = 50000;
1710               select (0, NULL, NULL, NULL, &tv);
1711               continue;
1712             }
1713           log_info ("network write failed: %s\n", strerror (errno));
1714           return gpg_error_from_syserror ();
1715         }
1716 #endif /*!HAVE_W32_SYSTEM*/
1717       nleft -= nwritten;
1718       data += nwritten;
1719     }
1720
1721   return 0;
1722 }
1723
1724
1725 \f
1726 #ifdef HTTP_USE_ESTREAM
1727 /* Read handler for estream.  */
1728 static ssize_t
1729 cookie_read (void *cookie, void *buffer, size_t size)
1730 {
1731   cookie_t c = cookie;
1732   int nread;
1733
1734 #ifdef HTTP_USE_GNUTLS
1735   if (c->tls_session)
1736     {
1737     again:
1738       nread = gnutls_record_recv (c->tls_session, buffer, size);
1739       if (nread < 0)
1740         {
1741           if (nread == GNUTLS_E_INTERRUPTED)
1742             goto again;
1743           if (nread == GNUTLS_E_AGAIN)
1744             {
1745               struct timeval tv;
1746               
1747               tv.tv_sec = 0;
1748               tv.tv_usec = 50000;
1749               select (0, NULL, NULL, NULL, &tv);
1750               goto again;
1751             }
1752           if (nread == GNUTLS_E_REHANDSHAKE)
1753             goto again; /* A client is allowed to just ignore this request. */
1754           log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
1755           errno = EIO;
1756           return -1;
1757         }
1758     }
1759   else
1760 #endif /*HTTP_USE_GNUTLS*/
1761     {
1762       do
1763         {
1764           nread = read (c->fd, buffer, size);
1765         }
1766       while (nread == -1 && errno == EINTR);
1767     }
1768
1769   return nread;
1770 }
1771
1772 /* Write handler for estream.  */
1773 static ssize_t
1774 cookie_write (void *cookie, const void *buffer, size_t size)
1775 {
1776   cookie_t c = cookie;
1777   int nwritten = 0;
1778
1779 #ifdef HTTP_USE_GNUTLS
1780   if (c->tls_session)
1781     {
1782       int nleft = size;
1783       while (nleft > 0)
1784         {
1785           nwritten = gnutls_record_send (c->tls_session, buffer, nleft); 
1786           if (nwritten <= 0)
1787             {
1788               if (nwritten == GNUTLS_E_INTERRUPTED)
1789                 continue;
1790               if (nwritten == GNUTLS_E_AGAIN)
1791                 {
1792                   struct timeval tv;
1793                   
1794                   tv.tv_sec = 0;
1795                   tv.tv_usec = 50000;
1796                   select (0, NULL, NULL, NULL, &tv);
1797                   continue;
1798                 }
1799               log_info ("TLS network write failed: %s\n",
1800                         gnutls_strerror (nwritten));
1801               errno = EIO;
1802               return -1;
1803             }
1804           nleft -= nwritten;
1805           buffer += nwritten;
1806         }
1807     }
1808   else
1809 #endif /*HTTP_USE_GNUTLS*/
1810     {
1811       if ( write_server (c->fd, buffer, size) )
1812         {
1813           errno = EIO;
1814           nwritten = -1;
1815         }
1816       else
1817         nwritten = size;
1818     }
1819
1820   return nwritten;
1821 }
1822
1823 /* Close handler for estream.  */
1824 static int
1825 cookie_close (void *cookie)
1826 {
1827   cookie_t c = cookie;
1828
1829   if (!c)
1830     return 0;
1831
1832  #ifdef HTTP_USE_GNUTLS
1833   if (c->tls_session && !c->keep_socket)
1834     {
1835       gnutls_bye (c->tls_session, GNUTLS_SHUT_RDWR);
1836     }
1837 #endif /*HTTP_USE_GNUTLS*/
1838   if (c->fd != -1 && !c->keep_socket)
1839     close (c->fd);
1840
1841   xfree (c);
1842   return 0;
1843 }
1844 #endif /*HTTP_USE_ESTREAM*/
1845
1846
1847
1848 \f
1849 /**** Test code ****/
1850 #ifdef TEST
1851
1852 static gpg_error_t
1853 verify_callback (http_t hd, void *tls_context, int reserved)
1854 {
1855   log_info ("verification of certificates skipped\n");
1856   return 0;
1857 }
1858
1859
1860
1861 /* static void */
1862 /* my_gnutls_log (int level, const char *text) */
1863 /* { */
1864 /*   fprintf (stderr, "gnutls:L%d: %s", level, text); */
1865 /* } */
1866
1867 int
1868 main (int argc, char **argv)
1869 {
1870   int rc;
1871   parsed_uri_t uri;
1872   uri_tuple_t r;
1873   http_t hd;
1874   int c;
1875   gnutls_session_t tls_session = NULL;
1876 #ifdef HTTP_USE_GNUTLS
1877   gnutls_certificate_credentials certcred;
1878   const int certprio[] = { GNUTLS_CRT_X509, 0 };
1879 #endif /*HTTP_USE_GNUTLS*/
1880   header_t hdr;
1881
1882 #ifdef HTTP_USE_ESTREAM
1883   es_init ();
1884 #endif
1885   log_set_prefix ("http-test", 1 | 4);
1886   if (argc == 1)
1887     {
1888       /*start_server (); */
1889       return 0;
1890     }
1891
1892   if (argc != 2)
1893     {
1894       fprintf (stderr, "usage: http-test uri\n");
1895       return 1;
1896     }
1897   argc--;
1898   argv++;
1899
1900 #ifdef HTTP_USE_GNUTLS
1901   rc = gnutls_global_init ();
1902   if (rc)
1903     log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc));
1904   rc = gnutls_certificate_allocate_credentials (&certcred);
1905   if (rc)
1906     log_error ("gnutls_certificate_allocate_credentials failed: %s\n",
1907                gnutls_strerror (rc));
1908 /*   rc = gnutls_certificate_set_x509_trust_file */
1909 /*     (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */
1910 /*   if (rc) */
1911 /*     log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */
1912 /*                gnutls_strerror (rc)); */
1913   rc = gnutls_init (&tls_session, GNUTLS_CLIENT);
1914   if (rc)
1915     log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc));
1916   rc = gnutls_set_default_priority (tls_session);
1917   if (rc)
1918     log_error ("gnutls_set_default_priority failed: %s\n",
1919                gnutls_strerror (rc));
1920   rc = gnutls_certificate_type_set_priority (tls_session, certprio);
1921   if (rc)
1922     log_error ("gnutls_certificate_type_set_priority failed: %s\n",
1923                gnutls_strerror (rc));
1924   rc = gnutls_credentials_set (tls_session, GNUTLS_CRD_CERTIFICATE, certcred);
1925   if (rc)
1926     log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc));
1927 /*   gnutls_global_set_log_function (my_gnutls_log); */
1928 /*   gnutls_global_set_log_level (4); */
1929
1930   http_register_tls_callback (verify_callback);
1931 #endif /*HTTP_USE_GNUTLS*/
1932
1933   rc = http_parse_uri (&uri, *argv);
1934   if (rc)
1935     {
1936       log_error ("`%s': %s\n", *argv, gpg_strerror (rc));
1937       http_release_parsed_uri (uri);
1938       return 1;
1939     }
1940
1941   printf ("Scheme: %s\n", uri->scheme);
1942   printf ("Host  : %s\n", uri->host);
1943   printf ("Port  : %u\n", uri->port);
1944   printf ("Path  : %s\n", uri->path);
1945   for (r = uri->params; r; r = r->next)
1946     {
1947       printf ("Params: %s", r->name);
1948       if (!r->no_value)
1949         {
1950           printf ("=%s", r->value);
1951           if (strlen (r->value) != r->valuelen)
1952             printf (" [real length=%d]", (int) r->valuelen);
1953         }
1954       putchar ('\n');
1955     }
1956   for (r = uri->query; r; r = r->next)
1957     {
1958       printf ("Query : %s", r->name);
1959       if (!r->no_value)
1960         {
1961           printf ("=%s", r->value);
1962           if (strlen (r->value) != r->valuelen)
1963             printf (" [real length=%d]", (int) r->valuelen);
1964         }
1965       putchar ('\n');
1966     }
1967   http_release_parsed_uri (uri);
1968   uri = NULL;
1969
1970   rc = http_open_document (&hd, *argv, NULL, 
1971                            HTTP_FLAG_NO_SHUTDOWN | HTTP_FLAG_NEED_HEADER,
1972                            NULL, tls_session);
1973   if (rc)
1974     {
1975       log_error ("can't get `%s': %s\n", *argv, gpg_strerror (rc));
1976       return 1;
1977     }
1978   log_info ("open_http_document succeeded; status=%u\n",
1979             http_get_status_code (hd));
1980   for (hdr = hd->headers; hdr; hdr = hdr->next)
1981     printf ("HDR: %s: %s\n", hdr->name, hdr->value);
1982   switch (http_get_status_code (hd))
1983     {
1984     case 200:
1985       while ((c = P_ES(getc) (http_get_read_ptr (hd))) != EOF)
1986         putchar (c);
1987       break;
1988     case 301:
1989     case 302:
1990       printf ("Redirected to `%s'\n", http_get_header (hd, "Location"));
1991       break;
1992     }
1993   http_close (hd, 0);
1994
1995 #ifdef HTTP_USE_GNUTLS
1996   gnutls_deinit (tls_session);
1997   gnutls_certificate_free_credentials (certcred);
1998   gnutls_global_deinit ();
1999 #endif /*HTTP_USE_GNUTLS*/
2000
2001   return 0;
2002 }
2003 #endif /*TEST*/
2004
2005
2006 /*
2007 Local Variables:
2008 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"
2009 End:
2010 */