Commit 4330e95a authored by Daniel Kahn Gillmor's avatar Daniel Kahn Gillmor Committed by Ondřej Surý

WIP: first pass at TLS implementation

parent 449ff02c
......@@ -5,6 +5,7 @@ kresd_SOURCES := \
daemon/worker.c \
daemon/bindings.c \
daemon/ffimodule.c \
daemon/tls.c \
daemon/main.c
kresd_DIST := daemon/lua/kres.lua daemon/lua/trust_anchors.lua
......
......@@ -23,6 +23,7 @@
#include "daemon/io.h"
#include "daemon/network.h"
#include "daemon/worker.h"
#include "daemon/tls.h"
#define negotiate_bufsize(func, handle, bufsize_want) do { \
int bufsize = 0; func(handle, &bufsize); \
......@@ -49,6 +50,7 @@ static void session_clear(struct session *s)
{
assert(s->outgoing || s->tasks.len == 0);
array_clear(s->tasks);
tls_free(s->tls_ctx);
memset(s, 0, sizeof(*s));
}
......@@ -204,7 +206,12 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
struct worker_ctx *worker = loop->data;
/* TCP pipelining is rather complicated and requires cooperation from the worker
* so the whole message reassembly and demuxing logic is inside worker */
int ret = worker_process_tcp(worker, (uv_handle_t *)handle, (const uint8_t *)buf->base, nread);
int ret = 0;
if (s->has_tls) {
ret = worker_process_tls(worker, handle, (const uint8_t *)buf->base, nread);
} else {
ret = worker_process_tcp(worker, handle, (const uint8_t *)buf->base, nread);
}
if (ret < 0) {
worker_end_tcp(worker, (uv_handle_t *)handle);
/* Exceeded per-connection quota for outstanding requests
......@@ -245,6 +252,9 @@ static void _tcp_accept(uv_stream_t *master, int status, bool tls)
* is idle and should be terminated, this is an educated guess. */
struct session *session = client->data;
session->has_tls = tls;
if (tls && !session->tls_ctx) {
session->tls_ctx = tls_new(master->loop->data);
}
uv_timer_t *timer = &session->timeout;
uv_timer_init(master->loop, timer);
timer->data = client;
......
......@@ -21,6 +21,7 @@
#include "lib/generic/array.h"
struct qr_task;
struct tls_ctx_t;
/* Per-session (TCP or UDP) persistent structure,
* that exists between remote counterpart and a local socket.
......@@ -31,6 +32,7 @@ struct session {
bool has_tls;
uv_timer_t timeout;
struct qr_task *buffering;
struct tls_ctx_t *tls_ctx;
array_t(struct qr_task *) tasks;
};
......
This diff is collapsed.
/* Copyright (C) 2016 American Civil Liberties Union (ACLU)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <uv.h>
#include <libknot/packet/pkt.h>
struct tls_ctx_t;
struct tls_ctx_t* tls_new(struct worker_ctx *worker);
void tls_free(struct tls_ctx_t* tls);
int push_tls(struct qr_task *task, uv_handle_t *handle, knot_pkt_t *pkt,
uv_write_t *writer, qr_task_send_cb on_send);
int worker_process_tls(struct worker_ctx *worker, uv_stream_t *handle, const uint8_t *buf, ssize_t nread);
......@@ -30,6 +30,7 @@
#include "daemon/worker.h"
#include "daemon/engine.h"
#include "daemon/io.h"
#include "daemon/tls.h"
/* @internal Union of various libuv objects for freelist. */
struct req
......@@ -455,13 +456,18 @@ static int qr_task_send(struct qr_task *task, uv_handle_t *handle, struct sockad
send_req->as.send.data = task;
ret = uv_udp_send(&send_req->as.send, (uv_udp_t *)handle, &buf, 1, addr, &on_send);
} else {
uint16_t pkt_size = htons(pkt->size);
uv_buf_t buf[2] = {
{ (char *)&pkt_size, sizeof(pkt_size) },
{ (char *)pkt->wire, pkt->size }
};
send_req->as.write.data = task;
ret = uv_write(&send_req->as.write, (uv_stream_t *)handle, buf, 2, &on_write);
struct session *session = handle->data;
if (session->has_tls) {
ret = push_tls(task, handle, pkt, &send_req->as.write, qr_task_on_send);
} else {
uint16_t pkt_size = htons(pkt->size);
uv_buf_t buf[2] = {
{ (char *)&pkt_size, sizeof(pkt_size) },
{ (char *)pkt->wire, pkt->size }
};
send_req->as.write.data = task;
ret = uv_write(&send_req->as.write, (uv_stream_t *)handle, buf, 2, &on_write);
}
}
if (ret == 0) {
qr_task_ref(task); /* Pending ioreq on current task */
......@@ -834,7 +840,7 @@ int worker_end_tcp(struct worker_ctx *worker, uv_handle_t *handle)
return 0;
}
int worker_process_tcp(struct worker_ctx *worker, uv_handle_t *handle, const uint8_t *msg, ssize_t len)
int worker_process_tcp(struct worker_ctx *worker, uv_stream_t *handle, const uint8_t *msg, ssize_t len)
{
if (!worker || !handle) {
return kr_error(EINVAL);
......@@ -865,7 +871,7 @@ int worker_process_tcp(struct worker_ctx *worker, uv_handle_t *handle, const uin
* to buffer incoming message until it's complete. */
if (!session->outgoing) {
if (!task) {
task = qr_task_create(worker, handle, NULL);
task = qr_task_create(worker, (uv_handle_t *)handle, NULL);
if (!task) {
return kr_error(ENOMEM);
}
......
......@@ -108,7 +108,7 @@ int worker_submit(struct worker_ctx *worker, uv_handle_t *handle, knot_pkt_t *qu
* If the fragment contains a complete query or completes current fragment, execute it.
* @return 0 or an error code
*/
int worker_process_tcp(struct worker_ctx *worker, uv_handle_t *handle, const uint8_t *msg, ssize_t len);
int worker_process_tcp(struct worker_ctx *worker, uv_stream_t *handle, const uint8_t *msg, ssize_t len);
/**
* End current DNS/TCP session, this disassociates pending tasks from this session
......@@ -128,3 +128,6 @@ int worker_reserve(struct worker_ctx *worker, size_t ring_maxlen);
/** Collect worker mempools */
void worker_reclaim(struct worker_ctx *worker);
struct qr_task;
typedef int (*qr_task_send_cb)(struct qr_task *task, uv_handle_t *handle, int status);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment