diff options
author | Yves-Alexis Perez <corsac@corsac.net> | 2012-06-28 21:16:07 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@corsac.net> | 2012-06-28 21:16:07 +0200 |
commit | b34738ed08c2227300d554b139e2495ca5da97d6 (patch) | |
tree | 62f33b52820f2e49f0e53c0f8c636312037c8054 /src/libtls/tls_socket.c | |
parent | 0a9d51a49042a68daa15b0c74a2b7f152f52606b (diff) | |
download | vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.tar.gz vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.zip |
Imported Upstream version 4.6.4
Diffstat (limited to 'src/libtls/tls_socket.c')
-rw-r--r-- | src/libtls/tls_socket.c | 115 |
1 files changed, 106 insertions, 9 deletions
diff --git a/src/libtls/tls_socket.c b/src/libtls/tls_socket.c index e0c440a4c..3abff596d 100644 --- a/src/libtls/tls_socket.c +++ b/src/libtls/tls_socket.c @@ -16,8 +16,20 @@ #include "tls_socket.h" #include <unistd.h> +#include <errno.h> #include <debug.h> +#include <threading/thread.h> + +/** + * Buffer size for plain side I/O + */ +#define PLAIN_BUF_SIZE 4096 + +/** + * Buffer size for encrypted side I/O + */ +#define CRYPTO_BUF_SIZE 4096 typedef struct private_tls_socket_t private_tls_socket_t; typedef struct private_tls_application_t private_tls_application_t; @@ -67,7 +79,7 @@ struct private_tls_socket_t { }; METHOD(tls_application_t, process, status_t, - private_tls_application_t *this, tls_reader_t *reader) + private_tls_application_t *this, bio_reader_t *reader) { chunk_t data; @@ -80,7 +92,7 @@ METHOD(tls_application_t, process, status_t, } METHOD(tls_application_t, build, status_t, - private_tls_application_t *this, tls_writer_t *writer) + private_tls_application_t *this, bio_writer_t *writer) { if (this->out.len) { @@ -96,8 +108,8 @@ METHOD(tls_application_t, build, status_t, */ static bool exchange(private_tls_socket_t *this, bool wr) { - char buf[1024]; - ssize_t len; + char buf[CRYPTO_BUF_SIZE], *pos; + ssize_t len, out; int round = 0; for (round = 0; TRUE; round++) @@ -109,10 +121,18 @@ static bool exchange(private_tls_socket_t *this, bool wr) { case NEED_MORE: case ALREADY_DONE: - len = write(this->fd, buf, len); - if (len == -1) + pos = buf; + while (len) { - return FALSE; + out = write(this->fd, pos, len); + if (out == -1) + { + DBG1(DBG_TLS, "TLS crypto write error: %s", + strerror(errno)); + return FALSE; + } + len -= out; + pos += out; } continue; case INVALID_STATE: @@ -175,6 +195,81 @@ METHOD(tls_socket_t, write_, bool, return FALSE; } +METHOD(tls_socket_t, splice, bool, + private_tls_socket_t *this, int rfd, int wfd) +{ + char buf[PLAIN_BUF_SIZE], *pos; + fd_set set; + chunk_t data; + ssize_t len; + bool old; + + while (TRUE) + { + FD_ZERO(&set); + FD_SET(rfd, &set); + FD_SET(this->fd, &set); + + old = thread_cancelability(TRUE); + len = select(max(rfd, this->fd) + 1, &set, NULL, NULL, NULL); + thread_cancelability(old); + if (len == -1) + { + DBG1(DBG_TLS, "TLS select error: %s", strerror(errno)); + return FALSE; + } + if (FD_ISSET(this->fd, &set)) + { + if (!read_(this, &data)) + { + DBG2(DBG_TLS, "TLS read error/disconnect"); + return TRUE; + } + pos = data.ptr; + while (data.len) + { + len = write(wfd, pos, data.len); + if (len == -1) + { + free(data.ptr); + DBG1(DBG_TLS, "TLS plain write error: %s", strerror(errno)); + return FALSE; + } + data.len -= len; + pos += len; + } + free(data.ptr); + } + if (FD_ISSET(rfd, &set)) + { + len = read(rfd, buf, sizeof(buf)); + if (len > 0) + { + if (!write_(this, chunk_create(buf, len))) + { + DBG1(DBG_TLS, "TLS write error"); + return FALSE; + } + } + else + { + if (len < 0) + { + DBG1(DBG_TLS, "TLS plain read error: %s", strerror(errno)); + return FALSE; + } + return TRUE; + } + } + } +} + +METHOD(tls_socket_t, get_fd, int, + private_tls_socket_t *this) +{ + return this->fd; +} + METHOD(tls_socket_t, destroy, void, private_tls_socket_t *this) { @@ -187,7 +282,7 @@ METHOD(tls_socket_t, destroy, void, * See header */ tls_socket_t *tls_socket_create(bool is_server, identification_t *server, - identification_t *peer, int fd) + identification_t *peer, int fd, tls_cache_t *cache) { private_tls_socket_t *this; @@ -195,6 +290,8 @@ tls_socket_t *tls_socket_create(bool is_server, identification_t *server, .public = { .read = _read_, .write = _write_, + .splice = _splice, + .get_fd = _get_fd, .destroy = _destroy, }, .app = { @@ -208,7 +305,7 @@ tls_socket_t *tls_socket_create(bool is_server, identification_t *server, ); this->tls = tls_create(is_server, server, peer, TLS_PURPOSE_GENERIC, - &this->app.application); + &this->app.application, cache); if (!this->tls) { free(this); |