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;

Reply via email to