diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2015-01-13 17:35:36 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2015-01-13 17:35:36 +0000 |
commit | 6da02863475cdc8a7505a78c590dc1787fe454ef (patch) | |
tree | 331e7fa9b689f4ad0bb00ab0162b738652242fa1 | |
parent | 05b9b4e27cdc1b0e1146bbafdef7c33467341a3f (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.c | 24 | ||||
-rw-r--r-- | lib/libtls/tls_internal.h | 5 |
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; |