|
|
|
@ -29,8 +29,9 @@ public:
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static ssize_t forst_tls_push_func(gnutls_transport_ptr_t p, const void *data,
|
|
|
|
|
size_t size);
|
|
|
|
|
static ssize_t forst_tls_pull_func(gnutls_transport_ptr_t p, void *data, size_t size);
|
|
|
|
|
size_t size);
|
|
|
|
|
static ssize_t forst_tls_pull_func(gnutls_transport_ptr_t p, void *data,
|
|
|
|
|
size_t size);
|
|
|
|
|
|
|
|
|
|
Tls::Tls() : impl{heap<Tls::Impl>()} {}
|
|
|
|
|
|
|
|
|
@ -51,12 +52,22 @@ public:
|
|
|
|
|
ErrorOr<size_t> read(void *buffer, size_t length) override {
|
|
|
|
|
ssize_t size = gnutls_record_recv(session_handle, buffer, length);
|
|
|
|
|
if (size < 0) {
|
|
|
|
|
if(gnutls_error_is_fatal(size) == 0){
|
|
|
|
|
return recoverableError([size](){return std::string{"Read recoverable Error "}+std::string{gnutls_strerror(size)};}, "Error read r");
|
|
|
|
|
}else{
|
|
|
|
|
return criticalError([size](){return std::string{"Read critical Error "}+std::string{gnutls_strerror(size)};}, "Error read c");
|
|
|
|
|
if (gnutls_error_is_fatal(size) == 0) {
|
|
|
|
|
return recoverableError(
|
|
|
|
|
[size]() {
|
|
|
|
|
return std::string{"Read recoverable Error "} +
|
|
|
|
|
std::string{gnutls_strerror(size)};
|
|
|
|
|
},
|
|
|
|
|
"Error read r");
|
|
|
|
|
} else {
|
|
|
|
|
return criticalError(
|
|
|
|
|
[size]() {
|
|
|
|
|
return std::string{"Read critical Error "} +
|
|
|
|
|
std::string{gnutls_strerror(size)};
|
|
|
|
|
},
|
|
|
|
|
"Error read c");
|
|
|
|
|
}
|
|
|
|
|
}else if(size == 0){
|
|
|
|
|
} else if (size == 0) {
|
|
|
|
|
return criticalError("Disconnected");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -71,11 +82,23 @@ public:
|
|
|
|
|
|
|
|
|
|
ErrorOr<size_t> write(const void *buffer, size_t length) override {
|
|
|
|
|
ssize_t size = gnutls_record_send(session_handle, buffer, length);
|
|
|
|
|
if(size < 0){
|
|
|
|
|
if(gnutls_error_is_fatal(size) == 0){
|
|
|
|
|
return recoverableError([size](){return std::string{"Write recoverable Error "}+std::string{gnutls_strerror(size)} + " " + std::to_string(size);}, "Error write r");
|
|
|
|
|
}else{
|
|
|
|
|
return criticalError([size](){return std::string{"Write critical Error "}+std::string{gnutls_strerror(size)} + " " + std::to_string(size);}, "Error write c");
|
|
|
|
|
if (size < 0) {
|
|
|
|
|
if (gnutls_error_is_fatal(size) == 0) {
|
|
|
|
|
return recoverableError(
|
|
|
|
|
[size]() {
|
|
|
|
|
return std::string{"Write recoverable Error "} +
|
|
|
|
|
std::string{gnutls_strerror(size)} + " " +
|
|
|
|
|
std::to_string(size);
|
|
|
|
|
},
|
|
|
|
|
"Error write r");
|
|
|
|
|
} else {
|
|
|
|
|
return criticalError(
|
|
|
|
|
[size]() {
|
|
|
|
|
return std::string{"Write critical Error "} +
|
|
|
|
|
std::string{gnutls_strerror(size)} + " " +
|
|
|
|
|
std::to_string(size);
|
|
|
|
|
},
|
|
|
|
|
"Error write c");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -87,22 +110,53 @@ public:
|
|
|
|
|
gnutls_session_t &session() { return session_handle; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
struct TlsServerStreamHelper {
|
|
|
|
|
public:
|
|
|
|
|
Own<ConveyorFeeder<Own<IoStream>>> feeder;
|
|
|
|
|
SinkConveyor connection_sink;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
TlsServerStreamHelper(Own<ConveyorFeeder<Own<IoStream>>> f)
|
|
|
|
|
: feeder{std::move(f)} {}
|
|
|
|
|
};
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
TlsServer::TlsServer(Own<Server> srv) : internal{std::move(srv)} {}
|
|
|
|
|
|
|
|
|
|
Conveyor<Own<IoStream>> TlsServer::accept() {
|
|
|
|
|
SAW_ASSERT(internal) { return Conveyor<Own<IoStream>>{nullptr, nullptr}; }
|
|
|
|
|
return internal->accept().then([](Own<IoStream> stream) -> Own<IoStream> {
|
|
|
|
|
/// @todo handshake
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return heap<TlsIoStream>(std::move(stream));
|
|
|
|
|
return nullptr;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
auto caf = newConveyorAndFeeder<Own<IoStream>>();
|
|
|
|
|
|
|
|
|
|
Own<TlsServerStreamHelper> helper =
|
|
|
|
|
heap<TlsServerStreamHelper>(std::move(caf.feeder));
|
|
|
|
|
TlsServerStreamHelper *hlp_ptr = helper.get();
|
|
|
|
|
|
|
|
|
|
auto acceptor_conv =
|
|
|
|
|
internal->accept().then([this](Own<IoStream> stream) -> Own<IoStream> {
|
|
|
|
|
/// @todo handshake
|
|
|
|
|
auto tls_stream = heap<TlsIoStream>(std::move(stream));
|
|
|
|
|
auto &session = tls_stream->session();
|
|
|
|
|
|
|
|
|
|
gnutls_init(&session, GNUTLS_SERVER);
|
|
|
|
|
|
|
|
|
|
return heap<TlsIoStream>(std::move(stream));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
helper->connection_sink = acceptor_conv.sink();
|
|
|
|
|
|
|
|
|
|
return caf.conveyor.attach(std::move(helper));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
/*
|
|
|
|
|
* Small helper for setting up the nonblocking connection handshake
|
|
|
|
|
*/
|
|
|
|
|
* Small helper for setting up the nonblocking connection handshake
|
|
|
|
|
*/
|
|
|
|
|
struct TlsClientStreamHelper {
|
|
|
|
|
public:
|
|
|
|
|
Own<ConveyorFeeder<Own<IoStream>>> feeder;
|
|
|
|
@ -111,51 +165,45 @@ public:
|
|
|
|
|
SinkConveyor stream_writer;
|
|
|
|
|
|
|
|
|
|
Own<TlsIoStream> stream = nullptr;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
TlsClientStreamHelper(Own<ConveyorFeeder<Own<IoStream>>> f):
|
|
|
|
|
feeder{std::move(f)}
|
|
|
|
|
{}
|
|
|
|
|
TlsClientStreamHelper(Own<ConveyorFeeder<Own<IoStream>>> f)
|
|
|
|
|
: feeder{std::move(f)} {}
|
|
|
|
|
|
|
|
|
|
void setupTurn(){
|
|
|
|
|
SAW_ASSERT(stream){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
void setupTurn() {
|
|
|
|
|
SAW_ASSERT(stream) { return; }
|
|
|
|
|
|
|
|
|
|
stream_reader = stream->readReady().then([this](){
|
|
|
|
|
turn();
|
|
|
|
|
}).sink();
|
|
|
|
|
stream_reader = stream->readReady().then([this]() { turn(); }).sink();
|
|
|
|
|
|
|
|
|
|
stream_writer = stream->writeReady().then([this](){
|
|
|
|
|
turn();
|
|
|
|
|
}).sink();
|
|
|
|
|
stream_writer = stream->writeReady().then([this]() { turn(); }).sink();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void turn(){
|
|
|
|
|
if(stream){
|
|
|
|
|
void turn() {
|
|
|
|
|
if (stream) {
|
|
|
|
|
// Guarantee that the receiving end is already setup
|
|
|
|
|
SAW_ASSERT(feeder){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
SAW_ASSERT(feeder) { return; }
|
|
|
|
|
|
|
|
|
|
auto &session = stream->session();
|
|
|
|
|
|
|
|
|
|
int ret;
|
|
|
|
|
do {
|
|
|
|
|
ret = gnutls_handshake(session);
|
|
|
|
|
} while ( (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) && gnutls_error_is_fatal(ret) == 0);
|
|
|
|
|
} while ((ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) &&
|
|
|
|
|
gnutls_error_is_fatal(ret) == 0);
|
|
|
|
|
|
|
|
|
|
if(gnutls_error_is_fatal(ret)){
|
|
|
|
|
if (gnutls_error_is_fatal(ret)) {
|
|
|
|
|
feeder->fail(criticalError("Couldn't create Tls connection"));
|
|
|
|
|
stream = nullptr;
|
|
|
|
|
}else if(ret == GNUTLS_E_SUCCESS){
|
|
|
|
|
} else if (ret == GNUTLS_E_SUCCESS) {
|
|
|
|
|
feeder->feed(std::move(stream));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
TlsNetworkAddress::TlsNetworkAddress(Own<NetworkAddress> net_addr, const std::string& host_name_, Tls &tls_)
|
|
|
|
|
TlsNetworkAddress::TlsNetworkAddress(Own<NetworkAddress> net_addr,
|
|
|
|
|
const std::string &host_name_, Tls &tls_)
|
|
|
|
|
: internal{std::move(net_addr)}, host_name{host_name_}, tls{tls_} {}
|
|
|
|
|
|
|
|
|
|
Own<Server> TlsNetworkAddress::listen() {
|
|
|
|
@ -168,41 +216,45 @@ Conveyor<Own<IoStream>> TlsNetworkAddress::connect() {
|
|
|
|
|
|
|
|
|
|
// Helper setups
|
|
|
|
|
auto caf = newConveyorAndFeeder<Own<IoStream>>();
|
|
|
|
|
Own<TlsClientStreamHelper> helper = heap<TlsClientStreamHelper>(std::move(caf.feeder));
|
|
|
|
|
TlsClientStreamHelper* hlp_ptr = helper.get();
|
|
|
|
|
|
|
|
|
|
Own<TlsClientStreamHelper> helper =
|
|
|
|
|
heap<TlsClientStreamHelper>(std::move(caf.feeder));
|
|
|
|
|
TlsClientStreamHelper *hlp_ptr = helper.get();
|
|
|
|
|
|
|
|
|
|
// Conveyor entangled structure
|
|
|
|
|
auto prim_conv = internal->connect().then([this, hlp_ptr](
|
|
|
|
|
Own<IoStream> stream) -> ErrorOr<void> {
|
|
|
|
|
IoStream* inner_stream = stream.get();
|
|
|
|
|
auto tls_stream = heap<TlsIoStream>(std::move(stream));
|
|
|
|
|
auto prim_conv = internal->connect().then(
|
|
|
|
|
[this, hlp_ptr](Own<IoStream> stream) -> ErrorOr<void> {
|
|
|
|
|
IoStream *inner_stream = stream.get();
|
|
|
|
|
auto tls_stream = heap<TlsIoStream>(std::move(stream));
|
|
|
|
|
|
|
|
|
|
auto &session = tls_stream->session();
|
|
|
|
|
auto &session = tls_stream->session();
|
|
|
|
|
|
|
|
|
|
gnutls_init(&session, GNUTLS_CLIENT);
|
|
|
|
|
gnutls_init(&session, GNUTLS_CLIENT);
|
|
|
|
|
|
|
|
|
|
const std::string &addr = this->address();
|
|
|
|
|
const std::string &addr = this->address();
|
|
|
|
|
|
|
|
|
|
gnutls_server_name_set(session, GNUTLS_NAME_DNS, addr.c_str(),
|
|
|
|
|
addr.size());
|
|
|
|
|
gnutls_server_name_set(session, GNUTLS_NAME_DNS, addr.c_str(),
|
|
|
|
|
addr.size());
|
|
|
|
|
|
|
|
|
|
gnutls_set_default_priority(session);
|
|
|
|
|
gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
|
|
|
|
|
tls.getImpl().xcred);
|
|
|
|
|
gnutls_session_set_verify_cert(session, addr.c_str(), 0);
|
|
|
|
|
gnutls_set_default_priority(session);
|
|
|
|
|
gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
|
|
|
|
|
tls.getImpl().xcred);
|
|
|
|
|
gnutls_session_set_verify_cert(session, addr.c_str(), 0);
|
|
|
|
|
|
|
|
|
|
gnutls_transport_set_ptr(session, reinterpret_cast<gnutls_transport_ptr_t>(inner_stream));
|
|
|
|
|
gnutls_transport_set_push_function(session, forst_tls_push_func);
|
|
|
|
|
gnutls_transport_set_pull_function(session, forst_tls_pull_func);
|
|
|
|
|
gnutls_transport_set_ptr(
|
|
|
|
|
session,
|
|
|
|
|
reinterpret_cast<gnutls_transport_ptr_t>(inner_stream));
|
|
|
|
|
gnutls_transport_set_push_function(session, forst_tls_push_func);
|
|
|
|
|
gnutls_transport_set_pull_function(session, forst_tls_pull_func);
|
|
|
|
|
|
|
|
|
|
// gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
|
|
|
|
|
// gnutls_handshake_set_timeout(session,
|
|
|
|
|
// GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
|
|
|
|
|
|
|
|
|
|
hlp_ptr->stream = std::move(tls_stream);
|
|
|
|
|
hlp_ptr->setupTurn();
|
|
|
|
|
hlp_ptr->turn();
|
|
|
|
|
hlp_ptr->stream = std::move(tls_stream);
|
|
|
|
|
hlp_ptr->setupTurn();
|
|
|
|
|
hlp_ptr->turn();
|
|
|
|
|
|
|
|
|
|
return Void{};
|
|
|
|
|
});
|
|
|
|
|
return Void{};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
helper->connection_sink = prim_conv.sink();
|
|
|
|
|
|
|
|
|
@ -210,7 +262,7 @@ Conveyor<Own<IoStream>> TlsNetworkAddress::connect() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ssize_t forst_tls_push_func(gnutls_transport_ptr_t p, const void *data,
|
|
|
|
|
size_t size) {
|
|
|
|
|
size_t size) {
|
|
|
|
|
IoStream *stream = reinterpret_cast<IoStream *>(p);
|
|
|
|
|
if (!stream) {
|
|
|
|
|
return -1;
|
|
|
|
@ -224,7 +276,8 @@ static ssize_t forst_tls_push_func(gnutls_transport_ptr_t p, const void *data,
|
|
|
|
|
return static_cast<ssize_t>(length.value());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ssize_t forst_tls_pull_func(gnutls_transport_ptr_t p, void *data, size_t size) {
|
|
|
|
|
static ssize_t forst_tls_pull_func(gnutls_transport_ptr_t p, void *data,
|
|
|
|
|
size_t size) {
|
|
|
|
|
IoStream *stream = reinterpret_cast<IoStream *>(p);
|
|
|
|
|
if (!stream) {
|
|
|
|
|
return -1;
|
|
|
|
@ -242,9 +295,10 @@ const std::string &TlsNetworkAddress::address() const {
|
|
|
|
|
assert(internal);
|
|
|
|
|
return internal->address();
|
|
|
|
|
}
|
|
|
|
|
uint16_t TlsNetworkAddress::port() const {
|
|
|
|
|
uint16_t TlsNetworkAddress::port() const {
|
|
|
|
|
assert(internal);
|
|
|
|
|
return internal->port(); }
|
|
|
|
|
return internal->port();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string TlsNetworkAddress::toString() const { return internal->toString(); }
|
|
|
|
|
|
|
|
|
@ -253,14 +307,13 @@ TlsNetwork::TlsNetwork(Network &network) : internal{network} {}
|
|
|
|
|
Conveyor<Own<NetworkAddress>> TlsNetwork::parseAddress(const std::string &addr,
|
|
|
|
|
uint16_t port) {
|
|
|
|
|
return internal.parseAddress(addr, port)
|
|
|
|
|
.then(
|
|
|
|
|
[this, addr, port](Own<NetworkAddress> net) -> Own<NetworkAddress> {
|
|
|
|
|
assert(net);
|
|
|
|
|
return heap<TlsNetworkAddress>(std::move(net), addr, tls);
|
|
|
|
|
});
|
|
|
|
|
.then([this, addr](Own<NetworkAddress> net) -> Own<NetworkAddress> {
|
|
|
|
|
assert(net);
|
|
|
|
|
return heap<TlsNetworkAddress>(std::move(net), addr, tls);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::optional<Own<TlsNetwork>> setupTlsNetwork(Network &network) {
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
return heap<TlsNetwork>(network);
|
|
|
|
|
}
|
|
|
|
|
} // namespace saw
|
|
|
|
|