]> sjero.net Git - wget/commitdiff
Fix timeout option when used with SSL
authorKarsten Hopp <karsten@redhat.com>
Thu, 11 Jul 2013 09:27:35 +0000 (11:27 +0200)
committerGiuseppe Scrivano <gscrivano@gnu.org>
Fri, 12 Jul 2013 09:43:41 +0000 (11:43 +0200)
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>
src/ChangeLog
src/openssl.c

index 8822973ed75a076f91d0b811dda1d7852a8a96dd..0d3b505bfddb0fc56d98a6849bffafbde207c8be 100644 (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>
 
         * gnutls.c (ssl_connect_wget): respect connect timeout.
index 3924e41ea19e9cf7af2c7b0e6296206753d1e789..e2eec4f7c2932b704fd5cd63e0ed48a735f15813 100644 (file)
@@ -251,24 +251,50 @@ ssl_init (void)
   return false;
 }
 
-struct openssl_transport_context {
+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 *arg)
+struct openssl_read_args
 {
-  int ret;
-  struct openssl_transport_context *ctx = arg;
+  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
+  while (ret == -1 && SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL
          && errno == EINTR);
+  args->retval = ret;
+}
 
-  return ret;
+static int
+openssl_read (int fd, char *buf, int bufsize, void *arg)
+{
+  struct openssl_read_args args;
+  args.fd = fd;
+  args.buf = buf;
+  args.bufsize = bufsize;
+  args.ctx = (struct openssl_transport_context*) arg;
+
+  if (run_with_timeout(opt.read_timeout, openssl_read_callback, &args)) {
+    return -1;
+  }
+  return args.retval;
 }
 
 static int
@@ -386,6 +412,19 @@ static struct transport_implementation openssl_transport = {
   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
    to be connected to an SSL server.  The SSL handle provided by
    OpenSSL is registered with the file descriptor FD using
@@ -398,6 +437,7 @@ bool
 ssl_connect_wget (int fd, const char *hostname)
 {
   SSL *conn;
+  struct scwt_context scwt_ctx;
   struct openssl_transport_context *ctx;
 
   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)))
     goto error;
   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;
 
   ctx = xnew0 (struct openssl_transport_context);
@@ -441,6 +488,7 @@ ssl_connect_wget (int fd, const char *hostname)
  error:
   DEBUGP (("SSL handshake failed.\n"));
   print_errors ();
+ timeout:
   if (conn)
     SSL_free (conn);
   return false;