/* HTTP support.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
+ 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation,
Inc.
This file is part of GNU Wget.
*/
static void
-request_set_header (struct request *req, char *name, char *value,
+request_set_header (struct request *req, const char *name, const char *value,
enum rp release_policy)
{
struct request_header *hdr;
/* A NULL value is a no-op; if freeing the name is requested,
free it now to avoid leaks. */
if (release_policy == rel_name || release_policy == rel_both)
- xfree (name);
+ xfree ((void *)name);
return;
}
{
/* Replace existing header. */
release_header (hdr);
- hdr->name = name;
- hdr->value = value;
+ hdr->name = (void *)name;
+ hdr->value = (void *)value;
hdr->release_policy = release_policy;
return;
}
req->headers = xrealloc (req->headers, req->hcapacity * sizeof (*hdr));
}
hdr = &req->headers[req->hcount++];
- hdr->name = name;
- hdr->value = value;
+ hdr->name = (void *)name;
+ hdr->value = (void *)value;
hdr->release_policy = release_policy;
}
the header was actually removed, false otherwise. */
static bool
-request_remove_header (struct request *req, char *name)
+request_remove_header (struct request *req, const char *name)
{
int i;
for (i = 0; i < req->hcount; i++)
break;
remaining_chunk_size = strtol (line, &endl, 16);
+ xfree (line);
+
if (remaining_chunk_size == 0)
{
- fd_read_line (fd);
+ line = fd_read_line (fd);
+ xfree_null (line);
break;
}
}
{
remaining_chunk_size -= ret;
if (remaining_chunk_size == 0)
- if (fd_read_line (fd) == NULL)
- return false;
+ {
+ char *line = fd_read_line (fd);
+ if (line == NULL)
+ return false;
+ else
+ xfree (line);
+ }
}
/* Safe even if %.*s bogusly expects terminating \0 because
char warc_timestamp_str [21];
char warc_request_uuid [48];
ip_address *warc_ip = NULL;
- long int warc_payload_offset = -1;
+ off_t warc_payload_offset = -1;
/* Whether this connection will be kept alive after the HTTP request
is done. */
#endif
&host_lookup_failed))
{
+ int family = socket_family (pconn.socket, ENDPOINT_PEER);
sock = pconn.socket;
using_ssl = pconn.ssl;
- logprintf (LOG_VERBOSE, _("Reusing existing connection to %s:%d.\n"),
- quotearg_style (escape_quoting_style, pconn.host),
- pconn.port);
+#if ENABLE_IPV6
+ if (family == AF_INET6)
+ logprintf (LOG_VERBOSE, _("Reusing existing connection to [%s]:%d.\n"),
+ quotearg_style (escape_quoting_style, pconn.host),
+ pconn.port);
+ else
+#endif
+ logprintf (LOG_VERBOSE, _("Reusing existing connection to %s:%d.\n"),
+ quotearg_style (escape_quoting_style, pconn.host),
+ pconn.port);
DEBUGP (("Reusing fd %d.\n", sock));
if (pconn.authorized)
/* If the connection is already authorized, the "Basic"
if (write_error < 0)
{
CLOSE_INVALIDATE (sock);
+ request_free (req);
return WRITEFAILED;
}
logprintf (LOG_VERBOSE, _("Failed reading proxy response: %s\n"),
fd_errstr (sock));
CLOSE_INVALIDATE (sock);
+ request_free (req);
return HERR;
}
message = NULL;
quotearg_style (escape_quoting_style,
_("Malformed status line")));
xfree (head);
+ request_free (req);
return HERR;
}
hs->message = xstrdup (message);
logprintf (LOG_NOTQUIET, _("Proxy tunneling failed: %s"),
message ? quotearg_style (escape_quoting_style, message) : "?");
xfree_null (message);
+ request_free (req);
return CONSSLERR;
}
xfree_null (message);
if (conn->scheme == SCHEME_HTTPS)
{
- if (!ssl_connect_wget (sock))
+ if (!ssl_connect_wget (sock, u->host))
{
fd_close (sock);
+ request_free (req);
return CONSSLERR;
}
else if (!ssl_check_certificate (sock, u->host))
{
fd_close (sock);
+ request_free (req);
return VERIFCERTERR;
}
using_ssl = true;
if (write_error >= 0 && warc_tmp != NULL)
{
/* Remember end of headers / start of payload. */
- warc_payload_offset = ftell (warc_tmp);
+ warc_payload_offset = ftello (warc_tmp);
/* Write a copy of the data to the WARC record. */
int warc_tmp_written = fwrite (opt.post_data, 1, post_data_size, warc_tmp);
{
if (warc_tmp != NULL)
/* Remember end of headers / start of payload. */
- warc_payload_offset = ftell (warc_tmp);
+ warc_payload_offset = ftello (warc_tmp);
write_error = post_file (sock, opt.post_file_name, post_data_size, warc_tmp);
}
quotearg_style (escape_quoting_style,
_("Malformed status line")));
CLOSE_INVALIDATE (sock);
+ resp_free (resp);
request_free (req);
xfree (head);
return HERR;
if (H_10X (statcode))
{
DEBUGP (("Ignoring response\n"));
+ resp_free (resp);
xfree (head);
goto read_header;
}
retrieve the file. But if the output_document was given, then this
test was already done and the file didn't exist. Hence the !opt.output_document */
get_file_flags (hs->local_file, dt);
+ request_free (req);
+ resp_free (resp);
xfree (head);
xfree_null (message);
return RETRUNNEEDED;
case WARC_ERR:
/* A fatal WARC error. */
logputs (LOG_VERBOSE, "\n");
- logprintf (LOG_NOTQUIET, _("Cannot write to WARC file..\n"));
+ logprintf (LOG_NOTQUIET, _("Cannot write to WARC file.\n"));
ret = err;
goto exit;
case WARC_TMP_FOPENERR: case WARC_TMP_FWRITEERR:
const char *passwd, const char *method,
const char *path)
{
- static char *realm, *opaque, *nonce;
+ static char *realm, *opaque, *nonce, *qop;
static struct {
const char *name;
char **variable;
} options[] = {
{ "realm", &realm },
{ "opaque", &opaque },
- { "nonce", &nonce }
+ { "nonce", &nonce },
+ { "qop", &qop }
};
+ char cnonce[16] = "";
char *res;
+ size_t res_size;
param_token name, value;
- realm = opaque = nonce = NULL;
+
+ realm = opaque = nonce = qop = NULL;
au += 6; /* skip over `Digest' */
while (extract_param (&au, &name, &value, ','))
break;
}
}
+
+ if (qop != NULL && strcmp(qop,"auth"))
+ {
+ logprintf (LOG_NOTQUIET, _("Unsupported quality of protection '%s'.\n"), qop);
+ user = NULL; /* force freeing mem and return */
+ }
+
if (!realm || !nonce || !user || !passwd || !path || !method)
{
xfree_null (realm);
xfree_null (opaque);
xfree_null (nonce);
+ xfree_null (qop);
return NULL;
}
md5_finish_ctx (&ctx, hash);
dump_hash (a2buf, hash);
- /* RESPONSE_DIGEST = H(A1BUF ":" nonce ":" A2BUF) */
- md5_init_ctx (&ctx);
- md5_process_bytes ((unsigned char *)a1buf, MD5_DIGEST_SIZE * 2, &ctx);
- md5_process_bytes ((unsigned char *)":", 1, &ctx);
- md5_process_bytes ((unsigned char *)nonce, strlen (nonce), &ctx);
- md5_process_bytes ((unsigned char *)":", 1, &ctx);
- md5_process_bytes ((unsigned char *)a2buf, MD5_DIGEST_SIZE * 2, &ctx);
- md5_finish_ctx (&ctx, hash);
+ if (!strcmp(qop,"auth"))
+ {
+ /* RFC 2617 Digest Access Authentication */
+ /* generate random hex string */
+ snprintf(cnonce, sizeof(cnonce), "%08x", random_number(INT_MAX));
+
+ /* RESPONSE_DIGEST = H(A1BUF ":" nonce ":" noncecount ":" clientnonce ":" qop ": " A2BUF) */
+ md5_init_ctx (&ctx);
+ md5_process_bytes ((unsigned char *)a1buf, MD5_DIGEST_SIZE * 2, &ctx);
+ md5_process_bytes ((unsigned char *)":", 1, &ctx);
+ md5_process_bytes ((unsigned char *)nonce, strlen (nonce), &ctx);
+ md5_process_bytes ((unsigned char *)":", 1, &ctx);
+ md5_process_bytes ((unsigned char *)"00000001", 8, &ctx); /* TODO: keep track of server nonce values */
+ md5_process_bytes ((unsigned char *)":", 1, &ctx);
+ md5_process_bytes ((unsigned char *)cnonce, strlen(cnonce), &ctx);
+ md5_process_bytes ((unsigned char *)":", 1, &ctx);
+ md5_process_bytes ((unsigned char *)qop, strlen(qop), &ctx);
+ md5_process_bytes ((unsigned char *)":", 1, &ctx);
+ md5_process_bytes ((unsigned char *)a2buf, MD5_DIGEST_SIZE * 2, &ctx);
+ md5_finish_ctx (&ctx, hash);
+ }
+ else
+ {
+ /* RFC 2069 Digest Access Authentication */
+ /* RESPONSE_DIGEST = H(A1BUF ":" nonce ":" A2BUF) */
+ md5_init_ctx (&ctx);
+ md5_process_bytes ((unsigned char *)a1buf, MD5_DIGEST_SIZE * 2, &ctx);
+ md5_process_bytes ((unsigned char *)":", 1, &ctx);
+ md5_process_bytes ((unsigned char *)nonce, strlen (nonce), &ctx);
+ md5_process_bytes ((unsigned char *)":", 1, &ctx);
+ md5_process_bytes ((unsigned char *)a2buf, MD5_DIGEST_SIZE * 2, &ctx);
+ md5_finish_ctx (&ctx, hash);
+ }
+
dump_hash (response_digest, hash);
- res = xmalloc (strlen (user)
- + strlen (user)
- + strlen (realm)
- + strlen (nonce)
- + strlen (path)
- + 2 * MD5_DIGEST_SIZE /*strlen (response_digest)*/
- + (opaque ? strlen (opaque) : 0)
- + 128);
- sprintf (res, "Digest \
-username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"",
- user, realm, nonce, path, response_digest);
+ res_size = strlen (user)
+ + strlen (user)
+ + strlen (realm)
+ + strlen (nonce)
+ + strlen (path)
+ + 2 * MD5_DIGEST_SIZE /*strlen (response_digest)*/
+ + (opaque ? strlen (opaque) : 0)
+ + (qop ? 128: 0)
+ + 128;
+
+ res = xmalloc (res_size);
+
+ if (!strcmp(qop,"auth"))
+ {
+ snprintf (res, res_size, "Digest "\
+ "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\""\
+ ", qop=auth, nc=00000001, cnonce=\"%s\"",
+ user, realm, nonce, path, response_digest, cnonce);
+
+ }
+ else
+ {
+ snprintf (res, res_size, "Digest "\
+ "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"",
+ user, realm, nonce, path, response_digest);
+ }
+
if (opaque)
{
char *p = res + strlen (res);