1
0
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:
hniksic 2005-07-04 14:42:09 -07:00
parent 134e59c61a
commit 6f6af2d913
4 changed files with 107 additions and 66 deletions

View File

@ -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>
* xmalloc.c (debugging_free): Prefix hex pointer value with "0x"

View File

@ -913,7 +913,8 @@ fd_write (int fd, char *buf, int bufsize, double timeout)
used.
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 *
fd_errstr (int fd)

View File

@ -1075,7 +1075,7 @@ struct http_stat
wgint contlen; /* expected length */
wgint restval; /* the restart value */
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 *remote_time; /* remote time-stamp string */
char *error; /* textual HTTP error */
@ -1092,6 +1092,7 @@ free_hstat (struct http_stat *hs)
xfree_null (hs->newloc);
xfree_null (hs->remote_time);
xfree_null (hs->error);
xfree_null (hs->rderrmsg);
/* Guard against being called twice. */
hs->newloc = NULL;
@ -1213,7 +1214,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
hs->len = 0;
hs->contlen = -1;
hs->res = -1;
hs->errstr = "";
hs->rderrmsg = NULL;
hs->newloc = NULL;
hs->remote_time = NULL;
hs->error = NULL;
@ -1970,7 +1971,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
else
{
if (hs->res < 0)
hs->errstr = fd_errstr (sock);
hs->rderrmsg = xstrdup (fd_errstr (sock));
CLOSE_INVALIDATE (sock);
}
@ -2498,7 +2499,7 @@ The sizes do not match (local %s) -- retrieving.\n"),
logprintf (LOG_VERBOSE,
_("%s (%s) - Read error at byte %s (%s)."),
tms, tmrate, number_to_static_string (hstat.len),
hstat.errstr);
hstat.rderrmsg);
printwhat (count, opt.ntry);
free_hstat (&hstat);
continue;
@ -2510,7 +2511,7 @@ The sizes do not match (local %s) -- retrieving.\n"),
tms, tmrate,
number_to_static_string (hstat.len),
number_to_static_string (hstat.contlen),
hstat.errstr);
hstat.rderrmsg);
printwhat (count, opt.ntry);
free_hstat (&hstat);
continue;

View File

@ -234,96 +234,124 @@ ssl_init ()
return false;
}
struct openssl_transport_context {
SSL *conn; /* SSL connection handle */
char *last_error; /* last error printed with openssl_errstr */
};
static int
openssl_read (int fd, char *buf, int bufsize, void *ctx)
openssl_read (int fd, char *buf, int bufsize, void *arg)
{
int ret;
SSL *ssl = ctx;
struct openssl_transport_context *ctx = arg;
SSL *conn = ctx->conn;
do
ret = SSL_read (ssl, buf, bufsize);
ret = SSL_read (conn, buf, bufsize);
while (ret == -1
&& SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
&& SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL
&& errno == EINTR);
return ret;
}
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;
SSL *ssl = ctx;
struct openssl_transport_context *ctx = arg;
SSL *conn = ctx->conn;
do
ret = SSL_write (ssl, buf, bufsize);
ret = SSL_write (conn, buf, bufsize);
while (ret == -1
&& SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
&& SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL
&& errno == EINTR);
return ret;
}
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)
return 1;
if (SSL_pending (ssl))
if (SSL_pending (conn))
return 1;
return select_fd (fd, timeout, wait_for);
}
static int
openssl_peek (int fd, char *buf, int bufsize, void *ctx)
openssl_peek (int fd, char *buf, int bufsize, void *arg)
{
int ret;
SSL *ssl = ctx;
struct openssl_transport_context *ctx = arg;
SSL *conn = ctx->conn;
do
ret = SSL_peek (ssl, buf, bufsize);
ret = SSL_peek (conn, buf, bufsize);
while (ret == -1
&& SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
&& SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL
&& errno == EINTR);
return ret;
}
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
because we must be prepared to print more than one error. */
static char errbuf[512];
char *p = errbuf, *end = errbuf + sizeof errbuf;
unsigned long err;
struct openssl_transport_context *ctx = arg;
unsigned long errcode;
char *errmsg = NULL;
int msglen = 0;
if ((err = ERR_get_error ()) == 0)
/* Inform the caller that there have been no errors */
/* If there are no SSL-specific errors, just return NULL. */
if ((errcode = ERR_get_error ()) == 0)
return NULL;
/* Iterate over OpenSSL's error stack and print errors to ERRBUF,
separated by "; ", while being careful not to overrun ERRBUF. */
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);
/* Get rid of previous contents of ctx->last_error, if any. */
xfree_null (ctx->last_error);
if (p < end)
*p++ = '\0';
else
end[-1] = '\0';
return errbuf;
/* Iterate over OpenSSL's error stack and accumulate errors in the
last_error buffer, separated by "; ". This is better than using
a static buffer, which *always* takes up space (and has to be
large, to fit more than one error message), whereas these
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
openssl_close (int fd, void *ctx)
openssl_close (int fd, void *arg)
{
SSL *ssl = ctx;
SSL_shutdown (ssl);
SSL_free (ssl);
struct openssl_transport_context *ctx = arg;
SSL *conn = ctx->conn;
SSL_shutdown (conn);
SSL_free (conn);
xfree_null (ctx->last_error);
xfree (ctx);
#ifdef WINDOWS
closesocket (fd);
@ -331,7 +359,7 @@ openssl_close (int fd, void *ctx)
close (fd);
#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
@ -353,32 +381,36 @@ static struct transport_implementation openssl_transport = {
bool
ssl_connect (int fd)
{
SSL *ssl;
SSL *conn;
struct openssl_transport_context *ctx;
DEBUGP (("Initiating SSL handshake.\n"));
assert (ssl_ctx != NULL);
ssl = SSL_new (ssl_ctx);
if (!ssl)
conn = SSL_new (ssl_ctx);
if (!conn)
goto error;
if (!SSL_set_fd (ssl, fd))
if (!SSL_set_fd (conn, fd))
goto error;
SSL_set_connect_state (ssl);
if (SSL_connect (ssl) <= 0 || ssl->state != SSL_ST_OK)
SSL_set_connect_state (conn);
if (SSL_connect (conn) <= 0 || conn->state != SSL_ST_OK)
goto error;
ctx = xnew0 (struct openssl_transport_context);
ctx->conn = conn;
/* Register FD with Wget's transport layer, i.e. arrange that our
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",
fd, PTR_FORMAT (ssl)));
fd, PTR_FORMAT (conn)));
return true;
error:
DEBUGP (("SSL handshake failed.\n"));
print_errors ();
if (ssl)
SSL_free (ssl);
if (conn)
SSL_free (conn);
return false;
}
@ -451,10 +483,11 @@ ssl_check_certificate (int fd, const char *host)
him about problems with the server's certificate. */
const char *severity = opt.check_cert ? _("ERROR") : _("WARNING");
SSL *ssl = (SSL *) fd_transport_context (fd);
assert (ssl != NULL);
struct openssl_transport_context *ctx = fd_transport_context (fd);
SSL *conn = ctx->conn;
assert (conn != NULL);
cert = SSL_get_peer_certificate (ssl);
cert = SSL_get_peer_certificate (conn);
if (!cert)
{
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);
}
vresult = SSL_get_verify_result (ssl);
vresult = SSL_get_verify_result (conn);
if (vresult != X509_V_OK)
{
/* #### We might want to print saner (and translatable) error