Add basic SSL/TLS listener

This commit adds a basic SSL/TLS listener using `openssl`.
The `SslListener` object can accept a connection and get a decrypted
stream.

Signed-off-by: Sayan Nandan <nandansayan@outlook.com>
next
Sayan Nandan 4 years ago
parent 5d17e0a89d
commit 0087d6b07c
No known key found for this signature in database
GPG Key ID: C31EFD7DDA12AEE0

91
Cargo.lock generated

@ -81,6 +81,12 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.19"
@ -138,6 +144,21 @@ dependencies = [
"termcolor",
]
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "fs_extra"
version = "1.2.0"
@ -156,7 +177,7 @@ version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
"libc",
"wasi 0.9.0+wasi-snapshot-preview1",
]
@ -245,7 +266,7 @@ version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
]
[[package]]
@ -321,6 +342,43 @@ version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
[[package]]
name = "openssl"
version = "0.10.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d008f51b1acffa0d3450a68606e6a51c123012edaacb0f4e1426bd978869187"
dependencies = [
"bitflags",
"cfg-if 1.0.0",
"foreign-types",
"lazy_static",
"libc",
"openssl-sys",
]
[[package]]
name = "openssl-src"
version = "111.13.0+1.1.1i"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "045e4dc48af57aad93d665885789b43222ae26f4886494da12d1ed58d309dcb6"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
version = "0.9.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de52d8eabd217311538a39bba130d7dea1f1e118010fee7a033d966845e7d5fe"
dependencies = [
"autocfg",
"cc",
"libc",
"openssl-src",
"pkg-config",
"vcpkg",
]
[[package]]
name = "parking_lot"
version = "0.11.1"
@ -338,7 +396,7 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
"cloudabi",
"instant",
"libc",
@ -353,6 +411,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c"
[[package]]
name = "pkg-config"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "ppv-lite86"
version = "0.2.9"
@ -513,7 +577,7 @@ version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fd8b795c389288baa5f355489c65e71fd48a02104600d15c4cfbc561e9e429d"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
"libc",
"redox_syscall",
"winapi",
@ -549,12 +613,15 @@ dependencies = [
"lazy_static",
"libtdb",
"log",
"openssl",
"openssl-sys",
"parking_lot",
"regex",
"serde",
"serde_derive",
"tdb_macros",
"tokio",
"tokio-openssl-vendored",
"toml",
]
@ -651,6 +718,16 @@ dependencies = [
"syn",
]
[[package]]
name = "tokio-openssl-vendored"
version = "0.5.0"
source = "git+https://github.com/terrabasedb/tokio-openssl-vendored.git?branch=next#048622804dd641428b51a0bcc72cd9c801d825e7"
dependencies = [
"openssl",
"openssl-sys",
"tokio",
]
[[package]]
name = "toml"
version = "0.5.7"
@ -684,6 +761,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "vcpkg"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
[[package]]
name = "vec_map"
version = "0.8.2"

@ -22,7 +22,9 @@ log = "0.4.11"
chrono = "0.4.19"
regex = "1.4.2"
tdb_macros = {path="../tdb-macros"}
tokio-openssl-vendored = {git="https://github.com/terrabasedb/tokio-openssl-vendored.git", branch="next"}
openssl = "0.10.31"
openssl-sys = "0.9.59"
[target.'cfg(not(target_env = "msvc"))'.dependencies]
jemallocator = "0.3.2"

@ -52,7 +52,6 @@ use tokio::net::TcpStream;
use tokio::sync::Semaphore;
use tokio::sync::{broadcast, mpsc};
use tokio::time::{self, Duration};
/// Responsible for gracefully shutting down the server instead of dying randomly
// Sounds very sci-fi ;)
pub struct Terminator {
@ -104,7 +103,7 @@ pub struct Listener {
}
/// A per-connection handler
struct CHandler {
pub struct CHandler {
db: CoreDB,
con: Connection,
climit: Arc<Semaphore>,

@ -38,6 +38,7 @@ mod kvengine;
mod protocol;
mod queryengine;
mod resp;
mod tls;
use coredb::CoreDB;
use dbnet::run;
use env_logger::*;

@ -0,0 +1,104 @@
/*
* Created on Fri Dec 18 2020
*
* This file is a part of TerrabaseDB
* Copyright (c) 2020, Sayan Nandan <ohsayan at outlook dot com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#[allow(dead_code)] // TODO: Don't keep clippy quiet!
// use crate::dbnet::CHandler;
// use crate::dbnet::Terminator;
// use crate::protocol::Connection;
use crate::CoreDB;
use libtdb::TResult;
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
// use std::net::ToSocketAddrs;
use std::sync::Arc;
// use tokio::io::{AsyncReadExt, AsyncWrite, AsyncWriteExt};
use tokio::net::TcpListener;
use tokio::net::TcpStream;
use tokio::sync::Semaphore;
use tokio::sync::{broadcast, mpsc};
use tokio::time::{self, Duration};
use tokio_openssl_vendored::SslStream;
pub struct SslListener {
/// An atomic reference to the coretable
db: CoreDB,
/// The incoming connection listener (binding)
listener: TcpListener,
/// The maximum number of connections
climit: Arc<Semaphore>,
/// The shutdown broadcaster
signal: broadcast::Sender<()>,
// When all `Sender`s are dropped - the `Receiver` gets a `None` value
// We send a clone of `terminate_tx` to each `CHandler`
terminate_tx: mpsc::Sender<()>,
terminate_rx: mpsc::Receiver<()>,
acceptor: Arc<SslAcceptor>,
}
impl SslListener {
pub fn new_pem_based_ssl_connection(
key_file: String,
chain_file: String,
db: CoreDB,
listener: TcpListener,
climit: Arc<Semaphore>,
signal: broadcast::Sender<()>,
terminate_tx: mpsc::Sender<()>,
terminate_rx: mpsc::Receiver<()>,
) -> TResult<Self> {
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls())?;
acceptor.set_private_key_file(key_file, SslFiletype::PEM)?;
acceptor.set_certificate_chain_file(chain_file)?;
let acceptor = Arc::new(acceptor.build());
Ok(SslListener {
db,
listener,
climit,
signal,
terminate_tx,
terminate_rx,
acceptor,
})
}
async fn accept(&mut self) -> TResult<SslStream<TcpStream>> {
let mut backoff = 1;
loop {
match self.listener.accept().await {
// We don't need the bindaddr
// We get the encrypted stream which we need to decrypt
// by using the acceptor
Ok((encrypted_stream, _)) => {
let decrypted_stream =
tokio_openssl_vendored::accept(&self.acceptor, encrypted_stream).await?;
return Ok(decrypted_stream);
}
Err(e) => {
if backoff > 64 {
// Too many retries, goodbye user
return Err(e.into());
}
}
}
// Wait for the `backoff` duration
time::sleep(Duration::from_secs(backoff)).await;
// We're using exponential backoff
backoff *= 2;
}
}
}
Loading…
Cancel
Save