summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2015-01-13 17:35:36 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2015-01-13 17:35:36 +0000
commit6da02863475cdc8a7505a78c590dc1787fe454ef (patch)
tree331e7fa9b689f4ad0bb00ab0162b738652242fa1
parent05b9b4e27cdc1b0e1146bbafdef7c33467341a3f (diff)
For non-blocking sockets tls_connect_fds() could fail with EAGAIN.
Use the same logic from the read, write, accept functions to inform the caller wether a readable or writable socket is needed. After that event, the connect function must be called again. All the checks before connecting are done only once. OK tedu@
-rw-r--r--lib/libtls/tls_client.c24
-rw-r--r--lib/libtls/tls_internal.h5
2 files changed, 22 insertions, 7 deletions
diff --git a/lib/libtls/tls_client.c b/lib/libtls/tls_client.c
index 79b1baf648c..c6117c32929 100644
--- a/lib/libtls/tls_client.c
+++ b/lib/libtls/tls_client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_client.c,v 1.7 2015/01/02 16:38:07 bluhm Exp $ */
+/* $OpenBSD: tls_client.c,v 1.8 2015/01/13 17:35:35 bluhm Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -135,7 +135,10 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write,
{
union { struct in_addr ip4; struct in6_addr ip6; } addrbuf;
X509 *cert = NULL;
- int ret;
+ int ret, ssl_err;
+
+ if (ctx->flags & TLS_CONNECTING)
+ goto connecting;
if ((ctx->flags & TLS_CLIENT) == 0) {
tls_set_error(ctx, "not a client context");
@@ -198,11 +201,22 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write,
}
}
+ connecting:
if ((ret = SSL_connect(ctx->ssl_conn)) != 1) {
- tls_set_error(ctx, "SSL connect failed: %i",
- SSL_get_error(ctx->ssl_conn, ret));
- goto err;
+ ssl_err = SSL_get_error(ctx->ssl_conn, ret);
+ switch (ssl_err) {
+ case SSL_ERROR_WANT_READ:
+ ctx->flags |= TLS_CONNECTING;
+ return (TLS_READ_AGAIN);
+ case SSL_ERROR_WANT_WRITE:
+ ctx->flags |= TLS_CONNECTING;
+ return (TLS_WRITE_AGAIN);
+ default:
+ tls_set_error(ctx, "SSL connect failed: %i", ssl_err);
+ goto err;
+ }
}
+ ctx->flags &= ~TLS_CONNECTING;
if (ctx->config->verify_host) {
cert = SSL_get_peer_certificate(ctx->ssl_conn);
diff --git a/lib/libtls/tls_internal.h b/lib/libtls/tls_internal.h
index 4b250574ef7..1a2bd388b7d 100644
--- a/lib/libtls/tls_internal.h
+++ b/lib/libtls/tls_internal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_internal.h,v 1.5 2014/12/17 17:51:33 doug Exp $ */
+/* $OpenBSD: tls_internal.h,v 1.6 2015/01/13 17:35:35 bluhm Exp $ */
/*
* Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org>
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
@@ -44,7 +44,8 @@ struct tls_config {
#define TLS_CLIENT (1 << 0)
#define TLS_SERVER (1 << 1)
-#define TLS_SERVER_CONN (1 << 2)
+#define TLS_SERVER_CONN (1 << 2)
+#define TLS_CONNECTING (1 << 3)
struct tls {
struct tls_config *config;