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