diff options
| author | bluhm <> | 2015-01-13 17:35:35 +0000 | 
|---|---|---|
| committer | bluhm <> | 2015-01-13 17:35:35 +0000 | 
| commit | 9d1112e0335b8725290afa68e01914dbc2df0606 (patch) | |
| tree | 675defc54ce1d8f4c3d5203592fb373c717de34d /src/lib/libtls/tls_client.c | |
| parent | fb6f4574b472c3157361e3f9a0ca5a2d11f47dae (diff) | |
| download | openbsd-9d1112e0335b8725290afa68e01914dbc2df0606.tar.gz openbsd-9d1112e0335b8725290afa68e01914dbc2df0606.tar.bz2 openbsd-9d1112e0335b8725290afa68e01914dbc2df0606.zip | |
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 'src/lib/libtls/tls_client.c')
| -rw-r--r-- | src/lib/libtls/tls_client.c | 24 | 
1 files changed, 19 insertions, 5 deletions
| diff --git a/src/lib/libtls/tls_client.c b/src/lib/libtls/tls_client.c index 79b1baf648..c6117c3292 100644 --- a/src/lib/libtls/tls_client.c +++ b/src/lib/libtls/tls_client.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls_client.c,v 1.7 2015/01/02 16:38:07 bluhm Exp $ */ | 1 | /* $OpenBSD: tls_client.c,v 1.8 2015/01/13 17:35:35 bluhm Exp $ */ | 
| 2 | /* | 2 | /* | 
| 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 
| 4 | * | 4 | * | 
| @@ -135,7 +135,10 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write, | |||
| 135 | { | 135 | { | 
| 136 | union { struct in_addr ip4; struct in6_addr ip6; } addrbuf; | 136 | union { struct in_addr ip4; struct in6_addr ip6; } addrbuf; | 
| 137 | X509 *cert = NULL; | 137 | X509 *cert = NULL; | 
| 138 | int ret; | 138 | int ret, ssl_err; | 
| 139 | |||
| 140 | if (ctx->flags & TLS_CONNECTING) | ||
| 141 | goto connecting; | ||
| 139 | 142 | ||
| 140 | if ((ctx->flags & TLS_CLIENT) == 0) { | 143 | if ((ctx->flags & TLS_CLIENT) == 0) { | 
| 141 | tls_set_error(ctx, "not a client context"); | 144 | tls_set_error(ctx, "not a client context"); | 
| @@ -198,11 +201,22 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write, | |||
| 198 | } | 201 | } | 
| 199 | } | 202 | } | 
| 200 | 203 | ||
| 204 | connecting: | ||
| 201 | if ((ret = SSL_connect(ctx->ssl_conn)) != 1) { | 205 | if ((ret = SSL_connect(ctx->ssl_conn)) != 1) { | 
| 202 | tls_set_error(ctx, "SSL connect failed: %i", | 206 | ssl_err = SSL_get_error(ctx->ssl_conn, ret); | 
| 203 | SSL_get_error(ctx->ssl_conn, ret)); | 207 | switch (ssl_err) { | 
| 204 | goto err; | 208 | case SSL_ERROR_WANT_READ: | 
| 209 | ctx->flags |= TLS_CONNECTING; | ||
| 210 | return (TLS_READ_AGAIN); | ||
| 211 | case SSL_ERROR_WANT_WRITE: | ||
| 212 | ctx->flags |= TLS_CONNECTING; | ||
| 213 | return (TLS_WRITE_AGAIN); | ||
| 214 | default: | ||
| 215 | tls_set_error(ctx, "SSL connect failed: %i", ssl_err); | ||
| 216 | goto err; | ||
| 217 | } | ||
| 205 | } | 218 | } | 
| 219 | ctx->flags &= ~TLS_CONNECTING; | ||
| 206 | 220 | ||
| 207 | if (ctx->config->verify_host) { | 221 | if (ctx->config->verify_host) { | 
| 208 | cert = SSL_get_peer_certificate(ctx->ssl_conn); | 222 | cert = SSL_get_peer_certificate(ctx->ssl_conn); | 
