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