stream: Integrate cipher
parent
f6336e02be
commit
8ddca0a197
|
@ -19,6 +19,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "sys/queue.h"
|
#include "sys/queue.h"
|
||||||
#include "rcbuf.h"
|
#include "rcbuf.h"
|
||||||
|
#include "vec.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -45,6 +46,7 @@ enum stream_event {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stream;
|
struct stream;
|
||||||
|
struct crypto_cipher;
|
||||||
|
|
||||||
typedef void (*stream_event_fn)(struct stream*, enum stream_event);
|
typedef void (*stream_event_fn)(struct stream*, enum stream_event);
|
||||||
typedef void (*stream_req_fn)(void*, enum stream_req_status);
|
typedef void (*stream_req_fn)(void*, enum stream_req_status);
|
||||||
|
@ -68,6 +70,7 @@ struct stream_impl {
|
||||||
stream_req_fn on_done, void* userdata);
|
stream_req_fn on_done, void* userdata);
|
||||||
int (*send_first)(struct stream*, struct rcbuf* payload);
|
int (*send_first)(struct stream*, struct rcbuf* payload);
|
||||||
void (*exec_and_send)(struct stream*, stream_exec_fn, void* userdata);
|
void (*exec_and_send)(struct stream*, stream_exec_fn, void* userdata);
|
||||||
|
int (*install_cipher)(struct stream*, struct crypto_cipher*);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stream {
|
struct stream {
|
||||||
|
@ -86,6 +89,9 @@ struct stream {
|
||||||
uint32_t bytes_received;
|
uint32_t bytes_received;
|
||||||
|
|
||||||
bool cork;
|
bool cork;
|
||||||
|
|
||||||
|
struct crypto_cipher* cipher;
|
||||||
|
struct vec tmp_buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef ENABLE_WEBSOCKET
|
#ifdef ENABLE_WEBSOCKET
|
||||||
|
@ -108,3 +114,5 @@ void stream_exec_and_send(struct stream* self, stream_exec_fn, void* userdata);
|
||||||
#ifdef ENABLE_TLS
|
#ifdef ENABLE_TLS
|
||||||
int stream_upgrade_to_tls(struct stream* self, void* context);
|
int stream_upgrade_to_tls(struct stream* self, void* context);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int stream_install_cipher(struct stream* self, struct crypto_cipher* cipher);
|
||||||
|
|
|
@ -82,6 +82,8 @@ static int stream_gnutls__flush(struct stream* base)
|
||||||
{
|
{
|
||||||
struct stream_gnutls* self = (struct stream_gnutls*)base;
|
struct stream_gnutls* self = (struct stream_gnutls*)base;
|
||||||
while (!TAILQ_EMPTY(&self->base.send_queue)) {
|
while (!TAILQ_EMPTY(&self->base.send_queue)) {
|
||||||
|
assert(self->base.state != STREAM_STATE_CLOSED);
|
||||||
|
|
||||||
struct stream_req* req = TAILQ_FIRST(&self->base.send_queue);
|
struct stream_req* req = TAILQ_FIRST(&self->base.send_queue);
|
||||||
|
|
||||||
ssize_t rc = gnutls_record_send(self->session,
|
ssize_t rc = gnutls_record_send(self->session,
|
||||||
|
|
|
@ -31,10 +31,23 @@
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "stream-common.h"
|
#include "stream-common.h"
|
||||||
#include "sys/queue.h"
|
#include "sys/queue.h"
|
||||||
|
#include "crypto.h"
|
||||||
|
#include "neatvnc.h"
|
||||||
|
|
||||||
static_assert(sizeof(struct stream) <= STREAM_ALLOC_SIZE,
|
static_assert(sizeof(struct stream) <= STREAM_ALLOC_SIZE,
|
||||||
"struct stream has grown too large, increase STREAM_ALLOC_SIZE");
|
"struct stream has grown too large, increase STREAM_ALLOC_SIZE");
|
||||||
|
|
||||||
|
static struct rcbuf* encrypt_rcbuf(struct stream* self, struct rcbuf* payload)
|
||||||
|
{
|
||||||
|
uint8_t* ciphertext = malloc(payload->size);
|
||||||
|
assert(ciphertext);
|
||||||
|
crypto_cipher_encrypt(self->cipher, ciphertext, payload->payload,
|
||||||
|
payload->size);
|
||||||
|
struct rcbuf* result = rcbuf_new(ciphertext, payload->size);
|
||||||
|
rcbuf_unref(payload);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static int stream_tcp_close(struct stream* self)
|
static int stream_tcp_close(struct stream* self)
|
||||||
{
|
{
|
||||||
if (self->state == STREAM_STATE_CLOSED)
|
if (self->state == STREAM_STATE_CLOSED)
|
||||||
|
@ -57,6 +70,8 @@ static int stream_tcp_close(struct stream* self)
|
||||||
|
|
||||||
static void stream_tcp_destroy(struct stream* self)
|
static void stream_tcp_destroy(struct stream* self)
|
||||||
{
|
{
|
||||||
|
vec_destroy(&self->tmp_buf);
|
||||||
|
crypto_cipher_del(self->cipher);
|
||||||
stream_close(self);
|
stream_close(self);
|
||||||
aml_unref(self->handler);
|
aml_unref(self->handler);
|
||||||
free(self);
|
free(self);
|
||||||
|
@ -76,7 +91,9 @@ static int stream_tcp__flush(struct stream* self)
|
||||||
if (req->exec) {
|
if (req->exec) {
|
||||||
if (req->payload)
|
if (req->payload)
|
||||||
rcbuf_unref(req->payload);
|
rcbuf_unref(req->payload);
|
||||||
req->payload = req->exec(self, req->userdata);
|
struct rcbuf* payload = req->exec(self, req->userdata);
|
||||||
|
req->payload = self->cipher ?
|
||||||
|
encrypt_rcbuf(self, payload) : payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
iov[n_msgs].iov_base = req->payload->payload;
|
iov[n_msgs].iov_base = req->payload->payload;
|
||||||
|
@ -187,11 +204,27 @@ static ssize_t stream_tcp_read(struct stream* self, void* dst, size_t size)
|
||||||
if (self->state != STREAM_STATE_NORMAL)
|
if (self->state != STREAM_STATE_NORMAL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ssize_t rc = read(self->fd, dst, size);
|
uint8_t* read_buffer = dst;
|
||||||
|
|
||||||
|
if (self->cipher) {
|
||||||
|
vec_reserve(&self->tmp_buf, size);
|
||||||
|
read_buffer = self->tmp_buf.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t rc = read(self->fd, read_buffer, size);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
stream__remote_closed(self);
|
stream__remote_closed(self);
|
||||||
if (rc > 0)
|
if (rc > 0)
|
||||||
self->bytes_received += rc;
|
self->bytes_received += rc;
|
||||||
|
|
||||||
|
if (rc > 0 && self->cipher && !crypto_cipher_decrypt(self->cipher, dst,
|
||||||
|
read_buffer, rc)) {
|
||||||
|
nvnc_log(NVNC_LOG_ERROR, "Message authentication failed!");
|
||||||
|
stream__remote_closed(self);
|
||||||
|
errno = EPROTO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +238,7 @@ static int stream_tcp_send(struct stream* self, struct rcbuf* payload,
|
||||||
if (!req)
|
if (!req)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
req->payload = payload;
|
req->payload = self->cipher ? encrypt_rcbuf(self, payload) : payload;
|
||||||
req->on_done = on_done;
|
req->on_done = on_done;
|
||||||
req->userdata = userdata;
|
req->userdata = userdata;
|
||||||
|
|
||||||
|
@ -247,6 +280,14 @@ static void stream_tcp_exec_and_send(struct stream* self,
|
||||||
stream_tcp__flush(self);
|
stream_tcp__flush(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int stream_tcp_install_cipher(struct stream* self,
|
||||||
|
struct crypto_cipher* cipher)
|
||||||
|
{
|
||||||
|
assert(!self->cipher);
|
||||||
|
self->cipher = cipher;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct stream_impl impl = {
|
static struct stream_impl impl = {
|
||||||
.close = stream_tcp_close,
|
.close = stream_tcp_close,
|
||||||
.destroy = stream_tcp_destroy,
|
.destroy = stream_tcp_destroy,
|
||||||
|
@ -254,6 +295,7 @@ static struct stream_impl impl = {
|
||||||
.send = stream_tcp_send,
|
.send = stream_tcp_send,
|
||||||
.send_first = stream_tcp_send_first,
|
.send_first = stream_tcp_send_first,
|
||||||
.exec_and_send = stream_tcp_exec_and_send,
|
.exec_and_send = stream_tcp_exec_and_send,
|
||||||
|
.install_cipher = stream_tcp_install_cipher,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stream* stream_new(int fd, stream_event_fn on_event, void* userdata)
|
struct stream* stream_new(int fd, stream_event_fn on_event, void* userdata)
|
||||||
|
|
|
@ -65,3 +65,11 @@ void stream_exec_and_send(struct stream* self, stream_exec_fn exec_fn,
|
||||||
else
|
else
|
||||||
stream_send(self, exec_fn(self, userdata), NULL, NULL);
|
stream_send(self, exec_fn(self, userdata), NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int stream_install_cipher(struct stream* self, struct crypto_cipher* cipher)
|
||||||
|
{
|
||||||
|
if (!self->impl->install_cipher) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return self->impl->install_cipher(self, cipher);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue