summaryrefslogtreecommitdiff
path: root/lib/libtls/tls_client.c
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 /lib/libtls/tls_client.c
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@
Diffstat (limited to 'lib/libtls/tls_client.c')
-rw-r--r--lib/libtls/tls_client.c24
1 files changed, 19 insertions, 5 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);