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