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