Fix timeout option when used with SSL

Previously wget didn't honor the --timeout option if the remote host did
not answer SSL handshake

Signed-off-by: Tomas Hozza <thozza@redhat.com>
This commit is contained in:
Karsten Hopp 2013-07-11 11:27:35 +02:00 committed by Giuseppe Scrivano
parent 91f0f99e9a
commit b8f036d16c
2 changed files with 65 additions and 11 deletions

View File

@ -1,3 +1,9 @@
2013-07-11 Karsten Hopp <karsten@redhat.com>
* openssl.c (struct openssl_read_args, struct scwt_context): New struct.
(openssl_read, ssl_connect_with_timeout_callback): New function.
(ssl_connect_wget): respect connect timeout.
2013-07-11 Tim Ruehsen <tim.ruehsen@gmx.de> 2013-07-11 Tim Ruehsen <tim.ruehsen@gmx.de>
* gnutls.c (ssl_connect_wget): respect connect timeout. * gnutls.c (ssl_connect_wget): respect connect timeout.

View File

@ -251,24 +251,50 @@ ssl_init (void)
return false; return false;
} }
struct openssl_transport_context { struct openssl_transport_context
{
SSL *conn; /* SSL connection handle */ SSL *conn; /* SSL connection handle */
char *last_error; /* last error printed with openssl_errstr */ char *last_error; /* last error printed with openssl_errstr */
}; };
struct openssl_read_args
{
int fd;
struct openssl_transport_context *ctx;
char *buf;
int bufsize;
int retval;
};
static void openssl_read_callback(void *arg)
{
struct openssl_read_args *args = (struct openssl_read_args *) arg;
struct openssl_transport_context *ctx = args->ctx;
SSL *conn = ctx->conn;
char *buf = args->buf;
int bufsize = args->bufsize;
int ret;
do
ret = SSL_read (conn, buf, bufsize);
while (ret == -1 && SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL
&& errno == EINTR);
args->retval = ret;
}
static int static int
openssl_read (int fd, char *buf, int bufsize, void *arg) openssl_read (int fd, char *buf, int bufsize, void *arg)
{ {
int ret; struct openssl_read_args args;
struct openssl_transport_context *ctx = arg; args.fd = fd;
SSL *conn = ctx->conn; args.buf = buf;
do args.bufsize = bufsize;
ret = SSL_read (conn, buf, bufsize); args.ctx = (struct openssl_transport_context*) arg;
while (ret == -1
&& SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL
&& errno == EINTR);
return ret; if (run_with_timeout(opt.read_timeout, openssl_read_callback, &args)) {
return -1;
}
return args.retval;
} }
static int static int
@ -386,6 +412,19 @@ static struct transport_implementation openssl_transport = {
openssl_peek, openssl_errstr, openssl_close openssl_peek, openssl_errstr, openssl_close
}; };
struct scwt_context
{
SSL *ssl;
int result;
};
static void
ssl_connect_with_timeout_callback(void *arg)
{
struct scwt_context *ctx = (struct scwt_context *)arg;
ctx->result = SSL_connect(ctx->ssl);
}
/* Perform the SSL handshake on file descriptor FD, which is assumed /* Perform the SSL handshake on file descriptor FD, which is assumed
to be connected to an SSL server. The SSL handle provided by to be connected to an SSL server. The SSL handle provided by
OpenSSL is registered with the file descriptor FD using OpenSSL is registered with the file descriptor FD using
@ -398,6 +437,7 @@ bool
ssl_connect_wget (int fd, const char *hostname) ssl_connect_wget (int fd, const char *hostname)
{ {
SSL *conn; SSL *conn;
struct scwt_context scwt_ctx;
struct openssl_transport_context *ctx; struct openssl_transport_context *ctx;
DEBUGP (("Initiating SSL handshake.\n")); DEBUGP (("Initiating SSL handshake.\n"));
@ -425,7 +465,14 @@ ssl_connect_wget (int fd, const char *hostname)
if (!SSL_set_fd (conn, FD_TO_SOCKET (fd))) if (!SSL_set_fd (conn, FD_TO_SOCKET (fd)))
goto error; goto error;
SSL_set_connect_state (conn); SSL_set_connect_state (conn);
if (SSL_connect (conn) <= 0 || conn->state != SSL_ST_OK)
scwt_ctx.ssl = conn;
if (run_with_timeout(opt.read_timeout, ssl_connect_with_timeout_callback,
&scwt_ctx)) {
DEBUGP (("SSL handshake timed out.\n"));
goto timeout;
}
if (scwt_ctx.result <= 0 || conn->state != SSL_ST_OK)
goto error; goto error;
ctx = xnew0 (struct openssl_transport_context); ctx = xnew0 (struct openssl_transport_context);
@ -441,6 +488,7 @@ ssl_connect_wget (int fd, const char *hostname)
error: error:
DEBUGP (("SSL handshake failed.\n")); DEBUGP (("SSL handshake failed.\n"));
print_errors (); print_errors ();
timeout:
if (conn) if (conn)
SSL_free (conn); SSL_free (conn);
return false; return false;