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