Hi, I think the connect function of libtls needs the same logic to read and write again like the read, write, accept functions for non-blocking sockets. All the connect checks should be done only once.
ok? bluhm Index: lib/libtls/tls_client.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/lib/libtls/tls_client.c,v retrieving revision 1.7 diff -u -p -r1.7 tls_client.c --- lib/libtls/tls_client.c 2 Jan 2015 16:38:07 -0000 1.7 +++ lib/libtls/tls_client.c 2 Jan 2015 17:46:45 -0000 @@ -135,7 +135,10 @@ tls_connect_fds(struct tls *ctx, int fd_ { 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_ } } + 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); Index: lib/libtls/tls_internal.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/lib/libtls/tls_internal.h,v retrieving revision 1.5 diff -u -p -r1.5 tls_internal.h --- lib/libtls/tls_internal.h 17 Dec 2014 17:51:33 -0000 1.5 +++ lib/libtls/tls_internal.h 2 Jan 2015 17:46:45 -0000 @@ -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;