For non-blocking sockets tls_connect_fds() could fail with EAGAIN.
authorbluhm <bluhm@openbsd.org>
Tue, 13 Jan 2015 17:35:35 +0000 (17:35 +0000)
committerbluhm <bluhm@openbsd.org>
Tue, 13 Jan 2015 17:35:35 +0000 (17:35 +0000)
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@

lib/libtls/tls_client.c
lib/libtls/tls_internal.h

index 79b1baf..c6117c3 100644 (file)
@@ -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);
index 4b25057..1a2bd38 100644 (file)
@@ -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;