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