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