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