svn commit: r242608 - stable/7/lib/libfetch
Dag-Erling Smørgrav
des at FreeBSD.org
Mon Nov 5 10:54:15 UTC 2012
Author: des
Date: Mon Nov 5 10:54:14 2012
New Revision: 242608
URL: http://svnweb.freebsd.org/changeset/base/242608
Log:
MFH r221820, r221821, r221822: increase WARNS
MFH r221830: mark all descriptors close-on-exec
MFH r225813: man page fixes
MFH r225814: adjust copyright statement
MFH r226537: latin1 -> utf8
MFH r230307, r230478: fix SIGINFO infinite loop and data loss
MFH r233648: man page fixes
MFH r234138: support percent-encoded user and password
MFH r234837: avoid busy-loop on slow connections
MFH r234838: don't reuse credentials when redirected to another host
MFH r236193: avoid SIGPIPE on network connections
MFH r240496: use libmd if and only if OpenSSL is not available
Modified:
stable/7/lib/libfetch/Makefile
stable/7/lib/libfetch/common.c
stable/7/lib/libfetch/common.h
stable/7/lib/libfetch/fetch.3
stable/7/lib/libfetch/fetch.c
stable/7/lib/libfetch/fetch.h
stable/7/lib/libfetch/file.c
stable/7/lib/libfetch/ftp.c
stable/7/lib/libfetch/http.c
Directory Properties:
stable/7/lib/libfetch/ (props changed)
Modified: stable/7/lib/libfetch/Makefile
==============================================================================
--- stable/7/lib/libfetch/Makefile Mon Nov 5 10:45:37 2012 (r242607)
+++ stable/7/lib/libfetch/Makefile Mon Nov 5 10:54:14 2012 (r242608)
@@ -16,8 +16,8 @@ CFLAGS+= -DINET6
.if ${MK_OPENSSL} != "no"
CFLAGS+= -DWITH_SSL
-DPADD= ${LIBSSL} ${LIBCRYPTO} ${LIBMD}
-LDADD= -lssl -lcrypto -lmd
+DPADD= ${LIBSSL} ${LIBCRYPTO}
+LDADD= -lssl -lcrypto
.else
DPADD= ${LIBMD}
LDADD= -lmd
@@ -26,7 +26,7 @@ LDADD= -lmd
CFLAGS+= -DFTP_COMBINE_CWDS
CSTD?= c99
-WARNS?= 2
+WARNS?= 4
SHLIB_MAJOR= 5
Modified: stable/7/lib/libfetch/common.c
==============================================================================
--- stable/7/lib/libfetch/common.c Mon Nov 5 10:45:37 2012 (r242607)
+++ stable/7/lib/libfetch/common.c Mon Nov 5 10:54:14 2012 (r242608)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
+ * Copyright (c) 1998-2011 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -209,10 +209,13 @@ conn_t *
fetch_reopen(int sd)
{
conn_t *conn;
+ int opt = 1;
/* allocate and fill connection structure */
if ((conn = calloc(1, sizeof(*conn))) == NULL)
return (NULL);
+ fcntl(sd, F_SETFD, FD_CLOEXEC);
+ setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof opt);
conn->sd = sd;
++conn->ref;
return (conn);
@@ -403,6 +406,33 @@ fetch_ssl_read(SSL *ssl, char *buf, size
}
#endif
+/*
+ * Cache some data that was read from a socket but cannot be immediately
+ * returned because of an interrupted system call.
+ */
+static int
+fetch_cache_data(conn_t *conn, char *src, size_t nbytes)
+{
+ char *tmp;
+
+ if (conn->cache.size < nbytes) {
+ tmp = realloc(conn->cache.buf, nbytes);
+ if (tmp == NULL) {
+ fetch_syserr();
+ return (-1);
+ }
+ conn->cache.buf = tmp;
+ conn->cache.size = nbytes;
+ }
+
+ memcpy(conn->cache.buf, src, nbytes);
+ conn->cache.len = nbytes;
+ conn->cache.pos = 0;
+
+ return (0);
+}
+
+
static ssize_t
fetch_socket_read(int sd, char *buf, size_t len)
{
@@ -427,15 +457,32 @@ fetch_read(conn_t *conn, char *buf, size
struct timeval now, timeout, delta;
fd_set readfds;
ssize_t rlen, total;
- int r;
+ char *start;
- if (fetchTimeout) {
- FD_ZERO(&readfds);
+ if (fetchTimeout > 0) {
gettimeofday(&timeout, NULL);
timeout.tv_sec += fetchTimeout;
}
total = 0;
+ start = buf;
+
+ if (conn->cache.len > 0) {
+ /*
+ * The last invocation of fetch_read was interrupted by a
+ * signal after some data had been read from the socket. Copy
+ * the cached data into the supplied buffer before trying to
+ * read from the socket again.
+ */
+ total = (conn->cache.len < len) ? conn->cache.len : len;
+ memcpy(buf, conn->cache.buf, total);
+
+ conn->cache.len -= total;
+ conn->cache.pos += total;
+ len -= total;
+ buf += total;
+ }
+
while (len > 0) {
/*
* The socket is non-blocking. Instead of the canonical
@@ -471,28 +518,32 @@ fetch_read(conn_t *conn, char *buf, size
total += rlen;
continue;
} else if (rlen == FETCH_READ_ERROR) {
+ if (errno == EINTR)
+ fetch_cache_data(conn, start, total);
return (-1);
}
// assert(rlen == FETCH_READ_WAIT);
- while (fetchTimeout && !FD_ISSET(conn->sd, &readfds)) {
+ FD_ZERO(&readfds);
+ while (!FD_ISSET(conn->sd, &readfds)) {
FD_SET(conn->sd, &readfds);
- gettimeofday(&now, NULL);
- delta.tv_sec = timeout.tv_sec - now.tv_sec;
- delta.tv_usec = timeout.tv_usec - now.tv_usec;
- if (delta.tv_usec < 0) {
- delta.tv_usec += 1000000;
- delta.tv_sec--;
- }
- if (delta.tv_sec < 0) {
- errno = ETIMEDOUT;
- fetch_syserr();
- return (-1);
+ if (fetchTimeout > 0) {
+ gettimeofday(&now, NULL);
+ if (!timercmp(&timeout, &now, >)) {
+ errno = ETIMEDOUT;
+ fetch_syserr();
+ return (-1);
+ }
+ timersub(&timeout, &now, &delta);
}
errno = 0;
- r = select(conn->sd + 1, &readfds, NULL, NULL, &delta);
- if (r == -1) {
- if (errno == EINTR && fetchRestartCalls)
- continue;
+ if (select(conn->sd + 1, &readfds, NULL, NULL,
+ fetchTimeout > 0 ? &delta : NULL) < 0) {
+ if (errno == EINTR) {
+ if (fetchRestartCalls)
+ continue;
+ /* Save anything that was read. */
+ fetch_cache_data(conn, start, total);
+ }
fetch_syserr();
return (-1);
}
@@ -676,6 +727,7 @@ fetch_close(conn_t *conn)
if (--conn->ref > 0)
return (0);
ret = close(conn->sd);
+ free(conn->cache.buf);
free(conn->buf);
free(conn);
return (ret);
Modified: stable/7/lib/libfetch/common.h
==============================================================================
--- stable/7/lib/libfetch/common.h Mon Nov 5 10:45:37 2012 (r242607)
+++ stable/7/lib/libfetch/common.h Mon Nov 5 10:54:14 2012 (r242608)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
+ * Copyright (c) 1998-2011 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -52,6 +52,13 @@ struct fetchconn {
size_t bufsize; /* buffer size */
size_t buflen; /* length of buffer contents */
int err; /* last protocol reply code */
+ struct { /* data cached after an interrupted
+ read */
+ char *buf;
+ size_t size;
+ size_t pos;
+ size_t len;
+ } cache;
#ifdef WITH_SSL
SSL *ssl; /* SSL handle */
SSL_CTX *ssl_ctx; /* SSL context */
Modified: stable/7/lib/libfetch/fetch.3
==============================================================================
--- stable/7/lib/libfetch/fetch.3 Mon Nov 5 10:45:37 2012 (r242607)
+++ stable/7/lib/libfetch/fetch.3 Mon Nov 5 10:54:14 2012 (r242608)
@@ -1,5 +1,5 @@
.\"-
-.\" Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
+.\" Copyright (c) 1998-2011 Dag-Erling Smørgrav
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 26, 2010
+.Dd September 27, 2011
.Dt FETCH 3
.Os
.Sh NAME
@@ -365,7 +365,7 @@ If the
(if-modified-since) flag is specified, and
the
.Va ims_time
-field is set in
+field is set in
.Vt "struct url" ,
then
.Fn fetchXGetHTTP
Modified: stable/7/lib/libfetch/fetch.c
==============================================================================
--- stable/7/lib/libfetch/fetch.c Mon Nov 5 10:45:37 2012 (r242607)
+++ stable/7/lib/libfetch/fetch.c Mon Nov 5 10:54:14 2012 (r242608)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
+ * Copyright (c) 1998-2004 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -289,6 +289,49 @@ fetchMakeURL(const char *scheme, const c
}
/*
+ * Return value of the given hex digit.
+ */
+static int
+fetch_hexval(char ch)
+{
+
+ if (ch >= '0' && ch <= '9')
+ return (ch - '0');
+ else if (ch >= 'a' && ch <= 'f')
+ return (ch - 'a' + 10);
+ else if (ch >= 'A' && ch <= 'F')
+ return (ch - 'A' + 10);
+ return (-1);
+}
+
+/*
+ * Decode percent-encoded URL component from src into dst, stopping at end
+ * of string, or at @ or : separators. Returns a pointer to the unhandled
+ * part of the input string (null terminator, @, or :). No terminator is
+ * written to dst (it is the caller's responsibility).
+ */
+static const char *
+fetch_pctdecode(char *dst, const char *src, size_t dlen)
+{
+ int d1, d2;
+ char c;
+ const char *s;
+
+ for (s = src; *s != '\0' && *s != '@' && *s != ':'; s++) {
+ if (s[0] == '%' && (d1 = fetch_hexval(s[1])) >= 0 &&
+ (d2 = fetch_hexval(s[2])) >= 0 && (d1 > 0 || d2 > 0)) {
+ c = d1 << 4 | d2;
+ s += 2;
+ } else {
+ c = *s;
+ }
+ if (dlen-- > 0)
+ *dst++ = c;
+ }
+ return (s);
+}
+
+/*
* Split an URL into components. URL syntax is:
* [method:/][/[user[:pwd]@]host[:port]/][document]
* This almost, but not quite, RFC1738 URL syntax.
@@ -329,15 +372,11 @@ fetchParseURL(const char *URL)
p = strpbrk(URL, "/@");
if (p && *p == '@') {
/* username */
- for (q = URL, i = 0; (*q != ':') && (*q != '@'); q++)
- if (i < URL_USERLEN)
- u->user[i++] = *q;
+ q = fetch_pctdecode(u->user, URL, URL_USERLEN);
/* password */
if (*q == ':')
- for (q++, i = 0; (*q != ':') && (*q != '@'); q++)
- if (i < URL_PWDLEN)
- u->pwd[i++] = *q;
+ q = fetch_pctdecode(u->pwd, ++q, URL_PWDLEN);
p++;
} else {
Modified: stable/7/lib/libfetch/fetch.h
==============================================================================
--- stable/7/lib/libfetch/fetch.h Mon Nov 5 10:45:37 2012 (r242607)
+++ stable/7/lib/libfetch/fetch.h Mon Nov 5 10:54:14 2012 (r242608)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
+ * Copyright (c) 1998-2004 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Modified: stable/7/lib/libfetch/file.c
==============================================================================
--- stable/7/lib/libfetch/file.c Mon Nov 5 10:45:37 2012 (r242607)
+++ stable/7/lib/libfetch/file.c Mon Nov 5 10:54:14 2012 (r242608)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
+ * Copyright (c) 1998-2011 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <dirent.h>
+#include <fcntl.h>
#include <stdio.h>
#include <string.h>
@@ -60,6 +61,7 @@ fetchXGetFile(struct url *u, struct url_
return (NULL);
}
+ fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
return (f);
}
@@ -90,6 +92,7 @@ fetchPutFile(struct url *u, const char *
return (NULL);
}
+ fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
return (f);
}
Modified: stable/7/lib/libfetch/ftp.c
==============================================================================
--- stable/7/lib/libfetch/ftp.c Mon Nov 5 10:45:37 2012 (r242607)
+++ stable/7/lib/libfetch/ftp.c Mon Nov 5 10:54:14 2012 (r242608)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
+ * Copyright (c) 1998-2011 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$");
*
* Major Changelog:
*
- * Dag-Erling Coïdan Smørgrav
+ * Dag-Erling Smørgrav
* 9 Jun 1998
*
* Incorporated into libfetch
@@ -127,7 +127,7 @@ unmappedaddr(struct sockaddr_in6 *sin6)
!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
return;
sin4 = (struct sockaddr_in *)sin6;
- addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12];
+ addr = *(u_int32_t *)(uintptr_t)&sin6->sin6_addr.s6_addr[12];
port = sin6->sin6_port;
memset(sin4, 0, sizeof(struct sockaddr_in));
sin4->sin_addr.s_addr = addr;
Modified: stable/7/lib/libfetch/http.c
==============================================================================
--- stable/7/lib/libfetch/http.c Mon Nov 5 10:45:37 2012 (r242607)
+++ stable/7/lib/libfetch/http.c Mon Nov 5 10:54:14 2012 (r242608)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2004 Dag-Erling Coïdan Smørgrav
+ * Copyright (c) 2000-2011 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -76,7 +76,15 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <time.h>
#include <unistd.h>
+
+#ifdef WITH_SSL
+#include <openssl/md5.h>
+#define MD5Init(c) MD5_Init(c)
+#define MD5Update(c, data, len) MD5_Update(c, data, len)
+#define MD5Final(md, c) MD5_Final(md, c)
+#else
#include <md5.h>
+#endif
#include <netinet/in.h>
#include <netinet/tcp.h>
@@ -199,6 +207,8 @@ http_growbuf(struct httpio *io, size_t l
static int
http_fillbuf(struct httpio *io, size_t len)
{
+ ssize_t nbytes;
+
if (io->error)
return (-1);
if (io->eof)
@@ -207,10 +217,11 @@ http_fillbuf(struct httpio *io, size_t l
if (io->chunked == 0) {
if (http_growbuf(io, len) == -1)
return (-1);
- if ((io->buflen = fetch_read(io->conn, io->buf, len)) == -1) {
- io->error = 1;
+ if ((nbytes = fetch_read(io->conn, io->buf, len)) == -1) {
+ io->error = errno;
return (-1);
}
+ io->buflen = nbytes;
io->bufpos = 0;
return (io->buflen);
}
@@ -230,10 +241,11 @@ http_fillbuf(struct httpio *io, size_t l
len = io->chunksize;
if (http_growbuf(io, len) == -1)
return (-1);
- if ((io->buflen = fetch_read(io->conn, io->buf, len)) == -1) {
- io->error = 1;
+ if ((nbytes = fetch_read(io->conn, io->buf, len)) == -1) {
+ io->error = errno;
return (-1);
}
+ io->buflen = nbytes;
io->chunksize -= io->buflen;
if (io->chunksize == 0) {
@@ -275,8 +287,11 @@ http_readfn(void *v, char *buf, int len)
io->bufpos += l;
}
- if (!pos && io->error)
+ if (!pos && io->error) {
+ if (io->error == EINTR)
+ io->error = 0;
return (-1);
+ }
return (pos);
}
@@ -457,7 +472,7 @@ http_match(const char *str, const char *
* Get the next header and return the appropriate symbolic code. We
* need to read one line ahead for checking for a continuation line
* belonging to the current header (continuation lines start with
- * white space).
+ * white space).
*
* We get called with a fresh line already in the conn buffer, either
* from the previous http_next_header() invocation, or, the first
@@ -465,7 +480,7 @@ http_match(const char *str, const char *
*
* This stops when we encounter an empty line (we dont read beyond the header
* area).
- *
+ *
* Note that the "headerbuf" is just a place to return the result. Its
* contents are not used for the next call. This means that no cleanup
* is needed when ie doing another connection, just call the cleanup when
@@ -490,7 +505,7 @@ init_http_headerbuf(http_headerbuf_t *bu
buf->buflen = 0;
}
-static void
+static void
clean_http_headerbuf(http_headerbuf_t *buf)
{
if (buf->buf)
@@ -499,10 +514,10 @@ clean_http_headerbuf(http_headerbuf_t *b
}
/* Remove whitespace at the end of the buffer */
-static void
+static void
http_conn_trimright(conn_t *conn)
{
- while (conn->buflen &&
+ while (conn->buflen &&
isspace((unsigned char)conn->buf[conn->buflen - 1]))
conn->buflen--;
conn->buf[conn->buflen] = '\0';
@@ -511,11 +526,11 @@ http_conn_trimright(conn_t *conn)
static hdr_t
http_next_header(conn_t *conn, http_headerbuf_t *hbuf, const char **p)
{
- int i, len;
+ unsigned int i, len;
- /*
+ /*
* Have to do the stripping here because of the first line. So
- * it's done twice for the subsequent lines. No big deal
+ * it's done twice for the subsequent lines. No big deal
*/
http_conn_trimright(conn);
if (conn->buflen == 0)
@@ -530,19 +545,19 @@ http_next_header(conn_t *conn, http_head
strcpy(hbuf->buf, conn->buf);
hbuf->buflen = conn->buflen;
- /*
+ /*
* Fetch possible continuation lines. Stop at 1st non-continuation
- * and leave it in the conn buffer
- */
+ * and leave it in the conn buffer
+ */
for (i = 0; i < HTTP_MAX_CONT_LINES; i++) {
if (fetch_getln(conn) == -1)
return (hdr_syserror);
- /*
+ /*
* Note: we carry on the idea from the previous version
* that a pure whitespace line is equivalent to an empty
* one (so it's not continuation and will be handled when
- * we are called next)
+ * we are called next)
*/
http_conn_trimright(conn);
if (conn->buf[0] != ' ' && conn->buf[0] != "\t"[0])
@@ -558,7 +573,7 @@ http_next_header(conn_t *conn, http_head
}
strcpy(hbuf->buf + hbuf->buflen, conn->buf);
hbuf->buflen += conn->buflen;
- }
+ }
/*
* We could check for malformed headers but we don't really care.
@@ -577,12 +592,12 @@ http_next_header(conn_t *conn, http_head
* [Proxy-]Authenticate header parsing
*/
-/*
- * Read doublequote-delimited string into output buffer obuf (allocated
+/*
+ * Read doublequote-delimited string into output buffer obuf (allocated
* by caller, whose responsibility it is to ensure that it's big enough)
* cp points to the first char after the initial '"'
- * Handles \ quoting
- * Returns pointer to the first char after the terminating double quote, or
+ * Handles \ quoting
+ * Returns pointer to the first char after the terminating double quote, or
* NULL for error.
*/
static const char *
@@ -623,7 +638,7 @@ typedef struct {
int nc; /* Nonce count */
} http_auth_challenge_t;
-static void
+static void
init_http_auth_challenge(http_auth_challenge_t *b)
{
b->scheme = HTTPAS_UNKNOWN;
@@ -631,18 +646,18 @@ init_http_auth_challenge(http_auth_chall
b->stale = b->nc = 0;
}
-static void
+static void
clean_http_auth_challenge(http_auth_challenge_t *b)
{
- if (b->realm)
+ if (b->realm)
free(b->realm);
- if (b->qop)
+ if (b->qop)
free(b->qop);
- if (b->nonce)
+ if (b->nonce)
free(b->nonce);
- if (b->opaque)
+ if (b->opaque)
free(b->opaque);
- if (b->algo)
+ if (b->algo)
free(b->algo);
init_http_auth_challenge(b);
}
@@ -655,7 +670,7 @@ typedef struct {
int valid; /* We did parse an authenticate header */
} http_auth_challenges_t;
-static void
+static void
init_http_auth_challenges(http_auth_challenges_t *cs)
{
int i;
@@ -664,7 +679,7 @@ init_http_auth_challenges(http_auth_chal
cs->count = cs->valid = 0;
}
-static void
+static void
clean_http_auth_challenges(http_auth_challenges_t *cs)
{
int i;
@@ -678,19 +693,19 @@ clean_http_auth_challenges(http_auth_cha
init_http_auth_challenges(cs);
}
-/*
+/*
* Enumeration for lexical elements. Separators will be returned as their own
* ascii value
*/
typedef enum {HTTPHL_WORD=256, HTTPHL_STRING=257, HTTPHL_END=258,
HTTPHL_ERROR = 259} http_header_lex_t;
-/*
+/*
* Determine what kind of token comes next and return possible value
* in buf, which is supposed to have been allocated big enough by
- * caller. Advance input pointer and return element type.
+ * caller. Advance input pointer and return element type.
*/
-static int
+static int
http_header_lex(const char **cpp, char *buf)
{
size_t l;
@@ -719,7 +734,7 @@ http_header_lex(const char **cpp, char *
return (HTTPHL_WORD);
}
-/*
+/*
* Read challenges from http xxx-authenticate header and accumulate them
* in the challenges list structure.
*
@@ -731,7 +746,7 @@ http_header_lex(const char **cpp, char *
*
* We support both approaches anyway
*/
-static int
+static int
http_parse_authenticate(const char *cp, http_auth_challenges_t *cs)
{
int ret = -1;
@@ -755,7 +770,7 @@ http_parse_authenticate(const char *cp,
/* Loop on challenges */
for (; cs->count < MAX_CHALLENGES; cs->count++) {
- cs->challenges[cs->count] =
+ cs->challenges[cs->count] =
malloc(sizeof(http_auth_challenge_t));
if (cs->challenges[cs->count] == NULL) {
fetch_syserr();
@@ -768,14 +783,14 @@ http_parse_authenticate(const char *cp,
cs->challenges[cs->count]->scheme = HTTPAS_DIGEST;
} else {
cs->challenges[cs->count]->scheme = HTTPAS_UNKNOWN;
- /*
- * Continue parsing as basic or digest may
+ /*
+ * Continue parsing as basic or digest may
* follow, and the syntax is the same for
* all. We'll just ignore this one when
* looking at the list
*/
}
-
+
/* Loop on attributes */
for (;;) {
/* Key */
@@ -794,31 +809,31 @@ http_parse_authenticate(const char *cp,
goto out;
if (!strcasecmp(key, "realm"))
- cs->challenges[cs->count]->realm =
+ cs->challenges[cs->count]->realm =
strdup(value);
else if (!strcasecmp(key, "qop"))
- cs->challenges[cs->count]->qop =
+ cs->challenges[cs->count]->qop =
strdup(value);
else if (!strcasecmp(key, "nonce"))
- cs->challenges[cs->count]->nonce =
+ cs->challenges[cs->count]->nonce =
strdup(value);
else if (!strcasecmp(key, "opaque"))
- cs->challenges[cs->count]->opaque =
+ cs->challenges[cs->count]->opaque =
strdup(value);
else if (!strcasecmp(key, "algorithm"))
- cs->challenges[cs->count]->algo =
+ cs->challenges[cs->count]->algo =
strdup(value);
else if (!strcasecmp(key, "stale"))
- cs->challenges[cs->count]->stale =
+ cs->challenges[cs->count]->stale =
strcasecmp(value, "no");
/* Else ignore unknown attributes */
/* Comma or Next challenge or End */
lex = http_header_lex(&cp, key);
- /*
- * If we get a word here, this is the beginning of the
- * next challenge. Break the attributes loop
- */
+ /*
+ * If we get a word here, this is the beginning of the
+ * next challenge. Break the attributes loop
+ */
if (lex == HTTPHL_WORD)
break;
@@ -835,10 +850,10 @@ http_parse_authenticate(const char *cp,
} /* End attributes loop */
} /* End challenge loop */
- /*
- * Challenges max count exceeded. This really can't happen
- * with normal data, something's fishy -> error
- */
+ /*
+ * Challenges max count exceeded. This really can't happen
+ * with normal data, something's fishy -> error
+ */
out:
if (key)
@@ -1014,16 +1029,16 @@ init_http_auth_params(http_auth_params_t
s->scheme = s->realm = s->user = s->password = 0;
}
-static void
+static void
clean_http_auth_params(http_auth_params_t *s)
{
- if (s->scheme)
+ if (s->scheme)
free(s->scheme);
- if (s->realm)
+ if (s->realm)
free(s->realm);
- if (s->user)
+ if (s->user)
free(s->user);
- if (s->password)
+ if (s->password)
free(s->password);
init_http_auth_params(s);
}
@@ -1078,7 +1093,7 @@ http_authfromenv(const char *p, http_aut
}
ret = 0;
out:
- if (ret == -1)
+ if (ret == -1)
clean_http_auth_params(parms);
if (str)
free(str);
@@ -1086,11 +1101,11 @@ out:
}
-/*
+/*
* Digest response: the code to compute the digest is taken from the
- * sample implementation in RFC2616
+ * sample implementation in RFC2616
*/
-#define IN
+#define IN const
#define OUT
#define HASHLEN 16
@@ -1099,7 +1114,7 @@ typedef char HASH[HASHLEN];
typedef char HASHHEX[HASHHEXLEN+1];
static const char *hexchars = "0123456789abcdef";
-static void
+static void
CvtHex(IN HASH Bin, OUT HASHHEX Hex)
{
unsigned short i;
@@ -1115,7 +1130,7 @@ CvtHex(IN HASH Bin, OUT HASHHEX Hex)
};
/* calculate H(A1) as per spec */
-static void
+static void
DigestCalcHA1(
IN char * pszAlg,
IN char * pszUserName,
@@ -1150,7 +1165,7 @@ DigestCalcHA1(
}
/* calculate request-digest/response-digest as per HTTP Digest spec */
-static void
+static void
DigestCalcResponse(
IN HASHHEX HA1, /* H(A1) */
IN char * pszNonce, /* nonce from server */
@@ -1163,7 +1178,7 @@ DigestCalcResponse(
OUT HASHHEX Response /* request-digest or response-digest */
)
{
-/* DEBUG(fprintf(stderr,
+/* DEBUG(fprintf(stderr,
"Calc: HA1[%s] Nonce[%s] qop[%s] method[%s] URI[%s]\n",
HA1, pszNonce, pszQop, pszMethod, pszDigestUri));*/
MD5_CTX Md5Ctx;
@@ -1202,8 +1217,8 @@ DigestCalcResponse(
CvtHex(RespHash, Response);
}
-/*
- * Generate/Send a Digest authorization header
+/*
+ * Generate/Send a Digest authorization header
* This looks like: [Proxy-]Authorization: credentials
*
* credentials = "Digest" digest-response
@@ -1236,10 +1251,10 @@ http_digest_auth(conn_t *conn, const cha
DEBUG(fprintf(stderr, "realm/nonce not set in challenge\n"));
return(-1);
}
- if (!c->algo)
+ if (!c->algo)
c->algo = strdup("");
- if (asprintf(&options, "%s%s%s%s",
+ if (asprintf(&options, "%s%s%s%s",
*c->algo? ",algorithm=" : "", c->algo,
c->opaque? ",opaque=" : "", c->opaque?c->opaque:"")== -1)
return (-1);
@@ -1267,13 +1282,13 @@ http_digest_auth(conn_t *conn, const cha
r = http_cmd(conn, "%s: Digest username=\"%s\",realm=\"%s\","
"nonce=\"%s\",uri=\"%s\",response=\"%s\","
"qop=\"auth\", cnonce=\"%s\", nc=%s%s",
- hdr, parms->user, c->realm,
+ hdr, parms->user, c->realm,
c->nonce, url->doc, digest,
cnonce, noncecount, options);
} else {
r = http_cmd(conn, "%s: Digest username=\"%s\",realm=\"%s\","
"nonce=\"%s\",uri=\"%s\",response=\"%s\"%s",
- hdr, parms->user, c->realm,
+ hdr, parms->user, c->realm,
c->nonce, url->doc, digest, options);
}
if (options)
@@ -1304,7 +1319,7 @@ http_basic_auth(conn_t *conn, const char
}
/*
- * Chose the challenge to answer and call the appropriate routine to
+ * Chose the challenge to answer and call the appropriate routine to
* produce the header.
*/
static int
@@ -1330,16 +1345,16 @@ http_authorize(conn_t *conn, const char
}
/* Error if "Digest" was specified and there is no Digest challenge */
- if (!digest && (parms->scheme &&
+ if (!digest && (parms->scheme &&
!strcasecmp(parms->scheme, "digest"))) {
- DEBUG(fprintf(stderr,
+ DEBUG(fprintf(stderr,
"Digest auth in env, not supported by peer\n"));
return (-1);
}
- /*
- * If "basic" was specified in the environment, or there is no Digest
+ /*
+ * If "basic" was specified in the environment, or there is no Digest
* challenge, do the basic thing. Don't need a challenge for this,
- * so no need to check basic!=NULL
+ * so no need to check basic!=NULL
*/
if (!digest || (parms->scheme && !strcasecmp(parms->scheme,"basic")))
return (http_basic_auth(conn,hdr,parms->user,parms->password));
@@ -1495,7 +1510,7 @@ http_request(struct url *URL, const char
http_auth_challenges_t proxy_challenges;
/* The following calls don't allocate anything */
- init_http_headerbuf(&headerbuf);
+ init_http_headerbuf(&headerbuf);
init_http_auth_challenges(&server_challenges);
init_http_auth_challenges(&proxy_challenges);
@@ -1580,65 +1595,65 @@ http_request(struct url *URL, const char
/* virtual host */
http_cmd(conn, "Host: %s", host);
- /*
- * Proxy authorization: we only send auth after we received
- * a 407 error. We do not first try basic anyway (changed
- * when support was added for digest-auth)
- */
+ /*
+ * Proxy authorization: we only send auth after we received
+ * a 407 error. We do not first try basic anyway (changed
+ * when support was added for digest-auth)
+ */
if (purl && proxy_challenges.valid) {
http_auth_params_t aparams;
init_http_auth_params(&aparams);
if (*purl->user || *purl->pwd) {
- aparams.user = purl->user ?
+ aparams.user = purl->user ?
strdup(purl->user) : strdup("");
aparams.password = purl->pwd?
strdup(purl->pwd) : strdup("");
- } else if ((p = getenv("HTTP_PROXY_AUTH")) != NULL &&
+ } else if ((p = getenv("HTTP_PROXY_AUTH")) != NULL &&
*p != '\0') {
if (http_authfromenv(p, &aparams) < 0) {
http_seterr(HTTP_NEED_PROXY_AUTH);
goto ouch;
}
}
- http_authorize(conn, "Proxy-Authorization",
+ http_authorize(conn, "Proxy-Authorization",
&proxy_challenges, &aparams, url);
clean_http_auth_params(&aparams);
}
- /*
- * Server authorization: we never send "a priori"
+ /*
+ * Server authorization: we never send "a priori"
* Basic auth, which used to be done if user/pass were
* set in the url. This would be weird because we'd send the
- * password in the clear even if Digest is finally to be
+ * password in the clear even if Digest is finally to be
* used (it would have made more sense for the
- * pre-digest version to do this when Basic was specified
- * in the environment)
- */
+ * pre-digest version to do this when Basic was specified
+ * in the environment)
+ */
if (server_challenges.valid) {
http_auth_params_t aparams;
init_http_auth_params(&aparams);
if (*url->user || *url->pwd) {
- aparams.user = url->user ?
+ aparams.user = url->user ?
strdup(url->user) : strdup("");
- aparams.password = url->pwd ?
+ aparams.password = url->pwd ?
strdup(url->pwd) : strdup("");
- } else if ((p = getenv("HTTP_AUTH")) != NULL &&
+ } else if ((p = getenv("HTTP_AUTH")) != NULL &&
*p != '\0') {
if (http_authfromenv(p, &aparams) < 0) {
http_seterr(HTTP_NEED_AUTH);
goto ouch;
}
- } else if (fetchAuthMethod &&
+ } else if (fetchAuthMethod &&
fetchAuthMethod(url) == 0) {
- aparams.user = url->user ?
+ aparams.user = url->user ?
strdup(url->user) : strdup("");
- aparams.password = url->pwd ?
+ aparams.password = url->pwd ?
strdup(url->pwd) : strdup("");
} else {
http_seterr(HTTP_NEED_AUTH);
goto ouch;
}
- http_authorize(conn, "Authorization",
+ http_authorize(conn, "Authorization",
&server_challenges, &aparams, url);
clean_http_auth_params(&aparams);
}
@@ -1786,7 +1801,9 @@ http_request(struct url *URL, const char
DEBUG(fprintf(stderr, "failed to parse new URL\n"));
goto ouch;
}
- if (!*new->user && !*new->pwd) {
+
+ /* Only copy credentials if the host matches */
+ if (!strcmp(new->host, url->host) && !*new->user && !*new->pwd) {
strcpy(new->user, url->user);
strcpy(new->pwd, url->pwd);
}
@@ -1818,12 +1835,12 @@ http_request(struct url *URL, const char
} while (h > hdr_end);
/* we need to provide authentication */
- if (conn->err == HTTP_NEED_AUTH ||
+ if (conn->err == HTTP_NEED_AUTH ||
conn->err == HTTP_NEED_PROXY_AUTH) {
e = conn->err;
- if ((conn->err == HTTP_NEED_AUTH &&
- !server_challenges.valid) ||
- (conn->err == HTTP_NEED_PROXY_AUTH &&
+ if ((conn->err == HTTP_NEED_AUTH &&
+ !server_challenges.valid) ||
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable
mailing list