Better debug output.
[gnupg.git] / common / http.c
blob96e2a9e0b4f577f7e17095129a1ad3b3cf277737
1 /* http.c - HTTP protocol handler
2 * Copyright (C) 1999, 2001, 2002, 2003, 2004,
3 * 2006 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
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.
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.
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/>.
21 /* Simple HTTP client implementation. We try to keep the code as
22 self-contained as possible. There are some contraints however:
24 - stpcpy is required
25 - fixme: list other requirements.
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.
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>
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*/
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*/
70 #ifdef TEST
71 #undef USE_DNS_SRV
72 #endif
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
87 unsigned short priority;
88 unsigned short weight;
89 unsigned short port;
90 int run_count;
91 char target[MAXDNAME];
93 #endif/*!USE_DNS_SRV*/
96 #ifdef HAVE_W32_SYSTEM
97 #define sock_close(a) closesocket(a)
98 #else
99 #define sock_close(a) close(a)
100 #endif
102 #ifndef EAGAIN
103 #define EAGAIN EWOULDBLOCK
104 #endif
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 "!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~"
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
126 static gpg_error_t do_parse_uri (parsed_uri_t uri, int only_local_part);
127 static int remove_escapes (char *string);
128 static int insert_escapes (char *buffer, const char *string,
129 const char *special);
130 static uri_tuple_t parse_tuple (char *string);
131 static gpg_error_t send_request (http_t hd,
132 const char *auth, const char *proxy);
133 static char *build_rel_path (parsed_uri_t uri);
134 static gpg_error_t parse_response (http_t hd);
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);
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);
145 static es_cookie_io_functions_t cookie_functions =
147 cookie_read,
148 cookie_write,
149 NULL,
150 cookie_close
153 struct cookie_s
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. */
159 typedef struct cookie_s *cookie_t;
161 #endif /*HTTP_USE_ESTREAM*/
163 #ifdef HTTP_USE_GNUTLS
164 static gpg_error_t (*tls_callback) (http_t, gnutls_session_t, int);
165 #endif /*HTTP_USE_GNUTLS*/
168 /* An object to save header lines. */
169 struct header_s
171 struct header_s *next;
172 char *value; /* The value of the header (malloced). */
173 char name[1]; /* The name of the header (canonicalized). */
175 typedef struct header_s *header_t;
178 /* Our handle context. */
179 struct http_context_s
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. */
205 #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
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
216 static void
217 deinit_sockets (void)
219 WSACleanup();
222 static void
223 init_sockets (void)
225 static int initialized;
226 static WSADATA wsdata;
228 if (initialized)
229 return;
231 if ( WSAStartup( MAKEWORD (REQ_WINSOCK_MINOR, REQ_WINSOCK_MAJOR), &wsdata ) )
233 log_error ("error initializing socket library: ec=%d\n",
234 (int)WSAGetLastError () );
235 return;
237 if ( LOBYTE(wsdata.wVersion) != REQ_WINSOCK_MAJOR
238 || HIBYTE(wsdata.wVersion) != REQ_WINSOCK_MINOR )
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;
246 atexit ( deinit_sockets );
247 initialized = 1;
249 #endif /*HAVE_W32_SYSTEM && !HTTP_NO_WSASTARTUP*/
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.
259 static char *
260 make_header_line (const char *prefix, const char *suffix,
261 const void *data, size_t len )
263 static unsigned char bintoasc[] =
264 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
265 "abcdefghijklmnopqrstuvwxyz"
266 "0123456789+/";
267 const unsigned int *s = data;
268 char *buffer, *p;
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 )
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];
281 if ( len == 2 )
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++ = '=';
288 else if ( len == 1 )
290 *p++ = bintoasc[(s[0] >> 2) & 077];
291 *p++ = bintoasc[(s[0] <<4)&060];
292 *p++ = '=';
293 *p++ = '=';
295 strcpy (p, suffix);
296 return buffer;
302 void
303 http_register_tls_callback ( gpg_error_t (*cb) (http_t, void *, int) )
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
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)
322 gpg_error_t err;
323 http_t hd;
325 *r_hd = NULL;
327 if (!(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST))
328 return gpg_error (GPG_ERR_INV_ARG);
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;
339 err = http_parse_uri (&hd->uri, url);
340 if (!err)
341 err = send_request (hd, auth, proxy);
343 if (err)
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);
354 else
355 *r_hd = hd;
356 return err;
360 void
361 http_start_data (http_t hd)
363 if (!hd->in_data)
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;
374 else
375 P_ES(fflush) (hd->fp_write);
379 gpg_error_t
380 http_wait_response (http_t hd)
382 gpg_error_t err;
384 /* Make sure that we are in the data. */
385 http_start_data (hd);
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)
394 /* The write cookie is only set in the TLS case. */
395 cookie_t cookie = hd->write_cookie;
396 cookie->keep_socket = 1;
398 else
399 #endif /*HTTP_USE_ESTREAM*/
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 ();
414 P_ES(fclose) (hd->fp_write);
415 hd->fp_write = NULL;
416 #ifdef HTTP_USE_ESTREAM
417 hd->write_cookie = NULL;
418 #endif
420 if (!(hd->flags & HTTP_FLAG_NO_SHUTDOWN))
421 shutdown (hd->sock, 1);
422 hd->in_data = 0;
424 #ifdef HTTP_USE_ESTREAM
426 cookie_t cookie;
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;
435 hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
436 if (!hd->fp_read)
438 xfree (cookie);
439 return gpg_error_from_syserror ();
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*/
448 err = parse_response (hd);
449 return err;
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)
462 gpg_error_t err;
464 err = http_open (r_hd, HTTP_REQ_GET, document, auth, flags,
465 proxy, tls_context);
466 if (err)
467 return err;
469 err = http_wait_response (*r_hd);
470 if (err)
471 http_close (*r_hd, 0);
473 return err;
477 void
478 http_close (http_t hd, int keep_read_stream)
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)
491 header_t tmp = hd->headers->next;
492 xfree (hd->headers->value);
493 xfree (hd->headers);
494 hd->headers = tmp;
496 xfree (hd->buffer);
497 xfree (hd);
501 #ifdef HTTP_USE_ESTREAM
502 estream_t
503 http_get_read_ptr (http_t hd)
505 return hd?hd->fp_read:NULL;
507 estream_t
508 http_get_write_ptr (http_t hd)
510 return hd?hd->fp_write:NULL;
512 #else /*!HTTP_USE_ESTREAM*/
513 FILE *
514 http_get_read_ptr (http_t hd)
516 return hd?hd->fp_read:NULL;
518 FILE *
519 http_get_write_ptr (http_t hd)
521 return hd?hd->fp_write:NULL;
523 #endif /*!HTTP_USE_ESTREAM*/
524 unsigned int
525 http_get_status_code (http_t hd)
527 return hd?hd->status_code:0;
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).
537 gpg_error_t
538 http_parse_uri (parsed_uri_t * ret_uri, const char *uri)
540 *ret_uri = xcalloc (1, sizeof **ret_uri + strlen (uri));
541 strcpy ((*ret_uri)->buffer, uri);
542 return do_parse_uri (*ret_uri, 0);
545 void
546 http_release_parsed_uri (parsed_uri_t uri)
548 if (uri)
550 uri_tuple_t r, r2;
552 for (r = uri->query; r; r = r2)
554 r2 = r->next;
555 xfree (r);
557 xfree (uri);
562 static gpg_error_t
563 do_parse_uri (parsed_uri_t uri, int only_local_part)
565 uri_tuple_t *tail;
566 char *p, *p2, *p3, *pp;
567 int n;
569 p = uri->buffer;
570 n = strlen (uri->buffer);
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;
578 /* A quick validity check. */
579 if (strspn (p, VALID_URI_CHARS) != n)
580 return gpg_error (GPG_ERR_BAD_URI); /* Invalid characters found. */
582 if (!only_local_part)
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"))
596 uri->port = 443;
597 uri->use_tls = 1;
599 #endif
600 else
601 return gpg_error (GPG_ERR_INV_URI); /* Unsupported scheme */
603 p = p2;
605 /* Find the hostname */
606 if (*p != '/')
607 return gpg_error (GPG_ERR_INV_URI); /* Does not start with a slash. */
609 p++;
610 if (*p == '/') /* There seems to be a hostname. */
612 p++;
613 if ((p2 = strchr (p, '/')))
614 *p2++ = 0;
616 /* Check for username/password encoding */
617 if ((p3 = strchr (p, '@')))
619 uri->auth = p;
620 *p3++ = '\0';
621 p = p3;
624 for (pp=p; *pp; pp++)
625 *pp = tolower (*(unsigned char*)pp);
626 uri->host = p;
627 if ((p3 = strchr (p, ':')))
629 *p3++ = 0;
630 uri->port = atoi (p3);
633 uri->host = p;
634 if ((n = remove_escapes (uri->host)) < 0)
635 return gpg_error (GPG_ERR_BAD_URI);
636 if (n != strlen (p))
637 return gpg_error (GPG_ERR_BAD_URI); /* Hostname incudes a Nul. */
638 p = p2 ? p2 : NULL;
640 } /* End global URI part. */
642 /* Parse the pathname part */
643 if (!p || !*p)
644 return 0; /* We don't have a path. Okay. */
646 /* TODO: Here we have to check params. */
648 /* Do we have a query part? */
649 if ((p2 = strchr (p, '?')))
650 *p2++ = 0;
652 uri->path = p;
653 if ((n = remove_escapes (p)) < 0)
654 return gpg_error (GPG_ERR_BAD_URI);
655 if (n != strlen (p))
656 return gpg_error (GPG_ERR_BAD_URI); /* Path includes a Nul. */
657 p = p2 ? p2 : NULL;
659 if (!p || !*p)
660 return 0; /* We don't have a query string. Okay. */
662 /* Now parse the query string. */
663 tail = &uri->query;
664 for (;;)
666 uri_tuple_t elem;
668 if ((p2 = strchr (p, '&')))
669 *p2++ = 0;
670 if (!(elem = parse_tuple (p)))
671 return gpg_error (GPG_ERR_BAD_URI);
672 *tail = elem;
673 tail = &elem->next;
675 if (!p2)
676 break; /* Ready. */
677 p = p2;
680 return 0;
685 * Remove all %xx escapes; this is done in-place. Returns: New length
686 * of the string.
688 static int
689 remove_escapes (char *string)
691 int n = 0;
692 unsigned char *p, *s;
694 for (p = s = (unsigned char*)string; *s; s++)
696 if (*s == '%')
698 if (s[1] && s[2] && isxdigit (s[1]) && isxdigit (s[2]))
700 s++;
701 *p = *s >= '0' && *s <= '9' ? *s - '0' :
702 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
703 *p <<= 4;
704 s++;
705 *p |= *s >= '0' && *s <= '9' ? *s - '0' :
706 *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
707 p++;
708 n++;
710 else
712 *p++ = *s++;
713 if (*s)
714 *p++ = *s++;
715 if (*s)
716 *p++ = *s++;
717 if (*s)
718 *p = 0;
719 return -1; /* Bad URI. */
722 else
724 *p++ = *s;
725 n++;
728 *p = 0; /* Make sure to keep a string terminator. */
729 return n;
733 static int
734 insert_escapes (char *buffer, const char *string,
735 const char *special)
737 const unsigned char *s = (const unsigned char*)string;
738 int n = 0;
740 for (; *s; s++)
742 if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
744 if (buffer)
745 *(unsigned char*)buffer++ = *s;
746 n++;
748 else
750 if (buffer)
752 sprintf (buffer, "%%%02X", *s);
753 buffer += 3;
755 n += 3;
758 return n;
762 /* Allocate a new string from STRING using standard HTTP escaping as
763 well as escaping of characters given in SPECIALS. A common pattern
764 for SPECIALS is "%;?&=". However it depends on the needs, for
765 example "+" and "/: often needs to be escaped too. Returns NULL on
766 failure and sets ERRNO. */
767 char *
768 http_escape_string (const char *string, const char *specials)
770 int n;
771 char *buf;
773 n = insert_escapes (NULL, string, specials);
774 buf = xtrymalloc (n+1);
775 if (buf)
777 insert_escapes (buf, string, specials);
778 buf[n] = 0;
780 return buf;
785 static uri_tuple_t
786 parse_tuple (char *string)
788 char *p = string;
789 char *p2;
790 int n;
791 uri_tuple_t tuple;
793 if ((p2 = strchr (p, '=')))
794 *p2++ = 0;
795 if ((n = remove_escapes (p)) < 0)
796 return NULL; /* Bad URI. */
797 if (n != strlen (p))
798 return NULL; /* Name with a Nul in it. */
799 tuple = xtrycalloc (1, sizeof *tuple);
800 if (!tuple)
801 return NULL; /* Out of core. */
802 tuple->name = p;
803 if (!p2) /* We have only the name, so we assume an empty value string. */
805 tuple->value = p + strlen (p);
806 tuple->valuelen = 0;
807 tuple->no_value = 1; /* Explicitly mark that we have seen no '='. */
809 else /* Name and value. */
811 if ((n = remove_escapes (p2)) < 0)
813 xfree (tuple);
814 return NULL; /* Bad URI. */
816 tuple->value = p2;
817 tuple->valuelen = n;
819 return tuple;
824 * Send a HTTP request to the server
825 * Returns 0 if the request was successful
827 static gpg_error_t
828 send_request (http_t hd, const char *auth, const char *proxy)
830 gnutls_session_t tls_session;
831 gpg_error_t err;
832 const char *server;
833 char *request, *p;
834 unsigned short port;
835 const char *http_proxy = NULL;
836 char *proxy_authstr = NULL;
837 char *authstr = NULL;
838 int save_errno;
840 tls_session = hd->tls_context;
841 if (hd->uri->use_tls && !tls_session)
843 log_error ("TLS requested but no GNUTLS context provided\n");
844 return gpg_error (GPG_ERR_INTERNAL);
847 server = *hd->uri->host ? hd->uri->host : "localhost";
848 port = hd->uri->port ? hd->uri->port : 80;
850 if ( (proxy && *proxy)
851 || ( (hd->flags & HTTP_FLAG_TRY_PROXY)
852 && (http_proxy = getenv (HTTP_PROXY_ENV))
853 && *http_proxy ))
855 parsed_uri_t uri;
857 if (proxy)
858 http_proxy = proxy;
860 err = http_parse_uri (&uri, http_proxy);
861 if (err)
863 log_error ("invalid HTTP proxy (%s): %s\n",
864 http_proxy, gpg_strerror (err));
865 http_release_parsed_uri (uri);
866 return gpg_error (GPG_ERR_CONFIGURATION);
870 if (uri->auth)
872 remove_escapes (uri->auth);
873 proxy_authstr = make_header_line ("Proxy-Authorization: Basic ",
874 "\r\n",
875 uri->auth, strlen(uri->auth));
876 if (!proxy_authstr)
878 err = gpg_error_from_syserror ();
879 http_release_parsed_uri (uri);
880 return err;
884 hd->sock = connect_server (*uri->host ? uri->host : "localhost",
885 uri->port ? uri->port : 80,
886 hd->flags, hd->uri->scheme);
887 save_errno = errno;
888 http_release_parsed_uri (uri);
890 else
892 hd->sock = connect_server (server, port, hd->flags, hd->uri->scheme);
893 save_errno = errno;
896 if (hd->sock == -1)
898 xfree (proxy_authstr);
899 return (save_errno
900 ? gpg_error_from_errno (save_errno)
901 : gpg_error (GPG_ERR_NOT_FOUND));
904 #ifdef HTTP_USE_GNUTLS
905 if (hd->uri->use_tls)
907 int rc;
909 gnutls_transport_set_ptr (tls_session, (gnutls_transport_ptr_t)hd->sock);
912 rc = gnutls_handshake (tls_session);
914 while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
915 if (rc < 0)
917 log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
918 xfree (proxy_authstr);
919 return gpg_error (GPG_ERR_NETWORK);
922 if (tls_callback)
924 err = tls_callback (hd, tls_session, 0);
925 if (err)
927 log_info ("TLS connection authentication failed: %s\n",
928 gpg_strerror (err));
929 xfree (proxy_authstr);
930 return err;
934 #endif /*HTTP_USE_GNUTLS*/
936 if (auth || hd->uri->auth)
938 char *myauth;
940 if (auth)
942 myauth = xtrystrdup (auth);
943 if (!myauth)
945 xfree (proxy_authstr);
946 return gpg_error_from_syserror ();
948 remove_escapes (myauth);
950 else
952 remove_escapes (hd->uri->auth);
953 myauth = hd->uri->auth;
956 authstr = make_header_line ("Authorization: Basic %s", "\r\n",
957 myauth, strlen (myauth));
958 if (auth)
959 xfree (myauth);
961 if (!authstr)
963 xfree (proxy_authstr);
964 return gpg_error_from_syserror ();
968 p = build_rel_path (hd->uri);
969 if (!p)
970 return gpg_error_from_syserror ();
972 request = xtrymalloc (2 * strlen (server)
973 + strlen (p)
974 + (authstr?strlen(authstr):0)
975 + (proxy_authstr?strlen(proxy_authstr):0)
976 + 100);
977 if (!request)
979 err = gpg_error_from_syserror ();
980 xfree (p);
981 xfree (authstr);
982 xfree (proxy_authstr);
983 return err;
986 if (http_proxy && *http_proxy)
988 sprintf (request, "%s http://%s:%hu%s%s HTTP/1.0\r\n%s%s",
989 hd->req_type == HTTP_REQ_GET ? "GET" :
990 hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
991 hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
992 server, port, *p == '/' ? "" : "/", p,
993 authstr ? authstr : "",
994 proxy_authstr ? proxy_authstr : "");
996 else
998 char portstr[35];
1000 if (port == 80)
1001 *portstr = 0;
1002 else
1003 sprintf (portstr, ":%u", port);
1005 sprintf (request, "%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
1006 hd->req_type == HTTP_REQ_GET ? "GET" :
1007 hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
1008 hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
1009 *p == '/' ? "" : "/", p, server, portstr,
1010 authstr? authstr:"");
1012 xfree (p);
1015 #ifdef HTTP_USE_ESTREAM
1016 /* First setup estream so that we can write even the first line
1017 using estream. This is also required for the sake of gnutls. */
1019 cookie_t cookie;
1021 cookie = xtrycalloc (1, sizeof *cookie);
1022 if (!cookie)
1024 err = gpg_error_from_syserror ();
1025 goto leave;
1027 cookie->fd = hd->sock;
1028 if (hd->uri->use_tls)
1030 cookie->tls_session = tls_session;
1031 hd->write_cookie = cookie;
1034 hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1035 if (!hd->fp_write)
1037 xfree (cookie);
1038 err = gpg_error_from_syserror ();
1040 else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
1041 err = gpg_error_from_syserror ();
1042 else
1043 err = 0;
1046 leave:
1048 #else /*!HTTP_USE_ESTREAM*/
1049 /* We send out the start of the request through our own send
1050 function and only then assign a stdio stream. This allows for
1051 better error reporting that through standard stdio means. */
1052 err = write_server (hd->sock, request, strlen (request));
1053 if (!err)
1055 hd->fp_write = fdopen (hd->sock, "w");
1056 if (!hd->fp_write)
1057 err = gpg_error_from_syserror ();
1059 #endif /*!HTTP_USE_ESTREAM*/
1061 xfree (request);
1062 xfree (authstr);
1063 xfree (proxy_authstr);
1065 return err;
1070 * Build the relative path from the parsed URI. Minimal
1071 * implementation. May return NULL in case of memory failure; errno
1072 * is then set accordingly.
1074 static char *
1075 build_rel_path (parsed_uri_t uri)
1077 uri_tuple_t r;
1078 char *rel_path, *p;
1079 int n;
1081 /* Count the needed space. */
1082 n = insert_escapes (NULL, uri->path, "%;?&");
1083 /* TODO: build params. */
1084 for (r = uri->query; r; r = r->next)
1086 n++; /* '?'/'&' */
1087 n += insert_escapes (NULL, r->name, "%;?&=");
1088 if (!r->no_value)
1090 n++; /* '=' */
1091 n += insert_escapes (NULL, r->value, "%;?&=");
1094 n++;
1096 /* Now allocate and copy. */
1097 p = rel_path = xtrymalloc (n);
1098 if (!p)
1099 return NULL;
1100 n = insert_escapes (p, uri->path, "%;?&");
1101 p += n;
1102 /* TODO: add params. */
1103 for (r = uri->query; r; r = r->next)
1105 *p++ = r == uri->query ? '?' : '&';
1106 n = insert_escapes (p, r->name, "%;?&=");
1107 p += n;
1108 if (!r->no_value)
1110 *p++ = '=';
1111 /* TODO: Use valuelen. */
1112 n = insert_escapes (p, r->value, "%;?&=");
1113 p += n;
1116 *p = 0;
1117 return rel_path;
1123 Same as fgets() but if the buffer is too short a larger one will be
1124 allocated up to some limit *MAX_LENGTH. A line is considered a
1125 byte stream ending in a LF. Returns the length of the line. EOF is
1126 indicated by a line of length zero. The last LF may be missing due
1127 to an EOF. If MAX_LENGTH is zero on return, the line has been
1128 truncated. If the returned buffer is NULL, not enough memory was
1129 enable to increase it, the return value will also be 0 and some
1130 bytes might have been lost which should be no problem becuase
1131 out-of-memory is pretty fatal for most applications.
1133 If a line has been truncated, the file pointer is internally moved
1134 forward to the end of the line.
1136 Note: The returned buffer is allocated with enough extra space to
1137 append a CR,LF,Nul
1139 static size_t
1140 my_read_line (
1141 #ifdef HTTP_USE_ESTREAM
1142 estream_t fp,
1143 #else
1144 FILE *fp,
1145 #endif
1146 char **addr_of_buffer,
1147 size_t *length_of_buffer, size_t *max_length)
1149 int c;
1150 char *buffer = *addr_of_buffer;
1151 size_t length = *length_of_buffer;
1152 size_t nbytes = 0;
1153 size_t maxlen = *max_length;
1154 char *p;
1156 if (!buffer) /* Must allocate a new buffer. */
1158 length = 256;
1159 buffer = xtrymalloc (length);
1160 *addr_of_buffer = buffer;
1161 if (!buffer)
1163 *length_of_buffer = *max_length = 0;
1164 return 0;
1166 *length_of_buffer = length;
1169 length -= 3; /* Reserve 3 bytes (cr,lf,eol). */
1170 p = buffer;
1171 while ((c = P_ES(getc) (fp)) != EOF)
1173 if (nbytes == length) /* Increase the buffer. */
1175 if (length > maxlen) /* Limit reached. */
1177 /* Skip the rest of the line. */
1178 while (c != '\n' && (c = P_ES(getc) (fp)) != EOF)
1180 *p++ = '\n'; /* Always append a LF (we reserved some space). */
1181 nbytes++;
1182 *max_length = 0; /* Indicate truncation */
1183 break; /*(the while loop)*/
1185 length += 3; /* Adjust for the reserved bytes. */
1186 length += length < 1024 ? 256 : 1024;
1187 *addr_of_buffer = xtryrealloc (buffer, length);
1188 if (!*addr_of_buffer)
1190 int save_errno = errno;
1191 xfree (buffer);
1192 *length_of_buffer = *max_length = 0;
1193 errno = save_errno;
1194 return 0;
1196 buffer = *addr_of_buffer;
1197 *length_of_buffer = length;
1198 length -= 3; /* And re-adjust for the reservation. */
1199 p = buffer + nbytes;
1201 *p++ = c;
1202 nbytes++;
1203 if (c == '\n')
1204 break;
1206 *p = 0; /* Make sure the line is a string. */
1208 return nbytes;
1212 /* Transform a header name into a standard capitalized format; e.g.
1213 "Content-Type". Conversion stops at the colon. As usual we don't
1214 use the localized versions of ctype.h. */
1215 static void
1216 capitalize_header_name (char *name)
1218 int first = 1;
1220 for (; *name && *name != ':'; name++)
1222 if (*name == '-')
1223 first = 1;
1224 else if (first)
1226 if (*name >= 'a' && *name <= 'z')
1227 *name = *name - 'a' + 'A';
1228 first = 0;
1230 else if (*name >= 'A' && *name <= 'Z')
1231 *name = *name - 'A' + 'a';
1236 /* Store an HTTP header line in LINE away. Line continuation is
1237 supported as well as merging of headers with the same name. This
1238 function may modify LINE. */
1239 static gpg_error_t
1240 store_header (http_t hd, char *line)
1242 size_t n;
1243 char *p, *value;
1244 header_t h;
1246 n = strlen (line);
1247 if (n && line[n-1] == '\n')
1249 line[--n] = 0;
1250 if (n && line[n-1] == '\r')
1251 line[--n] = 0;
1253 if (!n) /* we are never called to hit this. */
1254 return gpg_error (GPG_ERR_BUG);
1255 if (*line == ' ' || *line == '\t')
1257 /* Continuation. This won't happen too often as it is not
1258 recommended. We use a straightforward implementaion. */
1259 if (!hd->headers)
1260 return gpg_error (GPG_ERR_PROTOCOL_VIOLATION);
1261 n += strlen (hd->headers->value);
1262 p = xtrymalloc (n+1);
1263 if (!p)
1264 return gpg_error_from_syserror ();
1265 strcpy (stpcpy (p, hd->headers->value), line);
1266 xfree (hd->headers->value);
1267 hd->headers->value = p;
1268 return 0;
1271 capitalize_header_name (line);
1272 p = strchr (line, ':');
1273 if (!p)
1274 return gpg_error (GPG_ERR_PROTOCOL_VIOLATION);
1275 *p++ = 0;
1276 while (*p == ' ' || *p == '\t')
1277 p++;
1278 value = p;
1280 for (h=hd->headers; h; h = h->next)
1281 if ( !strcmp (h->name, line) )
1282 break;
1283 if (h)
1285 /* We have already seen a line with that name. Thus we assume
1286 it is a comma separated list and merge them. */
1287 p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1);
1288 if (!p)
1289 return gpg_error_from_syserror ();
1290 strcpy (stpcpy (stpcpy (p, h->value), ","), value);
1291 xfree (h->value);
1292 h->value = p;
1293 return 0;
1296 /* Append a new header. */
1297 h = xtrymalloc (sizeof *h + strlen (line));
1298 if (!h)
1299 return gpg_error_from_syserror ();
1300 strcpy (h->name, line);
1301 h->value = xtrymalloc (strlen (value)+1);
1302 if (!h->value)
1304 xfree (h);
1305 return gpg_error_from_syserror ();
1307 strcpy (h->value, value);
1308 h->next = hd->headers;
1309 hd->headers = h;
1311 return 0;
1315 /* Return the header NAME from the last response. The returned value
1316 is valid as along as HD has not been closed and no othe request has
1317 been send. If the header was not found, NULL is returned. Name
1318 must be canonicalized, that is the first letter of each dash
1319 delimited part must be uppercase and all other letters lowercase.
1320 Note that the context must have been opened with the
1321 HTTP_FLAG_NEED_HEADER. */
1322 const char *
1323 http_get_header (http_t hd, const char *name)
1325 header_t h;
1327 for (h=hd->headers; h; h = h->next)
1328 if ( !strcmp (h->name, name) )
1329 return h->value;
1330 return NULL;
1336 * Parse the response from a server.
1337 * Returns: Errorcode and sets some files in the handle
1339 static gpg_error_t
1340 parse_response (http_t hd)
1342 char *line, *p, *p2;
1343 size_t maxlen, len;
1345 /* Delete old header lines. */
1346 while (hd->headers)
1348 header_t tmp = hd->headers->next;
1349 xfree (hd->headers->value);
1350 xfree (hd->headers);
1351 hd->headers = tmp;
1354 /* Wait for the status line. */
1357 maxlen = MAX_LINELEN;
1358 len = my_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
1359 line = hd->buffer;
1360 if (!line)
1361 return gpg_error_from_syserror (); /* Out of core. */
1362 if (!maxlen)
1363 return gpg_error (GPG_ERR_TRUNCATED); /* Line has been truncated. */
1364 if (!len)
1365 return gpg_error (GPG_ERR_EOF);
1366 if ( (hd->flags & HTTP_FLAG_LOG_RESP) )
1367 log_info ("RESP: `%.*s'\n",
1368 (int)strlen(line)-(*line&&line[1]?2:0),line);
1370 while (!*line);
1372 if ((p = strchr (line, '/')))
1373 *p++ = 0;
1374 if (!p || strcmp (line, "HTTP"))
1375 return 0; /* Assume http 0.9. */
1377 if ((p2 = strpbrk (p, " \t")))
1379 *p2++ = 0;
1380 p2 += strspn (p2, " \t");
1382 if (!p2)
1383 return 0; /* Also assume http 0.9. */
1384 p = p2;
1385 /* TODO: Add HTTP version number check. */
1386 if ((p2 = strpbrk (p, " \t")))
1387 *p2++ = 0;
1388 if (!isdigit ((unsigned int)p[0]) || !isdigit ((unsigned int)p[1])
1389 || !isdigit ((unsigned int)p[2]) || p[3])
1391 /* Malformed HTTP status code - assume http 0.9. */
1392 hd->is_http_0_9 = 1;
1393 hd->status_code = 200;
1394 return 0;
1396 hd->status_code = atoi (p);
1398 /* Skip all the header lines and wait for the empty line. */
1401 maxlen = MAX_LINELEN;
1402 len = my_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
1403 line = hd->buffer;
1404 if (!line)
1405 return gpg_error_from_syserror (); /* Out of core. */
1406 /* Note, that we can silently ignore truncated lines. */
1407 if (!len)
1408 return gpg_error (GPG_ERR_EOF);
1409 /* Trim line endings of empty lines. */
1410 if ((*line == '\r' && line[1] == '\n') || *line == '\n')
1411 *line = 0;
1412 if ( (hd->flags & HTTP_FLAG_LOG_RESP) )
1413 log_info ("RESP: `%.*s'\n",
1414 (int)strlen(line)-(*line&&line[1]?2:0),line);
1415 if ( (hd->flags & HTTP_FLAG_NEED_HEADER) && *line )
1417 gpg_error_t err = store_header (hd, line);
1418 if (err)
1419 return err;
1422 while (len && *line);
1424 return 0;
1427 #if 0
1428 static int
1429 start_server ()
1431 struct sockaddr_in mya;
1432 struct sockaddr_in peer;
1433 int fd, client;
1434 fd_set rfds;
1435 int addrlen;
1436 int i;
1438 if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
1440 log_error ("socket() failed: %s\n", strerror (errno));
1441 return -1;
1443 i = 1;
1444 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (byte *) & i, sizeof (i)))
1445 log_info ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno));
1447 mya.sin_family = AF_INET;
1448 memset (&mya.sin_addr, 0, sizeof (mya.sin_addr));
1449 mya.sin_port = htons (11371);
1451 if (bind (fd, (struct sockaddr *) &mya, sizeof (mya)))
1453 log_error ("bind to port 11371 failed: %s\n", strerror (errno));
1454 sock_close (fd);
1455 return -1;
1458 if (listen (fd, 5))
1460 log_error ("listen failed: %s\n", strerror (errno));
1461 sock_close (fd);
1462 return -1;
1465 for (;;)
1467 FD_ZERO (&rfds);
1468 FD_SET (fd, &rfds);
1470 if (select (fd + 1, &rfds, NULL, NULL, NULL) <= 0)
1471 continue; /* ignore any errors */
1473 if (!FD_ISSET (fd, &rfds))
1474 continue;
1476 addrlen = sizeof peer;
1477 client = accept (fd, (struct sockaddr *) &peer, &addrlen);
1478 if (client == -1)
1479 continue; /* oops */
1481 log_info ("connect from %s\n", inet_ntoa (peer.sin_addr));
1483 fflush (stdout);
1484 fflush (stderr);
1485 if (!fork ())
1487 int c;
1488 FILE *fp;
1490 fp = fdopen (client, "r");
1491 while ((c = getc (fp)) != EOF)
1492 putchar (c);
1493 fclose (fp);
1494 exit (0);
1496 sock_close (client);
1500 return 0;
1502 #endif
1504 /* Actually connect to a server. Returns the file descriptor or -1 on
1505 error. ERRNO is set on error. */
1506 static int
1507 connect_server (const char *server, unsigned short port,
1508 unsigned int flags, const char *srvtag)
1510 int sock = -1;
1511 int srvcount = 0;
1512 int hostfound = 0;
1513 int srv, connected;
1514 int last_errno = 0;
1515 struct srventry *serverlist = NULL;
1517 #ifdef HAVE_W32_SYSTEM
1518 unsigned long inaddr;
1520 #ifndef HTTP_NO_WSASTARTUP
1521 init_sockets ();
1522 #endif
1523 /* Win32 gethostbyname doesn't handle IP addresses internally, so we
1524 try inet_addr first on that platform only. */
1525 inaddr = inet_addr(server);
1526 if ( inaddr != INADDR_NONE )
1528 struct sockaddr_in addr;
1530 memset(&addr,0,sizeof(addr));
1532 sock = socket(AF_INET,SOCK_STREAM,0);
1533 if ( sock==INVALID_SOCKET )
1535 log_error("error creating socket: ec=%d\n",(int)WSAGetLastError());
1536 return -1;
1539 addr.sin_family = AF_INET;
1540 addr.sin_port = htons(port);
1541 memcpy (&addr.sin_addr,&inaddr,sizeof(inaddr));
1543 if (!connect (sock,(struct sockaddr *)&addr,sizeof(addr)) )
1544 return sock;
1545 sock_close(sock);
1546 return -1;
1548 #endif /*HAVE_W32_SYSTEM*/
1550 #ifdef USE_DNS_SRV
1551 /* Do the SRV thing */
1552 if ((flags & HTTP_FLAG_TRY_SRV) && srvtag)
1554 /* We're using SRV, so append the tags. */
1555 if (1+strlen (srvtag) + 6 + strlen (server) + 1 <= MAXDNAME)
1557 char srvname[MAXDNAME];
1559 stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srvtag),
1560 "._tcp."), server);
1561 srvcount = getsrv (srvname, &serverlist);
1564 #endif /*USE_DNS_SRV*/
1566 if (!serverlist)
1568 /* Either we're not using SRV, or the SRV lookup failed. Make
1569 up a fake SRV record. */
1570 serverlist = xtrycalloc (1, sizeof *serverlist);
1571 if (!serverlist)
1572 return -1; /* Out of core. */
1573 serverlist->port = port;
1574 strncpy (serverlist->target, server, MAXDNAME);
1575 serverlist->target[MAXDNAME-1] = '\0';
1576 srvcount = 1;
1579 #ifdef HAVE_GETADDRINFO
1580 connected = 0;
1581 for (srv=0; srv < srvcount && !connected; srv++)
1583 struct addrinfo hints, *res, *ai;
1584 char portstr[35];
1586 sprintf (portstr, "%hu", port);
1587 memset (&hints, 0, sizeof (hints));
1588 hints.ai_socktype = SOCK_STREAM;
1589 if (getaddrinfo (serverlist[srv].target, portstr, &hints, &res))
1590 continue; /* Not found - try next one. */
1591 hostfound = 1;
1593 for (ai = res; ai && !connected; ai = ai->ai_next)
1595 if (sock != -1)
1596 sock_close (sock);
1597 sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
1598 if (sock == -1)
1600 int save_errno = errno;
1601 log_error ("error creating socket: %s\n", strerror (errno));
1602 freeaddrinfo (res);
1603 xfree (serverlist);
1604 errno = save_errno;
1605 return -1;
1608 if (connect (sock, ai->ai_addr, ai->ai_addrlen))
1609 last_errno = errno;
1610 else
1611 connected = 1;
1613 freeaddrinfo (res);
1615 #else /* !HAVE_GETADDRINFO */
1616 connected = 0;
1617 for (srv=0; srv < srvcount && !connected; srv++)
1619 int i;
1620 struct hostent *host = NULL;
1621 struct sockaddr_in addr;
1623 /* Note: This code is not thread-safe. */
1625 memset (&addr, 0, sizeof (addr));
1626 host = gethostbyname (serverlist[srv].target);
1627 if (!host)
1628 continue;
1629 hostfound = 1;
1631 if (sock != -1)
1632 sock_close (sock);
1633 sock = socket (host->h_addrtype, SOCK_STREAM, 0);
1634 if (sock == -1)
1636 log_error (_("error creating socket: %s\n"), strerror (errno));
1637 xfree (serverlist);
1638 return -1;
1641 addr.sin_family = host->h_addrtype;
1642 if (addr.sin_family != AF_INET)
1644 log_error ("unknown address family for `%s'\n",
1645 serverlist[srv].target);
1646 xfree (serverlist);
1647 return -1;
1649 addr.sin_port = htons (serverlist[srv].port);
1650 if (host->h_length != 4)
1652 log_error ("illegal address length for `%s'\n",
1653 serverlist[srv].target);
1654 xfree (serverlist);
1655 return -1;
1658 /* Try all A records until one responds. */
1659 for (i = 0; host->h_addr_list[i] && !connected; i++)
1661 memcpy (&addr.sin_addr, host->h_addr_list[i], host->h_length);
1662 if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)))
1663 last_errno = errno;
1664 else
1666 connected = 1;
1667 break;
1671 #endif /* !HAVE_GETADDRINFO */
1673 xfree (serverlist);
1675 if (!connected)
1677 #ifdef HAVE_W32_SYSTEM
1678 log_error ("can't connect to `%s': %s%sec=%d\n",
1679 server,
1680 hostfound? "":_("host not found"),
1681 hostfound? "":" - ", (int)WSAGetLastError());
1682 #else
1683 log_error ("can't connect to `%s': %s\n",
1684 server,
1685 hostfound? strerror (last_errno):"host not found");
1686 #endif
1687 if (sock != -1)
1688 sock_close (sock);
1689 errno = last_errno;
1690 return -1;
1692 return sock;
1696 static gpg_error_t
1697 write_server (int sock, const char *data, size_t length)
1699 int nleft;
1701 nleft = length;
1702 while (nleft > 0)
1704 #ifdef HAVE_W32_SYSTEM
1705 int nwritten;
1707 nwritten = send (sock, data, nleft, 0);
1708 if ( nwritten == SOCKET_ERROR )
1710 log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
1711 return gpg_error (GPG_ERR_NETWORK);
1713 #else /*!HAVE_W32_SYSTEM*/
1714 int nwritten = write (sock, data, nleft);
1715 if (nwritten == -1)
1717 if (errno == EINTR)
1718 continue;
1719 if (errno == EAGAIN)
1721 struct timeval tv;
1723 tv.tv_sec = 0;
1724 tv.tv_usec = 50000;
1725 select (0, NULL, NULL, NULL, &tv);
1726 continue;
1728 log_info ("network write failed: %s\n", strerror (errno));
1729 return gpg_error_from_syserror ();
1731 #endif /*!HAVE_W32_SYSTEM*/
1732 nleft -= nwritten;
1733 data += nwritten;
1736 return 0;
1741 #ifdef HTTP_USE_ESTREAM
1742 /* Read handler for estream. */
1743 static ssize_t
1744 cookie_read (void *cookie, void *buffer, size_t size)
1746 cookie_t c = cookie;
1747 int nread;
1749 #ifdef HTTP_USE_GNUTLS
1750 if (c->tls_session)
1752 again:
1753 nread = gnutls_record_recv (c->tls_session, buffer, size);
1754 if (nread < 0)
1756 if (nread == GNUTLS_E_INTERRUPTED)
1757 goto again;
1758 if (nread == GNUTLS_E_AGAIN)
1760 struct timeval tv;
1762 tv.tv_sec = 0;
1763 tv.tv_usec = 50000;
1764 select (0, NULL, NULL, NULL, &tv);
1765 goto again;
1767 if (nread == GNUTLS_E_REHANDSHAKE)
1768 goto again; /* A client is allowed to just ignore this request. */
1769 log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
1770 errno = EIO;
1771 return -1;
1774 else
1775 #endif /*HTTP_USE_GNUTLS*/
1779 #ifdef HAVE_W32_SYSTEM
1780 /* Under Windows we need to use recv for a socket. */
1781 nread = recv (c->fd, buffer, size, 0);
1782 #else
1783 nread = read (c->fd, buffer, size);
1784 #endif
1786 while (nread == -1 && errno == EINTR);
1789 return nread;
1792 /* Write handler for estream. */
1793 static ssize_t
1794 cookie_write (void *cookie, const void *buffer, size_t size)
1796 cookie_t c = cookie;
1797 int nwritten = 0;
1799 #ifdef HTTP_USE_GNUTLS
1800 if (c->tls_session)
1802 int nleft = size;
1803 while (nleft > 0)
1805 nwritten = gnutls_record_send (c->tls_session, buffer, nleft);
1806 if (nwritten <= 0)
1808 if (nwritten == GNUTLS_E_INTERRUPTED)
1809 continue;
1810 if (nwritten == GNUTLS_E_AGAIN)
1812 struct timeval tv;
1814 tv.tv_sec = 0;
1815 tv.tv_usec = 50000;
1816 select (0, NULL, NULL, NULL, &tv);
1817 continue;
1819 log_info ("TLS network write failed: %s\n",
1820 gnutls_strerror (nwritten));
1821 errno = EIO;
1822 return -1;
1824 nleft -= nwritten;
1825 buffer += nwritten;
1828 else
1829 #endif /*HTTP_USE_GNUTLS*/
1831 if ( write_server (c->fd, buffer, size) )
1833 errno = EIO;
1834 nwritten = -1;
1836 else
1837 nwritten = size;
1840 return nwritten;
1843 /* Close handler for estream. */
1844 static int
1845 cookie_close (void *cookie)
1847 cookie_t c = cookie;
1849 if (!c)
1850 return 0;
1852 #ifdef HTTP_USE_GNUTLS
1853 if (c->tls_session && !c->keep_socket)
1855 gnutls_bye (c->tls_session, GNUTLS_SHUT_RDWR);
1857 #endif /*HTTP_USE_GNUTLS*/
1858 if (c->fd != -1 && !c->keep_socket)
1859 sock_close (c->fd);
1861 xfree (c);
1862 return 0;
1864 #endif /*HTTP_USE_ESTREAM*/
1869 /**** Test code ****/
1870 #ifdef TEST
1872 static gpg_error_t
1873 verify_callback (http_t hd, void *tls_context, int reserved)
1875 log_info ("verification of certificates skipped\n");
1876 return 0;
1881 /* static void */
1882 /* my_gnutls_log (int level, const char *text) */
1883 /* { */
1884 /* fprintf (stderr, "gnutls:L%d: %s", level, text); */
1885 /* } */
1888 main (int argc, char **argv)
1890 int rc;
1891 parsed_uri_t uri;
1892 uri_tuple_t r;
1893 http_t hd;
1894 int c;
1895 gnutls_session_t tls_session = NULL;
1896 #ifdef HTTP_USE_GNUTLS
1897 gnutls_certificate_credentials certcred;
1898 const int certprio[] = { GNUTLS_CRT_X509, 0 };
1899 #endif /*HTTP_USE_GNUTLS*/
1900 header_t hdr;
1902 #ifdef HTTP_USE_ESTREAM
1903 es_init ();
1904 #endif
1905 log_set_prefix ("http-test", 1 | 4);
1906 if (argc == 1)
1908 /*start_server (); */
1909 return 0;
1912 if (argc != 2)
1914 fprintf (stderr, "usage: http-test uri\n");
1915 return 1;
1917 argc--;
1918 argv++;
1920 #ifdef HTTP_USE_GNUTLS
1921 rc = gnutls_global_init ();
1922 if (rc)
1923 log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc));
1924 rc = gnutls_certificate_allocate_credentials (&certcred);
1925 if (rc)
1926 log_error ("gnutls_certificate_allocate_credentials failed: %s\n",
1927 gnutls_strerror (rc));
1928 /* rc = gnutls_certificate_set_x509_trust_file */
1929 /* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */
1930 /* if (rc) */
1931 /* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */
1932 /* gnutls_strerror (rc)); */
1933 rc = gnutls_init (&tls_session, GNUTLS_CLIENT);
1934 if (rc)
1935 log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc));
1936 rc = gnutls_set_default_priority (tls_session);
1937 if (rc)
1938 log_error ("gnutls_set_default_priority failed: %s\n",
1939 gnutls_strerror (rc));
1940 rc = gnutls_certificate_type_set_priority (tls_session, certprio);
1941 if (rc)
1942 log_error ("gnutls_certificate_type_set_priority failed: %s\n",
1943 gnutls_strerror (rc));
1944 rc = gnutls_credentials_set (tls_session, GNUTLS_CRD_CERTIFICATE, certcred);
1945 if (rc)
1946 log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc));
1947 /* gnutls_global_set_log_function (my_gnutls_log); */
1948 /* gnutls_global_set_log_level (4); */
1950 http_register_tls_callback (verify_callback);
1951 #endif /*HTTP_USE_GNUTLS*/
1953 rc = http_parse_uri (&uri, *argv);
1954 if (rc)
1956 log_error ("`%s': %s\n", *argv, gpg_strerror (rc));
1957 http_release_parsed_uri (uri);
1958 return 1;
1961 printf ("Scheme: %s\n", uri->scheme);
1962 printf ("Host : %s\n", uri->host);
1963 printf ("Port : %u\n", uri->port);
1964 printf ("Path : %s\n", uri->path);
1965 for (r = uri->params; r; r = r->next)
1967 printf ("Params: %s", r->name);
1968 if (!r->no_value)
1970 printf ("=%s", r->value);
1971 if (strlen (r->value) != r->valuelen)
1972 printf (" [real length=%d]", (int) r->valuelen);
1974 putchar ('\n');
1976 for (r = uri->query; r; r = r->next)
1978 printf ("Query : %s", r->name);
1979 if (!r->no_value)
1981 printf ("=%s", r->value);
1982 if (strlen (r->value) != r->valuelen)
1983 printf (" [real length=%d]", (int) r->valuelen);
1985 putchar ('\n');
1987 http_release_parsed_uri (uri);
1988 uri = NULL;
1990 rc = http_open_document (&hd, *argv, NULL,
1991 HTTP_FLAG_NO_SHUTDOWN | HTTP_FLAG_NEED_HEADER,
1992 NULL, tls_session);
1993 if (rc)
1995 log_error ("can't get `%s': %s\n", *argv, gpg_strerror (rc));
1996 return 1;
1998 log_info ("open_http_document succeeded; status=%u\n",
1999 http_get_status_code (hd));
2000 for (hdr = hd->headers; hdr; hdr = hdr->next)
2001 printf ("HDR: %s: %s\n", hdr->name, hdr->value);
2002 switch (http_get_status_code (hd))
2004 case 200:
2005 while ((c = P_ES(getc) (http_get_read_ptr (hd))) != EOF)
2006 putchar (c);
2007 break;
2008 case 301:
2009 case 302:
2010 printf ("Redirected to `%s'\n", http_get_header (hd, "Location"));
2011 break;
2013 http_close (hd, 0);
2015 #ifdef HTTP_USE_GNUTLS
2016 gnutls_deinit (tls_session);
2017 gnutls_certificate_free_credentials (certcred);
2018 gnutls_global_deinit ();
2019 #endif /*HTTP_USE_GNUTLS*/
2021 return 0;
2023 #endif /*TEST*/
2027 Local Variables:
2028 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"
2029 End: