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