summaryrefslogtreecommitdiff
path: root/lib/libtls/tls_server.c
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2015-09-10 10:14:21 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2015-09-10 10:14:21 +0000
commit61808a78974649e09438a6739320582c5d406e91 (patch)
tree73067e9bad65b9903a95b3bbdecd7e90ff9e39a9 /lib/libtls/tls_server.c
parent330f2594cffb53ef590216e7f2f3eba370e74d40 (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.c76
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);
}