diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2015-09-10 10:14:21 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2015-09-10 10:14:21 +0000 |
commit | 61808a78974649e09438a6739320582c5d406e91 (patch) | |
tree | 73067e9bad65b9903a95b3bbdecd7e90ff9e39a9 /lib/libtls/tls_server.c | |
parent | 330f2594cffb53ef590216e7f2f3eba370e74d40 (diff) |
Split tls_handshake() out from tls_accept/tls_connect. By doing this the
tls_accept/tls_connect functions can be guaranteed to succeed or fail and
will no longer return TLS_READ_AGAIN/TLS_WRITE_AGAIN. This also resolves
the semantics of tls_accept_*.
The tls_handshake() function now does I/O and can return
TLS_READ_AGAIN/TLS_WRITE_AGAIN. Calls to tls_read() and tls_write() will
trigger the handshake if it has not already completed, meaning that in many
cases existing code will continue to work.
Discussed over many coffees at l2k15.
ok beck@ bluhm@
Diffstat (limited to 'lib/libtls/tls_server.c')
-rw-r--r-- | lib/libtls/tls_server.c | 76 |
1 files changed, 46 insertions, 30 deletions
diff --git a/lib/libtls/tls_server.c b/lib/libtls/tls_server.c index a3cee095962..3dfd29ac19f 100644 --- a/lib/libtls/tls_server.c +++ b/lib/libtls/tls_server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_server.c,v 1.14 2015/09/10 09:10:42 jsing Exp $ */ +/* $OpenBSD: tls_server.c,v 1.15 2015/09/10 10:14:20 jsing Exp $ */ /* * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> * @@ -110,54 +110,70 @@ tls_configure_server(struct tls *ctx) } int +tls_accept_socket(struct tls *ctx, struct tls **cctx, int socket) +{ + return (tls_accept_fds(ctx, cctx, socket, socket)); +} + +int tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write) { - struct tls *conn_ctx = *cctx; - int ret, err; + struct tls *conn_ctx = NULL; if ((ctx->flags & TLS_SERVER) == 0) { tls_set_errorx(ctx, "not a server context"); goto err; } - if (conn_ctx == NULL) { - if ((conn_ctx = tls_server_conn(ctx)) == NULL) { - tls_set_errorx(ctx, "connection context failure"); - goto err; - } - *cctx = conn_ctx; - - if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { - tls_set_errorx(ctx, "ssl failure"); - goto err; - } - if (SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx) != 1) { - tls_set_errorx(ctx, "ssl application data failure"); - goto err; - } - if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 || - SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) { - tls_set_errorx(ctx, "ssl file descriptor failure"); - goto err; - } + if ((conn_ctx = tls_server_conn(ctx)) == NULL) { + tls_set_errorx(ctx, "connection context failure"); + goto err; } - if ((ret = SSL_accept(conn_ctx->ssl_conn)) != 1) { - err = tls_ssl_error(ctx, conn_ctx->ssl_conn, ret, "accept"); - if (err == TLS_READ_AGAIN || err == TLS_WRITE_AGAIN) { - return (err); - } + if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { + tls_set_errorx(ctx, "ssl failure"); + goto err; + } + if (SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx) != 1) { + tls_set_errorx(ctx, "ssl application data failure"); + goto err; + } + if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 || + SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) { + tls_set_errorx(ctx, "ssl file descriptor failure"); goto err; } + *cctx = conn_ctx; + return (0); err: + tls_free(conn_ctx); + + *cctx = NULL; + return (-1); } int -tls_accept_socket(struct tls *ctx, struct tls **cctx, int socket) +tls_handshake_server(struct tls *ctx) { - return (tls_accept_fds(ctx, cctx, socket, socket)); + int ssl_ret; + int rv = -1; + + if ((ctx->flags & TLS_SERVER_CONN) == 0) { + tls_set_errorx(ctx, "not a server connection context"); + goto err; + } + + if ((ssl_ret = SSL_accept(ctx->ssl_conn)) != 1) { + rv = tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "handshake"); + goto err; + } + + ctx->state |= TLS_HANDSHAKE_COMPLETE; + + err: + return (rv); } |