mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Only allocate an error string on actual error.
This commit is contained in:
parent
134e59c61a
commit
6f6af2d913
@ -1,3 +1,9 @@
|
|||||||
|
2005-07-04 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
|
* openssl.c (openssl_errstr): Instead of always using a large
|
||||||
|
static buffer, only allocate the error string when there is an
|
||||||
|
actual error.
|
||||||
|
|
||||||
2005-07-04 Hrvoje Niksic <hniksic@xemacs.org>
|
2005-07-04 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
* xmalloc.c (debugging_free): Prefix hex pointer value with "0x"
|
* xmalloc.c (debugging_free): Prefix hex pointer value with "0x"
|
||||||
|
@ -913,7 +913,8 @@ fd_write (int fd, char *buf, int bufsize, double timeout)
|
|||||||
used.
|
used.
|
||||||
|
|
||||||
If the transport doesn't support error messages or doesn't supply
|
If the transport doesn't support error messages or doesn't supply
|
||||||
one, strerror(errno) is returned. */
|
one, strerror(errno) is returned. The returned error message
|
||||||
|
should not be used after fd_close has been called. */
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
fd_errstr (int fd)
|
fd_errstr (int fd)
|
||||||
|
11
src/http.c
11
src/http.c
@ -1075,7 +1075,7 @@ struct http_stat
|
|||||||
wgint contlen; /* expected length */
|
wgint contlen; /* expected length */
|
||||||
wgint restval; /* the restart value */
|
wgint restval; /* the restart value */
|
||||||
int res; /* the result of last read */
|
int res; /* the result of last read */
|
||||||
const char *errstr; /* error message from read error */
|
char *rderrmsg; /* error message from read error */
|
||||||
char *newloc; /* new location (redirection) */
|
char *newloc; /* new location (redirection) */
|
||||||
char *remote_time; /* remote time-stamp string */
|
char *remote_time; /* remote time-stamp string */
|
||||||
char *error; /* textual HTTP error */
|
char *error; /* textual HTTP error */
|
||||||
@ -1092,6 +1092,7 @@ free_hstat (struct http_stat *hs)
|
|||||||
xfree_null (hs->newloc);
|
xfree_null (hs->newloc);
|
||||||
xfree_null (hs->remote_time);
|
xfree_null (hs->remote_time);
|
||||||
xfree_null (hs->error);
|
xfree_null (hs->error);
|
||||||
|
xfree_null (hs->rderrmsg);
|
||||||
|
|
||||||
/* Guard against being called twice. */
|
/* Guard against being called twice. */
|
||||||
hs->newloc = NULL;
|
hs->newloc = NULL;
|
||||||
@ -1213,7 +1214,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
|
|||||||
hs->len = 0;
|
hs->len = 0;
|
||||||
hs->contlen = -1;
|
hs->contlen = -1;
|
||||||
hs->res = -1;
|
hs->res = -1;
|
||||||
hs->errstr = "";
|
hs->rderrmsg = NULL;
|
||||||
hs->newloc = NULL;
|
hs->newloc = NULL;
|
||||||
hs->remote_time = NULL;
|
hs->remote_time = NULL;
|
||||||
hs->error = NULL;
|
hs->error = NULL;
|
||||||
@ -1970,7 +1971,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (hs->res < 0)
|
if (hs->res < 0)
|
||||||
hs->errstr = fd_errstr (sock);
|
hs->rderrmsg = xstrdup (fd_errstr (sock));
|
||||||
CLOSE_INVALIDATE (sock);
|
CLOSE_INVALIDATE (sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2498,7 +2499,7 @@ The sizes do not match (local %s) -- retrieving.\n"),
|
|||||||
logprintf (LOG_VERBOSE,
|
logprintf (LOG_VERBOSE,
|
||||||
_("%s (%s) - Read error at byte %s (%s)."),
|
_("%s (%s) - Read error at byte %s (%s)."),
|
||||||
tms, tmrate, number_to_static_string (hstat.len),
|
tms, tmrate, number_to_static_string (hstat.len),
|
||||||
hstat.errstr);
|
hstat.rderrmsg);
|
||||||
printwhat (count, opt.ntry);
|
printwhat (count, opt.ntry);
|
||||||
free_hstat (&hstat);
|
free_hstat (&hstat);
|
||||||
continue;
|
continue;
|
||||||
@ -2510,7 +2511,7 @@ The sizes do not match (local %s) -- retrieving.\n"),
|
|||||||
tms, tmrate,
|
tms, tmrate,
|
||||||
number_to_static_string (hstat.len),
|
number_to_static_string (hstat.len),
|
||||||
number_to_static_string (hstat.contlen),
|
number_to_static_string (hstat.contlen),
|
||||||
hstat.errstr);
|
hstat.rderrmsg);
|
||||||
printwhat (count, opt.ntry);
|
printwhat (count, opt.ntry);
|
||||||
free_hstat (&hstat);
|
free_hstat (&hstat);
|
||||||
continue;
|
continue;
|
||||||
|
153
src/openssl.c
153
src/openssl.c
@ -234,96 +234,124 @@ ssl_init ()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct openssl_transport_context {
|
||||||
|
SSL *conn; /* SSL connection handle */
|
||||||
|
char *last_error; /* last error printed with openssl_errstr */
|
||||||
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
openssl_read (int fd, char *buf, int bufsize, void *ctx)
|
openssl_read (int fd, char *buf, int bufsize, void *arg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
SSL *ssl = ctx;
|
struct openssl_transport_context *ctx = arg;
|
||||||
|
SSL *conn = ctx->conn;
|
||||||
do
|
do
|
||||||
ret = SSL_read (ssl, buf, bufsize);
|
ret = SSL_read (conn, buf, bufsize);
|
||||||
while (ret == -1
|
while (ret == -1
|
||||||
&& SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
|
&& SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL
|
||||||
&& errno == EINTR);
|
&& errno == EINTR);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
openssl_write (int fd, char *buf, int bufsize, void *ctx)
|
openssl_write (int fd, char *buf, int bufsize, void *arg)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
SSL *ssl = ctx;
|
struct openssl_transport_context *ctx = arg;
|
||||||
|
SSL *conn = ctx->conn;
|
||||||
do
|
do
|
||||||
ret = SSL_write (ssl, buf, bufsize);
|
ret = SSL_write (conn, buf, bufsize);
|
||||||
while (ret == -1
|
while (ret == -1
|
||||||
&& SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
|
&& SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL
|
||||||
&& errno == EINTR);
|
&& errno == EINTR);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
openssl_poll (int fd, double timeout, int wait_for, void *ctx)
|
openssl_poll (int fd, double timeout, int wait_for, void *arg)
|
||||||
{
|
{
|
||||||
SSL *ssl = ctx;
|
struct openssl_transport_context *ctx = arg;
|
||||||
|
SSL *conn = ctx->conn;
|
||||||
if (timeout == 0)
|
if (timeout == 0)
|
||||||
return 1;
|
return 1;
|
||||||
if (SSL_pending (ssl))
|
if (SSL_pending (conn))
|
||||||
return 1;
|
return 1;
|
||||||
return select_fd (fd, timeout, wait_for);
|
return select_fd (fd, timeout, wait_for);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
openssl_peek (int fd, char *buf, int bufsize, void *ctx)
|
openssl_peek (int fd, char *buf, int bufsize, void *arg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
SSL *ssl = ctx;
|
struct openssl_transport_context *ctx = arg;
|
||||||
|
SSL *conn = ctx->conn;
|
||||||
do
|
do
|
||||||
ret = SSL_peek (ssl, buf, bufsize);
|
ret = SSL_peek (conn, buf, bufsize);
|
||||||
while (ret == -1
|
while (ret == -1
|
||||||
&& SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
|
&& SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL
|
||||||
&& errno == EINTR);
|
&& errno == EINTR);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
openssl_errstr (int fd, void *ctx)
|
openssl_errstr (int fd, void *arg)
|
||||||
{
|
{
|
||||||
/* Unfortunately we cannot use ERR_error_string's internal buffer
|
struct openssl_transport_context *ctx = arg;
|
||||||
because we must be prepared to print more than one error. */
|
unsigned long errcode;
|
||||||
static char errbuf[512];
|
char *errmsg = NULL;
|
||||||
char *p = errbuf, *end = errbuf + sizeof errbuf;
|
int msglen = 0;
|
||||||
unsigned long err;
|
|
||||||
|
|
||||||
if ((err = ERR_get_error ()) == 0)
|
/* If there are no SSL-specific errors, just return NULL. */
|
||||||
/* Inform the caller that there have been no errors */
|
if ((errcode = ERR_get_error ()) == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Iterate over OpenSSL's error stack and print errors to ERRBUF,
|
/* Get rid of previous contents of ctx->last_error, if any. */
|
||||||
separated by "; ", while being careful not to overrun ERRBUF. */
|
xfree_null (ctx->last_error);
|
||||||
do
|
|
||||||
{
|
|
||||||
ERR_error_string_n (err, p, end - p);
|
|
||||||
p = strchr (p, '\0');
|
|
||||||
err = ERR_get_error ();
|
|
||||||
if (err == 0)
|
|
||||||
break;
|
|
||||||
if (p < end) *p++ = ';';
|
|
||||||
if (p < end) *p++ = ' ';
|
|
||||||
}
|
|
||||||
while (p < end);
|
|
||||||
|
|
||||||
if (p < end)
|
/* Iterate over OpenSSL's error stack and accumulate errors in the
|
||||||
*p++ = '\0';
|
last_error buffer, separated by "; ". This is better than using
|
||||||
else
|
a static buffer, which *always* takes up space (and has to be
|
||||||
end[-1] = '\0';
|
large, to fit more than one error message), whereas these
|
||||||
return errbuf;
|
allocations are only performed when there is an actual error. */
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
const char *str = ERR_error_string (errcode, NULL);
|
||||||
|
int len = strlen (str);
|
||||||
|
|
||||||
|
/* Allocate space for the existing message, plus two more chars
|
||||||
|
for the "; " separator and one for the terminating \0. */
|
||||||
|
errmsg = xrealloc (errmsg, msglen + len + 2 + 1);
|
||||||
|
memcpy (errmsg + msglen, str, len);
|
||||||
|
msglen += len;
|
||||||
|
|
||||||
|
/* Get next error and bail out if there are no more. */
|
||||||
|
errcode = ERR_get_error ();
|
||||||
|
if (errcode == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
errmsg[msglen++] = ';';
|
||||||
|
errmsg[msglen++] = ' ';
|
||||||
|
}
|
||||||
|
errmsg[msglen] = '\0';
|
||||||
|
|
||||||
|
/* Store the error in ctx->last_error where openssl_close will
|
||||||
|
eventually find it and free it. */
|
||||||
|
ctx->last_error = errmsg;
|
||||||
|
|
||||||
|
return errmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
openssl_close (int fd, void *ctx)
|
openssl_close (int fd, void *arg)
|
||||||
{
|
{
|
||||||
SSL *ssl = ctx;
|
struct openssl_transport_context *ctx = arg;
|
||||||
SSL_shutdown (ssl);
|
SSL *conn = ctx->conn;
|
||||||
SSL_free (ssl);
|
|
||||||
|
SSL_shutdown (conn);
|
||||||
|
SSL_free (conn);
|
||||||
|
xfree_null (ctx->last_error);
|
||||||
|
xfree (ctx);
|
||||||
|
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
closesocket (fd);
|
closesocket (fd);
|
||||||
@ -331,7 +359,7 @@ openssl_close (int fd, void *ctx)
|
|||||||
close (fd);
|
close (fd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEBUGP (("Closed %d/SSL 0x%0lx\n", fd, (unsigned long) ssl));
|
DEBUGP (("Closed %d/SSL 0x%0*lx\n", fd, PTR_FORMAT (conn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* openssl_transport is the singleton that describes the SSL transport
|
/* openssl_transport is the singleton that describes the SSL transport
|
||||||
@ -353,32 +381,36 @@ static struct transport_implementation openssl_transport = {
|
|||||||
bool
|
bool
|
||||||
ssl_connect (int fd)
|
ssl_connect (int fd)
|
||||||
{
|
{
|
||||||
SSL *ssl;
|
SSL *conn;
|
||||||
|
struct openssl_transport_context *ctx;
|
||||||
|
|
||||||
DEBUGP (("Initiating SSL handshake.\n"));
|
DEBUGP (("Initiating SSL handshake.\n"));
|
||||||
|
|
||||||
assert (ssl_ctx != NULL);
|
assert (ssl_ctx != NULL);
|
||||||
ssl = SSL_new (ssl_ctx);
|
conn = SSL_new (ssl_ctx);
|
||||||
if (!ssl)
|
if (!conn)
|
||||||
goto error;
|
goto error;
|
||||||
if (!SSL_set_fd (ssl, fd))
|
if (!SSL_set_fd (conn, fd))
|
||||||
goto error;
|
goto error;
|
||||||
SSL_set_connect_state (ssl);
|
SSL_set_connect_state (conn);
|
||||||
if (SSL_connect (ssl) <= 0 || ssl->state != SSL_ST_OK)
|
if (SSL_connect (conn) <= 0 || conn->state != SSL_ST_OK)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
ctx = xnew0 (struct openssl_transport_context);
|
||||||
|
ctx->conn = conn;
|
||||||
|
|
||||||
/* Register FD with Wget's transport layer, i.e. arrange that our
|
/* Register FD with Wget's transport layer, i.e. arrange that our
|
||||||
functions are used for reading, writing, and polling. */
|
functions are used for reading, writing, and polling. */
|
||||||
fd_register_transport (fd, &openssl_transport, ssl);
|
fd_register_transport (fd, &openssl_transport, ctx);
|
||||||
DEBUGP (("Handshake successful; connected socket %d to SSL handle 0x%0*lx\n",
|
DEBUGP (("Handshake successful; connected socket %d to SSL handle 0x%0*lx\n",
|
||||||
fd, PTR_FORMAT (ssl)));
|
fd, PTR_FORMAT (conn)));
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
DEBUGP (("SSL handshake failed.\n"));
|
DEBUGP (("SSL handshake failed.\n"));
|
||||||
print_errors ();
|
print_errors ();
|
||||||
if (ssl)
|
if (conn)
|
||||||
SSL_free (ssl);
|
SSL_free (conn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,10 +483,11 @@ ssl_check_certificate (int fd, const char *host)
|
|||||||
him about problems with the server's certificate. */
|
him about problems with the server's certificate. */
|
||||||
const char *severity = opt.check_cert ? _("ERROR") : _("WARNING");
|
const char *severity = opt.check_cert ? _("ERROR") : _("WARNING");
|
||||||
|
|
||||||
SSL *ssl = (SSL *) fd_transport_context (fd);
|
struct openssl_transport_context *ctx = fd_transport_context (fd);
|
||||||
assert (ssl != NULL);
|
SSL *conn = ctx->conn;
|
||||||
|
assert (conn != NULL);
|
||||||
|
|
||||||
cert = SSL_get_peer_certificate (ssl);
|
cert = SSL_get_peer_certificate (conn);
|
||||||
if (!cert)
|
if (!cert)
|
||||||
{
|
{
|
||||||
logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
|
logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
|
||||||
@ -473,7 +506,7 @@ ssl_check_certificate (int fd, const char *host)
|
|||||||
OPENSSL_free (issuer);
|
OPENSSL_free (issuer);
|
||||||
}
|
}
|
||||||
|
|
||||||
vresult = SSL_get_verify_result (ssl);
|
vresult = SSL_get_verify_result (conn);
|
||||||
if (vresult != X509_V_OK)
|
if (vresult != X509_V_OK)
|
||||||
{
|
{
|
||||||
/* #### We might want to print saner (and translatable) error
|
/* #### We might want to print saner (and translatable) error
|
||||||
|
Loading…
Reference in New Issue
Block a user