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:
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
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.
48
#ifdef HAVE_W32_SYSTEM
50
#else /*!HAVE_W32_SYSTEM*/
51
# include <sys/types.h>
52
# include <sys/socket.h>
53
# include <sys/time.h>
55
# include <netinet/in.h>
56
# include <arpa/inet.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
66
typedef gnutls_session gnutls_session_t;
67
typedef gnutls_transport_ptr gnutls_transport_ptr_t;
68
#endif /*HTTP_USE_GNUTLS*/
79
#else /*!USE_DNS_SRV*/
80
/* If we are not compiling with SRV record support we provide stub
87
unsigned short priority;
88
unsigned short weight;
91
char target[MAXDNAME];
93
#endif/*!USE_DNS_SRV*/
96
#ifdef HAVE_W32_SYSTEM
97
#define sock_close(a) closesocket(a)
99
#define sock_close(a) close(a)
103
#define EAGAIN EWOULDBLOCK
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" \
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
119
#ifndef HTTP_USE_GNUTLS
120
typedef void * gnutls_session_t;
122
#if defined(HTTP_USE_GNUTLS) && !defined(HTTP_USE_ESTREAM)
123
#error Use of GNUTLS also requires support for Estream
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 =
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. */
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;
184
#ifdef HTTP_USE_ESTREAM
188
#else /*!HTTP_USE_ESTREAM*/
191
#endif /*!HTTP_USE_ESTREAM*/
196
char *buffer; /* Line buffer. */
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
211
#define REQ_WINSOCK_MAJOR 2
212
#define REQ_WINSOCK_MINOR 2
217
deinit_sockets (void)
225
static int initialized;
226
static WSADATA wsdata;
231
if ( WSAStartup( MAKEWORD (REQ_WINSOCK_MINOR, REQ_WINSOCK_MAJOR), &wsdata ) )
233
log_error ("error initializing socket library: ec=%d\n",
234
(int)WSAGetLastError () );
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);
246
atexit ( deinit_sockets );
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.
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"
267
const unsigned int *s = data;
270
buffer = xtrymalloc (strlen (prefix) + (len+2)/3*4 + strlen (suffix) + 1);
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];
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)];
290
*p++ = bintoasc[(s[0] >> 2) & 077];
291
*p++ = bintoasc[(s[0] <<4)&060];
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;
312
/* Start a HTTP retrieval and return on success in R_HD a context
313
pointer for completing the the request and to wait for the
316
http_open (http_t *r_hd, http_req_t reqtype, const char *url,
317
const char *auth, unsigned int flags, const char *proxy,
325
if (!(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST))
326
return gpg_error (GPG_ERR_INV_ARG);
328
/* Create the handle. */
329
hd = xtrycalloc (1, sizeof *hd);
331
return gpg_error_from_syserror ();
333
hd->req_type = reqtype;
335
hd->tls_context = tls_context;
337
err = http_parse_uri (&hd->uri, url);
339
err = send_request (hd, auth, proxy);
343
if (!hd->fp_read && !hd->fp_write && hd->sock != -1)
344
sock_close (hd->sock);
346
P_ES(fclose) (hd->fp_read);
348
P_ES(fclose) (hd->fp_write);
349
http_release_parsed_uri (hd->uri);
359
http_start_data (http_t hd)
363
#ifdef HTTP_USE_ESTREAM
364
es_fputs ("\r\n", hd->fp_write);
365
es_fflush (hd->fp_write);
367
fflush (hd->fp_write);
368
write_server (hd->sock, "\r\n", 2);
373
P_ES(fflush) (hd->fp_write);
378
http_wait_response (http_t hd)
382
/* Make sure that we are in the data. */
383
http_start_data (hd);
385
/* We dup the socket, to cope with the fact that fclose closes the
386
underlying socket. In TLS mode we don't do that because we can't
387
close the socket gnutls is working on; instead we make sure that
388
the fclose won't close the socket in this case. */
389
#ifdef HTTP_USE_ESTREAM
390
if (hd->write_cookie)
392
/* The write cookie is only set in the TLS case. */
393
cookie_t cookie = hd->write_cookie;
394
cookie->keep_socket = 1;
397
#endif /*HTTP_USE_ESTREAM*/
399
hd->sock = dup (hd->sock);
401
return gpg_error_from_syserror ();
403
P_ES(fclose) (hd->fp_write);
405
#ifdef HTTP_USE_ESTREAM
406
hd->write_cookie = NULL;
409
if (!(hd->flags & HTTP_FLAG_NO_SHUTDOWN))
410
shutdown (hd->sock, 1);
413
#ifdef HTTP_USE_ESTREAM
417
cookie = xtrycalloc (1, sizeof *cookie);
419
return gpg_error_from_syserror ();
420
cookie->fd = hd->sock;
421
if (hd->uri->use_tls)
422
cookie->tls_session = hd->tls_context;
424
hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
428
return gpg_error_from_syserror ();
431
#else /*!HTTP_USE_ESTREAM*/
432
hd->fp_read = fdopen (hd->sock, "r");
434
return gpg_error_from_syserror ();
435
#endif /*!HTTP_USE_ESTREAM*/
437
err = parse_response (hd);
442
/* Convenience function to send a request and wait for the response.
443
Closes the handle on error. If PROXY is not NULL, this value will
444
be used as an HTTP proxy and any enabled $http_proxy gets
447
http_open_document (http_t *r_hd, const char *document,
448
const char *auth, unsigned int flags, const char *proxy,
453
err = http_open (r_hd, HTTP_REQ_GET, document, auth, flags,
458
err = http_wait_response (*r_hd);
460
http_close (*r_hd, 0);
467
http_close (http_t hd, int keep_read_stream)
471
if (!hd->fp_read && !hd->fp_write && hd->sock != -1)
472
sock_close (hd->sock);
473
if (hd->fp_read && !keep_read_stream)
474
P_ES(fclose) (hd->fp_read);
476
P_ES(fclose) (hd->fp_write);
477
http_release_parsed_uri (hd->uri);
480
header_t tmp = hd->headers->next;
481
xfree (hd->headers->value);
490
#ifdef HTTP_USE_ESTREAM
492
http_get_read_ptr (http_t hd)
494
return hd?hd->fp_read:NULL;
497
http_get_write_ptr (http_t hd)
499
return hd?hd->fp_write:NULL;
501
#else /*!HTTP_USE_ESTREAM*/
503
http_get_read_ptr (http_t hd)
505
return hd?hd->fp_read:NULL;
508
http_get_write_ptr (http_t hd)
510
return hd?hd->fp_write:NULL;
512
#endif /*!HTTP_USE_ESTREAM*/
514
http_get_status_code (http_t hd)
516
return hd?hd->status_code:0;
522
* Parse an URI and put the result into the newly allocated RET_URI.
523
* The caller must always use release_parsed_uri() to releases the
524
* resources (even on error).
527
http_parse_uri (parsed_uri_t * ret_uri, const char *uri)
529
*ret_uri = xcalloc (1, sizeof **ret_uri + strlen (uri));
530
strcpy ((*ret_uri)->buffer, uri);
531
return do_parse_uri (*ret_uri, 0);
535
http_release_parsed_uri (parsed_uri_t uri)
541
for (r = uri->query; r; r = r2)
552
do_parse_uri (parsed_uri_t uri, int only_local_part)
555
char *p, *p2, *p3, *pp;
559
n = strlen (uri->buffer);
561
/* Initialize all fields to an empty string or an empty list. */
562
uri->scheme = uri->host = uri->path = p + n;
564
uri->params = uri->query = NULL;
567
/* A quick validity check. */
568
if (strspn (p, VALID_URI_CHARS) != n)
569
return gpg_error (GPG_ERR_BAD_URI); /* Invalid characters found. */
571
if (!only_local_part)
573
/* Find the scheme. */
574
if (!(p2 = strchr (p, ':')) || p2 == p)
575
return gpg_error (GPG_ERR_BAD_URI); /* No scheme. */
577
for (pp=p; *pp; pp++)
578
*pp = tolower (*(unsigned char*)pp);
580
if (!strcmp (uri->scheme, "http"))
582
#ifdef HTTP_USE_GNUTLS
583
else if (!strcmp (uri->scheme, "https"))
590
return gpg_error (GPG_ERR_INV_URI); /* Unsupported scheme */
594
/* Find the hostname */
596
return gpg_error (GPG_ERR_INV_URI); /* Does not start with a slash. */
599
if (*p == '/') /* There seems to be a hostname. */
602
if ((p2 = strchr (p, '/')))
605
/* Check for username/password encoding */
606
if ((p3 = strchr (p, '@')))
613
for (pp=p; *pp; pp++)
614
*pp = tolower (*(unsigned char*)pp);
616
if ((p3 = strchr (p, ':')))
619
uri->port = atoi (p3);
623
if ((n = remove_escapes (uri->host)) < 0)
624
return gpg_error (GPG_ERR_BAD_URI);
626
return gpg_error (GPG_ERR_BAD_URI); /* Hostname incudes a Nul. */
629
} /* End global URI part. */
631
/* Parse the pathname part */
633
return 0; /* We don't have a path. Okay. */
635
/* TODO: Here we have to check params. */
637
/* Do we have a query part? */
638
if ((p2 = strchr (p, '?')))
642
if ((n = remove_escapes (p)) < 0)
643
return gpg_error (GPG_ERR_BAD_URI);
645
return gpg_error (GPG_ERR_BAD_URI); /* Path includes a Nul. */
649
return 0; /* We don't have a query string. Okay. */
651
/* Now parse the query string. */
657
if ((p2 = strchr (p, '&')))
659
if (!(elem = parse_tuple (p)))
660
return gpg_error (GPG_ERR_BAD_URI);
674
* Remove all %xx escapes; this is done in-place. Returns: New length
678
remove_escapes (char *string)
681
unsigned char *p, *s;
683
for (p = s = (unsigned char*)string; *s; s++)
687
if (s[1] && s[2] && isxdigit (s[1]) && isxdigit (s[2]))
690
*p = *s >= '0' && *s <= '9' ? *s - '0' :
691
*s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
694
*p |= *s >= '0' && *s <= '9' ? *s - '0' :
695
*s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
708
return -1; /* Bad URI. */
717
*p = 0; /* Make sure to keep a string terminator. */
723
insert_escapes (char *buffer, const char *string,
726
const unsigned char *s = (const unsigned char*)string;
731
if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
734
*(unsigned char*)buffer++ = *s;
741
sprintf (buffer, "%%%02X", *s);
751
/* Allocate a new string from STRING using standard HTTP escaping as
752
well as escaping of characters given in SPECIALS. A common pattern
753
for SPECIALS is "%;?&=". However it depends on the needs, for
754
example "+" and "/: often needs to be escaped too. Returns NULL on
755
failure and sets ERRNO. */
757
http_escape_string (const char *string, const char *specials)
762
n = insert_escapes (NULL, string, specials);
763
buf = xtrymalloc (n+1);
766
insert_escapes (buf, string, specials);
775
parse_tuple (char *string)
782
if ((p2 = strchr (p, '=')))
784
if ((n = remove_escapes (p)) < 0)
785
return NULL; /* Bad URI. */
787
return NULL; /* Name with a Nul in it. */
788
tuple = xtrycalloc (1, sizeof *tuple);
790
return NULL; /* Out of core. */
792
if (!p2) /* We have only the name, so we assume an empty value string. */
794
tuple->value = p + strlen (p);
796
tuple->no_value = 1; /* Explicitly mark that we have seen no '='. */
798
else /* Name and value. */
800
if ((n = remove_escapes (p2)) < 0)
803
return NULL; /* Bad URI. */
813
* Send a HTTP request to the server
814
* Returns 0 if the request was successful
817
send_request (http_t hd, const char *auth, const char *proxy)
819
gnutls_session_t tls_session;
824
const char *http_proxy = NULL;
825
char *proxy_authstr = NULL;
826
char *authstr = NULL;
829
tls_session = hd->tls_context;
830
if (hd->uri->use_tls && !tls_session)
832
log_error ("TLS requested but no GNUTLS context provided\n");
833
return gpg_error (GPG_ERR_INTERNAL);
836
server = *hd->uri->host ? hd->uri->host : "localhost";
837
port = hd->uri->port ? hd->uri->port : 80;
839
if ( (proxy && *proxy)
840
|| ( (hd->flags & HTTP_FLAG_TRY_PROXY)
841
&& (http_proxy = getenv (HTTP_PROXY_ENV))
849
err = http_parse_uri (&uri, http_proxy);
852
log_error ("invalid HTTP proxy (%s): %s\n",
853
http_proxy, gpg_strerror (err));
854
http_release_parsed_uri (uri);
855
return gpg_error (GPG_ERR_CONFIGURATION);
861
remove_escapes (uri->auth);
862
proxy_authstr = make_header_line ("Proxy-Authorization: Basic ",
864
uri->auth, strlen(uri->auth));
867
err = gpg_error_from_syserror ();
868
http_release_parsed_uri (uri);
873
hd->sock = connect_server (*uri->host ? uri->host : "localhost",
874
uri->port ? uri->port : 80,
875
hd->flags, hd->uri->scheme);
877
http_release_parsed_uri (uri);
881
hd->sock = connect_server (server, port, hd->flags, hd->uri->scheme);
887
xfree (proxy_authstr);
889
? gpg_error_from_errno (save_errno)
890
: gpg_error (GPG_ERR_NOT_FOUND));
893
#ifdef HTTP_USE_GNUTLS
894
if (hd->uri->use_tls)
898
gnutls_transport_set_ptr (tls_session, (gnutls_transport_ptr_t)hd->sock);
901
rc = gnutls_handshake (tls_session);
903
while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
906
log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
907
xfree (proxy_authstr);
908
return gpg_error (GPG_ERR_NETWORK);
913
err = tls_callback (hd, tls_session, 0);
916
log_info ("TLS connection authentication failed: %s\n",
918
xfree (proxy_authstr);
923
#endif /*HTTP_USE_GNUTLS*/
925
if (auth || hd->uri->auth)
931
myauth = xtrystrdup (auth);
934
xfree (proxy_authstr);
935
return gpg_error_from_syserror ();
937
remove_escapes (myauth);
941
remove_escapes (hd->uri->auth);
942
myauth = hd->uri->auth;
945
authstr = make_header_line ("Authorization: Basic %s", "\r\n",
946
myauth, strlen (myauth));
952
xfree (proxy_authstr);
953
return gpg_error_from_syserror ();
957
p = build_rel_path (hd->uri);
959
return gpg_error_from_syserror ();
961
request = xtrymalloc (2 * strlen (server)
963
+ (authstr?strlen(authstr):0)
964
+ (proxy_authstr?strlen(proxy_authstr):0)
968
err = gpg_error_from_syserror ();
971
xfree (proxy_authstr);
975
if (http_proxy && *http_proxy)
977
sprintf (request, "%s http://%s:%hu%s%s HTTP/1.0\r\n%s%s",
978
hd->req_type == HTTP_REQ_GET ? "GET" :
979
hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
980
hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
981
server, port, *p == '/' ? "" : "/", p,
982
authstr ? authstr : "",
983
proxy_authstr ? proxy_authstr : "");
992
sprintf (portstr, ":%u", port);
994
sprintf (request, "%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
995
hd->req_type == HTTP_REQ_GET ? "GET" :
996
hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
997
hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
998
*p == '/' ? "" : "/", p, server, portstr,
999
authstr? authstr:"");
1004
#ifdef HTTP_USE_ESTREAM
1005
/* First setup estream so that we can write even the first line
1006
using estream. This is also required for the sake of gnutls. */
1010
cookie = xtrycalloc (1, sizeof *cookie);
1013
err = gpg_error_from_syserror ();
1016
cookie->fd = hd->sock;
1017
if (hd->uri->use_tls)
1019
cookie->tls_session = tls_session;
1020
hd->write_cookie = cookie;
1023
hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1027
err = gpg_error_from_syserror ();
1029
else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
1030
err = gpg_error_from_syserror ();
1037
#else /*!HTTP_USE_ESTREAM*/
1038
/* We send out the start of the request through our own send
1039
function and only then assign a stdio stream. This allows for
1040
better error reporting that through standard stdio means. */
1041
err = write_server (hd->sock, request, strlen (request));
1044
hd->fp_write = fdopen (hd->sock, "w");
1046
err = gpg_error_from_syserror ();
1048
#endif /*!HTTP_USE_ESTREAM*/
1052
xfree (proxy_authstr);
1059
* Build the relative path from the parsed URI. Minimal
1060
* implementation. May return NULL in case of memory failure; errno
1061
* is then set accordingly.
1064
build_rel_path (parsed_uri_t uri)
1070
/* Count the needed space. */
1071
n = insert_escapes (NULL, uri->path, "%;?&");
1072
/* TODO: build params. */
1073
for (r = uri->query; r; r = r->next)
1076
n += insert_escapes (NULL, r->name, "%;?&=");
1080
n += insert_escapes (NULL, r->value, "%;?&=");
1085
/* Now allocate and copy. */
1086
p = rel_path = xtrymalloc (n);
1089
n = insert_escapes (p, uri->path, "%;?&");
1091
/* TODO: add params. */
1092
for (r = uri->query; r; r = r->next)
1094
*p++ = r == uri->query ? '?' : '&';
1095
n = insert_escapes (p, r->name, "%;?&=");
1100
/* TODO: Use valuelen. */
1101
n = insert_escapes (p, r->value, "%;?&=");
1112
Same as fgets() but if the buffer is too short a larger one will be
1113
allocated up to some limit *MAX_LENGTH. A line is considered a
1114
byte stream ending in a LF. Returns the length of the line. EOF is
1115
indicated by a line of length zero. The last LF may be missing due
1116
to an EOF. If MAX_LENGTH is zero on return, the line has been
1117
truncated. If the returned buffer is NULL, not enough memory was
1118
enable to increase it, the return value will also be 0 and some
1119
bytes might have been lost which should be no problem becuase
1120
out-of-memory is pretty fatal for most applications.
1122
If a line has been truncated, the file pointer is internally moved
1123
forward to the end of the line.
1125
Note: The returned buffer is allocated with enough extra space to
1130
#ifdef HTTP_USE_ESTREAM
1135
char **addr_of_buffer,
1136
size_t *length_of_buffer, size_t *max_length)
1139
char *buffer = *addr_of_buffer;
1140
size_t length = *length_of_buffer;
1142
size_t maxlen = *max_length;
1145
if (!buffer) /* Must allocate a new buffer. */
1148
buffer = xtrymalloc (length);
1149
*addr_of_buffer = buffer;
1152
*length_of_buffer = *max_length = 0;
1155
*length_of_buffer = length;
1158
length -= 3; /* Reserve 3 bytes (cr,lf,eol). */
1160
while ((c = P_ES(getc) (fp)) != EOF)
1162
if (nbytes == length) /* Increase the buffer. */
1164
if (length > maxlen) /* Limit reached. */
1166
/* Skip the rest of the line. */
1167
while (c != '\n' && (c = P_ES(getc) (fp)) != EOF)
1169
*p++ = '\n'; /* Always append a LF (we reserved some space). */
1171
*max_length = 0; /* Indicate truncation */
1172
break; /*(the while loop)*/
1174
length += 3; /* Adjust for the reserved bytes. */
1175
length += length < 1024 ? 256 : 1024;
1176
*addr_of_buffer = xtryrealloc (buffer, length);
1177
if (!*addr_of_buffer)
1179
int save_errno = errno;
1181
*length_of_buffer = *max_length = 0;
1185
buffer = *addr_of_buffer;
1186
*length_of_buffer = length;
1187
length -= 3; /* And re-adjust for the reservation. */
1188
p = buffer + nbytes;
1195
*p = 0; /* Make sure the line is a string. */
1201
/* Transform a header name into a standard capitalized format; e.g.
1202
"Content-Type". Conversion stops at the colon. As usual we don't
1203
use the localized versions of ctype.h. */
1205
capitalize_header_name (char *name)
1209
for (; *name && *name != ':'; name++)
1215
if (*name >= 'a' && *name <= 'z')
1216
*name = *name - 'a' + 'A';
1219
else if (*name >= 'A' && *name <= 'Z')
1220
*name = *name - 'A' + 'a';
1225
/* Store an HTTP header line in LINE away. Line continuation is
1226
supported as well as merging of headers with the same name. This
1227
function may modify LINE. */
1229
store_header (http_t hd, char *line)
1236
if (n && line[n-1] == '\n')
1239
if (n && line[n-1] == '\r')
1242
if (!n) /* we are never called to hit this. */
1243
return gpg_error (GPG_ERR_BUG);
1244
if (*line == ' ' || *line == '\t')
1246
/* Continuation. This won't happen too often as it is not
1247
recommended. We use a straightforward implementaion. */
1249
return gpg_error (GPG_ERR_PROTOCOL_VIOLATION);
1250
n += strlen (hd->headers->value);
1251
p = xtrymalloc (n+1);
1253
return gpg_error_from_syserror ();
1254
strcpy (stpcpy (p, hd->headers->value), line);
1255
xfree (hd->headers->value);
1256
hd->headers->value = p;
1260
capitalize_header_name (line);
1261
p = strchr (line, ':');
1263
return gpg_error (GPG_ERR_PROTOCOL_VIOLATION);
1265
while (*p == ' ' || *p == '\t')
1269
for (h=hd->headers; h; h = h->next)
1270
if ( !strcmp (h->name, line) )
1274
/* We have already seen a line with that name. Thus we assume
1275
it is a comma separated list and merge them. */
1276
p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1);
1278
return gpg_error_from_syserror ();
1279
strcpy (stpcpy (stpcpy (p, h->value), ","), value);
1285
/* Append a new header. */
1286
h = xtrymalloc (sizeof *h + strlen (line));
1288
return gpg_error_from_syserror ();
1289
strcpy (h->name, line);
1290
h->value = xtrymalloc (strlen (value)+1);
1294
return gpg_error_from_syserror ();
1296
strcpy (h->value, value);
1297
h->next = hd->headers;
1304
/* Return the header NAME from the last response. The returned value
1305
is valid as along as HD has not been closed and no othe request has
1306
been send. If the header was not found, NULL is returned. Name
1307
must be canonicalized, that is the first letter of each dash
1308
delimited part must be uppercase and all other letters lowercase.
1309
Note that the context must have been opened with the
1310
HTTP_FLAG_NEED_HEADER. */
1312
http_get_header (http_t hd, const char *name)
1316
for (h=hd->headers; h; h = h->next)
1317
if ( !strcmp (h->name, name) )
1325
* Parse the response from a server.
1326
* Returns: Errorcode and sets some files in the handle
1329
parse_response (http_t hd)
1331
char *line, *p, *p2;
1334
/* Delete old header lines. */
1337
header_t tmp = hd->headers->next;
1338
xfree (hd->headers->value);
1339
xfree (hd->headers);
1343
/* Wait for the status line. */
1346
maxlen = MAX_LINELEN;
1347
len = my_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
1350
return gpg_error_from_syserror (); /* Out of core. */
1352
return gpg_error (GPG_ERR_TRUNCATED); /* Line has been truncated. */
1354
return gpg_error (GPG_ERR_EOF);
1355
if ( (hd->flags & HTTP_FLAG_LOG_RESP) )
1356
log_info ("RESP: `%.*s'\n",
1357
(int)strlen(line)-(*line&&line[1]?2:0),line);
1361
if ((p = strchr (line, '/')))
1363
if (!p || strcmp (line, "HTTP"))
1364
return 0; /* Assume http 0.9. */
1366
if ((p2 = strpbrk (p, " \t")))
1369
p2 += strspn (p2, " \t");
1372
return 0; /* Also assume http 0.9. */
1374
/* TODO: Add HTTP version number check. */
1375
if ((p2 = strpbrk (p, " \t")))
1377
if (!isdigit ((unsigned int)p[0]) || !isdigit ((unsigned int)p[1])
1378
|| !isdigit ((unsigned int)p[2]) || p[3])
1380
/* Malformed HTTP status code - assume http 0.9. */
1381
hd->is_http_0_9 = 1;
1382
hd->status_code = 200;
1385
hd->status_code = atoi (p);
1387
/* Skip all the header lines and wait for the empty line. */
1390
maxlen = MAX_LINELEN;
1391
len = my_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
1394
return gpg_error_from_syserror (); /* Out of core. */
1395
/* Note, that we can silently ignore truncated lines. */
1397
return gpg_error (GPG_ERR_EOF);
1398
/* Trim line endings of empty lines. */
1399
if ((*line == '\r' && line[1] == '\n') || *line == '\n')
1401
if ( (hd->flags & HTTP_FLAG_LOG_RESP) )
1402
log_info ("RESP: `%.*s'\n",
1403
(int)strlen(line)-(*line&&line[1]?2:0),line);
1404
if ( (hd->flags & HTTP_FLAG_NEED_HEADER) && *line )
1406
gpg_error_t err = store_header (hd, line);
1411
while (len && *line);
1420
struct sockaddr_in mya;
1421
struct sockaddr_in peer;
1427
if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
1429
log_error ("socket() failed: %s\n", strerror (errno));
1433
if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (byte *) & i, sizeof (i)))
1434
log_info ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno));
1436
mya.sin_family = AF_INET;
1437
memset (&mya.sin_addr, 0, sizeof (mya.sin_addr));
1438
mya.sin_port = htons (11371);
1440
if (bind (fd, (struct sockaddr *) &mya, sizeof (mya)))
1442
log_error ("bind to port 11371 failed: %s\n", strerror (errno));
1449
log_error ("listen failed: %s\n", strerror (errno));
1459
if (select (fd + 1, &rfds, NULL, NULL, NULL) <= 0)
1460
continue; /* ignore any errors */
1462
if (!FD_ISSET (fd, &rfds))
1465
addrlen = sizeof peer;
1466
client = accept (fd, (struct sockaddr *) &peer, &addrlen);
1468
continue; /* oops */
1470
log_info ("connect from %s\n", inet_ntoa (peer.sin_addr));
1479
fp = fdopen (client, "r");
1480
while ((c = getc (fp)) != EOF)
1485
sock_close (client);
1493
/* Actually connect to a server. Returns the file descripto or -1 on
1494
error. ERRNO is set on error. */
1496
connect_server (const char *server, unsigned short port,
1497
unsigned int flags, const char *srvtag)
1504
struct srventry *serverlist = NULL;
1506
#ifdef HAVE_W32_SYSTEM
1507
unsigned long inaddr;
1509
#ifndef HTTP_NO_WSASTARTUP
1512
/* Win32 gethostbyname doesn't handle IP addresses internally, so we
1513
try inet_addr first on that platform only. */
1514
inaddr = inet_addr(server);
1515
if ( inaddr != INADDR_NONE )
1517
struct sockaddr_in addr;
1519
memset(&addr,0,sizeof(addr));
1521
sock = socket(AF_INET,SOCK_STREAM,0);
1522
if ( sock==INVALID_SOCKET )
1524
log_error("error creating socket: ec=%d\n",(int)WSAGetLastError());
1528
addr.sin_family = AF_INET;
1529
addr.sin_port = htons(port);
1530
memcpy (&addr.sin_addr,&inaddr,sizeof(inaddr));
1532
if (!connect (sock,(struct sockaddr *)&addr,sizeof(addr)) )
1537
#endif /*HAVE_W32_SYSTEM*/
1540
/* Do the SRV thing */
1541
if ((flags & HTTP_FLAG_TRY_SRV) && srvtag)
1543
/* We're using SRV, so append the tags. */
1544
if (1+strlen (srvtag) + 6 + strlen (server) + 1 <= MAXDNAME)
1546
char srvname[MAXDNAME];
1548
stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srvtag),
1550
srvcount = getsrv (srvname, &serverlist);
1553
#endif /*USE_DNS_SRV*/
1557
/* Either we're not using SRV, or the SRV lookup failed. Make
1558
up a fake SRV record. */
1559
serverlist = xtrycalloc (1, sizeof *serverlist);
1561
return -1; /* Out of core. */
1562
serverlist->port = port;
1563
strncpy (serverlist->target, server, MAXDNAME);
1564
serverlist->target[MAXDNAME-1] = '\0';
1568
#ifdef HAVE_GETADDRINFO
1570
for (srv=0; srv < srvcount && !connected; srv++)
1572
struct addrinfo hints, *res, *ai;
1575
sprintf (portstr, "%hu", port);
1576
memset (&hints, 0, sizeof (hints));
1577
hints.ai_socktype = SOCK_STREAM;
1578
if (getaddrinfo (serverlist[srv].target, portstr, &hints, &res))
1579
continue; /* Not found - try next one. */
1582
for (ai = res; ai && !connected; ai = ai->ai_next)
1586
sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
1589
int save_errno = errno;
1590
log_error ("error creating socket: %s\n", strerror (errno));
1597
if (connect (sock, ai->ai_addr, ai->ai_addrlen))
1604
#else /* !HAVE_GETADDRINFO */
1606
for (srv=0; srv < srvcount && !connected; srv++)
1609
struct hostent *host = NULL;
1610
struct sockaddr_in addr;
1612
/* Note: This code is not thread-safe. */
1614
memset (&addr, 0, sizeof (addr));
1615
host = gethostbyname (serverlist[srv].target);
1622
sock = socket (host->h_addrtype, SOCK_STREAM, 0);
1625
log_error (_("error creating socket: %s\n"), strerror (errno));
1630
addr.sin_family = host->h_addrtype;
1631
if (addr.sin_family != AF_INET)
1633
log_error ("unknown address family for `%s'\n",
1634
serverlist[srv].target);
1638
addr.sin_port = htons (serverlist[srv].port);
1639
if (host->h_length != 4)
1641
log_error ("illegal address length for `%s'\n",
1642
serverlist[srv].target);
1647
/* Try all A records until one responds. */
1648
for (i = 0; host->h_addr_list[i] && !connected; i++)
1650
memcpy (&addr.sin_addr, host->h_addr_list[i], host->h_length);
1651
if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)))
1660
#endif /* !HAVE_GETADDRINFO */
1666
#ifdef HAVE_W32_SYSTEM
1667
log_error ("can't connect to `%s': %s%sec=%d\n",
1669
hostfound? "":_("host not found"),
1670
hostfound? "":" - ", (int)WSAGetLastError());
1672
log_error ("can't connect to `%s': %s\n",
1674
hostfound? strerror (last_errno):"host not found");
1686
write_server (int sock, const char *data, size_t length)
1693
#ifdef HAVE_W32_SYSTEM
1696
nwritten = send (sock, data, nleft, 0);
1697
if ( nwritten == SOCKET_ERROR )
1699
log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
1700
return gpg_error (GPG_ERR_NETWORK);
1702
#else /*!HAVE_W32_SYSTEM*/
1703
int nwritten = write (sock, data, nleft);
1708
if (errno == EAGAIN)
1714
select (0, NULL, NULL, NULL, &tv);
1717
log_info ("network write failed: %s\n", strerror (errno));
1718
return gpg_error_from_syserror ();
1720
#endif /*!HAVE_W32_SYSTEM*/
1730
#ifdef HTTP_USE_ESTREAM
1731
/* Read handler for estream. */
1733
cookie_read (void *cookie, void *buffer, size_t size)
1735
cookie_t c = cookie;
1738
#ifdef HTTP_USE_GNUTLS
1742
nread = gnutls_record_recv (c->tls_session, buffer, size);
1745
if (nread == GNUTLS_E_INTERRUPTED)
1747
if (nread == GNUTLS_E_AGAIN)
1753
select (0, NULL, NULL, NULL, &tv);
1756
if (nread == GNUTLS_E_REHANDSHAKE)
1757
goto again; /* A client is allowed to just ignore this request. */
1758
log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
1764
#endif /*HTTP_USE_GNUTLS*/
1768
nread = read (c->fd, buffer, size);
1770
while (nread == -1 && errno == EINTR);
1776
/* Write handler for estream. */
1778
cookie_write (void *cookie, const void *buffer, size_t size)
1780
cookie_t c = cookie;
1783
#ifdef HTTP_USE_GNUTLS
1789
nwritten = gnutls_record_send (c->tls_session, buffer, nleft);
1792
if (nwritten == GNUTLS_E_INTERRUPTED)
1794
if (nwritten == GNUTLS_E_AGAIN)
1800
select (0, NULL, NULL, NULL, &tv);
1803
log_info ("TLS network write failed: %s\n",
1804
gnutls_strerror (nwritten));
1813
#endif /*HTTP_USE_GNUTLS*/
1815
if ( write_server (c->fd, buffer, size) )
1827
/* Close handler for estream. */
1829
cookie_close (void *cookie)
1831
cookie_t c = cookie;
1836
#ifdef HTTP_USE_GNUTLS
1837
if (c->tls_session && !c->keep_socket)
1839
gnutls_bye (c->tls_session, GNUTLS_SHUT_RDWR);
1841
#endif /*HTTP_USE_GNUTLS*/
1842
if (c->fd != -1 && !c->keep_socket)
1848
#endif /*HTTP_USE_ESTREAM*/
1853
/**** Test code ****/
1857
verify_callback (http_t hd, void *tls_context, int reserved)
1859
log_info ("verification of certificates skipped\n");
1866
/* my_gnutls_log (int level, const char *text) */
1868
/* fprintf (stderr, "gnutls:L%d: %s", level, text); */
1872
main (int argc, char **argv)
1879
gnutls_session_t tls_session = NULL;
1880
#ifdef HTTP_USE_GNUTLS
1881
gnutls_certificate_credentials certcred;
1882
const int certprio[] = { GNUTLS_CRT_X509, 0 };
1883
#endif /*HTTP_USE_GNUTLS*/
1886
#ifdef HTTP_USE_ESTREAM
1889
log_set_prefix ("http-test", 1 | 4);
1892
/*start_server (); */
1898
fprintf (stderr, "usage: http-test uri\n");
1904
#ifdef HTTP_USE_GNUTLS
1905
rc = gnutls_global_init ();
1907
log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc));
1908
rc = gnutls_certificate_allocate_credentials (&certcred);
1910
log_error ("gnutls_certificate_allocate_credentials failed: %s\n",
1911
gnutls_strerror (rc));
1912
/* rc = gnutls_certificate_set_x509_trust_file */
1913
/* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */
1915
/* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */
1916
/* gnutls_strerror (rc)); */
1917
rc = gnutls_init (&tls_session, GNUTLS_CLIENT);
1919
log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc));
1920
rc = gnutls_set_default_priority (tls_session);
1922
log_error ("gnutls_set_default_priority failed: %s\n",
1923
gnutls_strerror (rc));
1924
rc = gnutls_certificate_type_set_priority (tls_session, certprio);
1926
log_error ("gnutls_certificate_type_set_priority failed: %s\n",
1927
gnutls_strerror (rc));
1928
rc = gnutls_credentials_set (tls_session, GNUTLS_CRD_CERTIFICATE, certcred);
1930
log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc));
1931
/* gnutls_global_set_log_function (my_gnutls_log); */
1932
/* gnutls_global_set_log_level (4); */
1934
http_register_tls_callback (verify_callback);
1935
#endif /*HTTP_USE_GNUTLS*/
1937
rc = http_parse_uri (&uri, *argv);
1940
log_error ("`%s': %s\n", *argv, gpg_strerror (rc));
1941
http_release_parsed_uri (uri);
1945
printf ("Scheme: %s\n", uri->scheme);
1946
printf ("Host : %s\n", uri->host);
1947
printf ("Port : %u\n", uri->port);
1948
printf ("Path : %s\n", uri->path);
1949
for (r = uri->params; r; r = r->next)
1951
printf ("Params: %s", r->name);
1954
printf ("=%s", r->value);
1955
if (strlen (r->value) != r->valuelen)
1956
printf (" [real length=%d]", (int) r->valuelen);
1960
for (r = uri->query; r; r = r->next)
1962
printf ("Query : %s", r->name);
1965
printf ("=%s", r->value);
1966
if (strlen (r->value) != r->valuelen)
1967
printf (" [real length=%d]", (int) r->valuelen);
1971
http_release_parsed_uri (uri);
1974
rc = http_open_document (&hd, *argv, NULL,
1975
HTTP_FLAG_NO_SHUTDOWN | HTTP_FLAG_NEED_HEADER,
1979
log_error ("can't get `%s': %s\n", *argv, gpg_strerror (rc));
1982
log_info ("open_http_document succeeded; status=%u\n",
1983
http_get_status_code (hd));
1984
for (hdr = hd->headers; hdr; hdr = hdr->next)
1985
printf ("HDR: %s: %s\n", hdr->name, hdr->value);
1986
switch (http_get_status_code (hd))
1989
while ((c = P_ES(getc) (http_get_read_ptr (hd))) != EOF)
1994
printf ("Redirected to `%s'\n", http_get_header (hd, "Location"));
1999
#ifdef HTTP_USE_GNUTLS
2000
gnutls_deinit (tls_session);
2001
gnutls_certificate_free_credentials (certcred);
2002
gnutls_global_deinit ();
2003
#endif /*HTTP_USE_GNUTLS*/
2012
compile-command: "gcc -I.. -I../gl -DTEST -DHAVE_CONFIG_H -Wall -O2 -g -o http-test http.c -L. -lcommon -L../jnlib -ljnlib -lgcrypt -lpth -lgnutls"