diff --git a/.gitignore b/.gitignore index ea7757d..e51fd85 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -/target +**target/ **/*.rs.bk *.cbor *.yaml \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index b6a94e4..fbdfb51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,13 +103,16 @@ dependencies = [ "seckey 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_cbor 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "sodiumoxide 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "coffer-companion" version = "0.2.0" dependencies = [ + "coffer-common 0.1.0", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -127,13 +130,14 @@ dependencies = [ "coffer-common 0.1.0", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_cbor 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "sodiumoxide 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -354,6 +358,11 @@ dependencies = [ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "itoa" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -596,6 +605,11 @@ name = "rle-decode-fast" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ryu" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "seckey" version = "0.9.1" @@ -632,6 +646,16 @@ dependencies = [ "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_json" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde_yaml" version = "0.8.11" @@ -756,7 +780,7 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -773,19 +797,27 @@ dependencies = [ "pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-macros 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-macros 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-macros" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "toml" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-segmentation" version = "1.6.0" @@ -926,6 +958,7 @@ dependencies = [ "checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" @@ -956,10 +989,12 @@ dependencies = [ "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac" +"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum seckey 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c819d0a699db7622e4ee55a651f992242f754481f97de3024dc548adcce13237" "checksum serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4b39bd9b0b087684013a792c59e3e07a46a01d2322518d8a1104641a0b1be0" "checksum serde_cbor 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7081ed758ec726a6ed8ee7e92f5d3f6e6f8c3901b1f972e3a4a2f2599fad14f" "checksum serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "ca13fc1a832f793322228923fbb3aba9f3f44444898f835d31ad1b74fa0a2bf8" +"checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" @@ -974,8 +1009,9 @@ dependencies = [ "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum tokio 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1bef565a52394086ecac0a6fa3b8ace4cb3a138ee1d96bd2b93283b56824e3" -"checksum tokio-macros 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7de6c21a09bab0ce34614bb1071403ad9996db62715eb61e63be5d82f91342bc" +"checksum tokio 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "a9d5acfe1b1130d50ac2286a2f1f8cf49309680366ceb7609ce369b75c9058d4" +"checksum tokio-macros 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "50a61f268a3db2acee8dcab514efc813dc6dbe8a00e86076f935f94304b59a7a" +"checksum toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01d1404644c8b12b16bfcffa4322403a91a451584daaaa7c28d3152e6cbc98cf" "checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" diff --git a/coffer-common/Cargo.toml b/coffer-common/Cargo.toml index edc1529..82f58d8 100644 --- a/coffer-common/Cargo.toml +++ b/coffer-common/Cargo.toml @@ -12,6 +12,8 @@ log = "^0.4" env_logger = "^0.7" serde = { version = "^1.0", features = ["derive"]} serde_cbor = "^0.10" +serde_json = "^1.0" +toml = "^0.5" quick-error = "^1.2" # Key management/Cryptography sodiumoxide = "^0.2" diff --git a/coffer-common/src/certificate.rs b/coffer-common/src/certificate.rs index 5dd0f3a..b453786 100644 --- a/coffer-common/src/certificate.rs +++ b/coffer-common/src/certificate.rs @@ -40,6 +40,9 @@ pub struct Certificate { inner: SecKey } +unsafe impl Send for Certificate {} +unsafe impl Sync for Certificate {} + #[derive(Serialize, Deserialize)] struct CertificateInner { public_key: box_::PublicKey, @@ -73,21 +76,19 @@ impl Certificate { Ok(Certificate{inner}) } + pub fn to_cbor(&self) -> Result, CertificateError> { + let inner_cert = &*self.inner.read(); + let cbor = serde_cbor::to_vec(inner_cert)?; + Ok(cbor) + } + pub fn open(&self, c: &[u8]) -> Result, CertificateError> { let pk = &self.inner.read().public_key; let sk = &self.inner.read().private_key; - debug!{"Opening sealed box"}; sealedbox::open(c, pk, sk) .map_err(|_| CertificateError::Crypto) } - - fn seal(&self, m: &[u8]) -> Vec { - let pk = &self.inner.read().public_key; - - debug!{"Sealing box"} - sealedbox::seal(m, pk) - } } impl > From for Certificate { diff --git a/coffer-common/src/coffer.rs b/coffer-common/src/coffer.rs index a3c92ba..1dedeb6 100644 --- a/coffer-common/src/coffer.rs +++ b/coffer-common/src/coffer.rs @@ -8,13 +8,20 @@ use quick_error::quick_error; quick_error! { #[derive(Debug)] pub enum CofferError { - Coffer + Msg(err: &'static str) { + from(err) + display("{}", err) + } + Other(err: Box) { + cause(&**err) + } } } pub type CofferResult = Result; /// Values supported by a `Coffer` +#[derive(Clone, Debug)] pub enum CofferValue { /// A UTF-8 encoded string String(String), @@ -25,22 +32,33 @@ pub enum CofferValue { } /// A path to a value +#[derive(Clone, Eq, PartialEq, Hash, Debug)] pub struct CofferPath(Vec); /// Interface for interacting with a `Coffer` pub trait Coffer { /// Put `value` at `path`. Errors if there is already a value at `path`. - fn put(path: CofferPath, value: CofferValue) -> CofferResult<()>; + fn put(&mut self, path: CofferPath, value: CofferValue) -> CofferResult<()>; + /// Push `value` to `path`. Replaces existing values silently. - fn push(path: CofferPath, value: CofferValue); + fn push(&mut self, path: CofferPath, value: CofferValue); + /// Retrieve `value` at path. Errors if there is no `value` at path. - fn get(path: CofferPath) -> CofferResult; + fn get(&self, path: CofferPath) -> CofferResult; } -impl From<&[T]> for CofferPath +impl From> for CofferPath where T: AsRef { - fn from(val: &[T]) -> Self { + fn from(val: Vec) -> Self { + CofferPath::from(&val) + } +} + +impl From<&Vec> for CofferPath +where T: AsRef +{ + fn from(val: &Vec) -> Self { let col = val.iter().map(|p| {(*p).as_ref().to_owned()}).collect(); CofferPath(col) } diff --git a/coffer-common/src/keyring.rs b/coffer-common/src/keyring.rs new file mode 100644 index 0000000..1c4722a --- /dev/null +++ b/coffer-common/src/keyring.rs @@ -0,0 +1,62 @@ +#[allow(unused_imports)] +use log::{debug, error, info, trace, warn}; + +use std::collections::HashMap; + +use quick_error::quick_error; +use sodiumoxide::crypto::box_; +use sodiumoxide::crypto::sealedbox; + +use crate::certificate::{Certificate, CertificateError}; + +quick_error! { + #[derive(Debug)] + pub enum KeyringError { + UnkownClientKey + InvalidClientKey + Certificate(err: CertificateError) { + from() + } + Msg(err: &'static str) { + from(err) + display("{}", err) + } + Other(err: Box) { + cause(&**err) + } + } +} + +pub struct Keyring { + certificate: Certificate, + known_keys: HashMap, box_::PublicKey> +} + +impl Keyring { + pub fn new(certificate: Certificate) -> Keyring { + Keyring { + certificate: certificate, + known_keys: HashMap::new() + } + } + + pub fn add_known_key(&mut self, key: &[u8]) -> Result<(), KeyringError> { + let public_key = box_::PublicKey::from_slice(key) + .ok_or(KeyringError::InvalidClientKey)?; + + self.known_keys.insert(Vec::from(key), public_key); + Ok(()) + } + + pub fn open(&self, message: &[u8]) -> Result, KeyringError> { + self.certificate.open(message) + .map_err(|e| KeyringError::from(e)) + } + + pub fn seal(&self, client: &[u8], message: &[u8]) -> Result, KeyringError> { + let client_key = self.known_keys.get(client) + .ok_or(KeyringError::UnkownClientKey)?; + + Ok(sealedbox::seal(message, client_key)) + } +} diff --git a/coffer-common/src/lib.rs b/coffer-common/src/lib.rs index 968ef2c..36b33b7 100644 --- a/coffer-common/src/lib.rs +++ b/coffer-common/src/lib.rs @@ -5,6 +5,7 @@ use log::{debug, error, info, trace, warn}; pub mod certificate; pub mod coffer; +pub mod keyring; #[cfg(test)] mod tests { diff --git a/coffer-companion/Cargo.toml b/coffer-companion/Cargo.toml index fcb1d2c..1830a46 100644 --- a/coffer-companion/Cargo.toml +++ b/coffer-companion/Cargo.toml @@ -18,3 +18,5 @@ sodiumoxide = "0.2.5" serde = { version = "1.0", features = ["derive"]} serde_cbor = "0.10.2" serde_yaml = "0.8" + +coffer-common = { path = "../coffer-common" } \ No newline at end of file diff --git a/coffer-companion/src/encrypt.rs b/coffer-companion/src/encrypt.rs index c4388a7..e69de29 100644 --- a/coffer-companion/src/encrypt.rs +++ b/coffer-companion/src/encrypt.rs @@ -1,26 +0,0 @@ -use sodiumoxide::crypto::sealedbox; -use std::collections::HashMap; -use std::fs::File; -use std::io::{Write}; -use std::path::PathBuf; - -use crate::generate::MasterKey; - -type Secrets = HashMap; - -pub fn generate_encrypted_secrets(yaml: PathBuf, out: PathBuf, masterkey: PathBuf) { - let reader = File::open(&yaml) - .expect(&format!{"Could not read file {}", masterkey.display()}); - - let secrets: Secrets = serde_yaml::from_reader(reader) - .expect(&format!{"Could not deserialize secrets from {}", &yaml.display()}); - - let masterkey: MasterKey = (&masterkey).into(); - - let secrets_bin = serde_cbor::to_vec(&secrets).unwrap(); - let sealed_secrets_bin = sealedbox::seal(&secrets_bin, &masterkey.public_key); - - File::create(&out) - .and_then(|mut f| f.write(&sealed_secrets_bin)) - .expect(&format!{"Could not create out file {}", &out.display()}); -} diff --git a/coffer-companion/src/generate.rs b/coffer-companion/src/generate.rs index 529a043..0501aaf 100644 --- a/coffer-companion/src/generate.rs +++ b/coffer-companion/src/generate.rs @@ -1,33 +1,17 @@ -use sodiumoxide::crypto::box_; -use serde::{Deserialize, Serialize}; +use coffer_common::certificate::Certificate; + use std::path::PathBuf; use std::fs::File; - -#[derive(Debug, Serialize, Deserialize)] -pub struct MasterKey { - pub public_key: box_::PublicKey, - secret_key: box_::SecretKey, -} +use std::io::Write; pub fn generate_key(out: PathBuf) { - let keypair = box_::gen_keypair(); - let masterkey: MasterKey = MasterKey { - public_key: keypair.0, - secret_key: keypair.1, - }; + let certificate = Certificate::new().unwrap(); - let writer = File::create(&out) + let cert = certificate.to_cbor().unwrap(); + + let mut writer = File::create(&out) .expect(&format!{"Could not create out file {}", &out.display()}); - serde_cbor::to_writer(writer, &masterkey) - .expect(&format!{"Couldn't deserialize to key file {}", &out.display()}); -} + writer.write_all(&cert); -impl From<&PathBuf> for MasterKey { - fn from(masterkey: &PathBuf) -> Self { - let reader = File::open(masterkey) - .expect(&format!{"Could not read file {}", masterkey.display()}); - - serde_cbor::from_reader(reader).unwrap() - } } diff --git a/coffer-companion/src/main.rs b/coffer-companion/src/main.rs index d38c3c4..404bc58 100644 --- a/coffer-companion/src/main.rs +++ b/coffer-companion/src/main.rs @@ -25,6 +25,6 @@ fn main() { match args { Args::Generate {out} => generate::generate_key(out), - Args::Encrypt {yaml, out, masterkey} => encrypt::generate_encrypted_secrets(yaml, out, masterkey) + Args::Encrypt {yaml, out, masterkey} => {} } } diff --git a/coffer-server/Cargo.toml b/coffer-server/Cargo.toml index a2f765b..ed334d6 100644 --- a/coffer-server/Cargo.toml +++ b/coffer-server/Cargo.toml @@ -10,10 +10,12 @@ log = "^0.4" env_logger = "^0.7" structopt = "^0.3" quick-error = "^1.2" +lazy_static = "^1.4" + # Key management/Cryptography sodiumoxide = "^0.2" # Communication -tokio = { version="^0.2", features = ["full"]} +tokio = { version="^0.2.8", features = ["full"]} serde = { version = "^1.0", features = ["derive"]} serde_cbor = "^0.10.2" futures = { version = "0.3.1", features = ["thread-pool"]} diff --git a/coffer-server/src/coffer/coffer.rs b/coffer-server/src/coffer/coffer.rs deleted file mode 100644 index 79a9300..0000000 --- a/coffer-server/src/coffer/coffer.rs +++ /dev/null @@ -1,20 +0,0 @@ -#[allow(unused_imports)] -use log::{debug, error, info, trace, warn}; - -use coffer_common::certificate::Certificate; - -pub struct Coffer { - certificate: Certificate, -} - -impl Coffer { - /// Create a new, empty `Coffer` with a generated certificate - pub fn new() -> Coffer { - Coffer {certificate: Certificate::new()} - } - - /// Create a new `Coffer` with certificate - pub fn new_with_certificate (certificate: Certificate) { - Coffer {certificate.into()} - } -} diff --git a/coffer-server/src/coffer/keyring.rs b/coffer-server/src/coffer/keyring.rs deleted file mode 100644 index f10de7a..0000000 --- a/coffer-server/src/coffer/keyring.rs +++ /dev/null @@ -1,81 +0,0 @@ -#[allow(unused_imports)] -use log::{debug, error, info, trace, warn}; -use quick_error::quick_error; - -use std::collections::HashMap; -use std::fs::File; -use std::path::PathBuf; - -use serde::{Deserialize, Serialize}; - -use sodiumoxide::crypto::sealedbox; -use sodiumoxide::crypto::box_; - -quick_error! { - #[derive(Debug)] - pub enum KeyringError { - Io(err: std::io::Error) { - from() - } - Cbor(err: serde_cbor::Error) { - from() - } - Crypto - } -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct MasterKey { - public_key: box_::PublicKey, - secret_key: box_::SecretKey, -} - -impl MasterKey { - pub fn decrypt(&self, c: &[u8]) -> Result, KeyringError> { - sealedbox::open(c, &self.public_key, &self.secret_key) - .map_err(|_| KeyringError::Crypto) - } - - fn encrypt(&self, m: &[u8]) -> Vec { - sealedbox::seal(m, &self.public_key) - } -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct ClientKey { - id: String, - public_key: box_::PublicKey, -} - -pub struct Keyring { - pub master: MasterKey, - pub clients: HashMap, -} - -impl Keyring { - pub fn new_from_path(path: &PathBuf) -> Result { - let keyring = Keyring { - master: key_from_path(path)?, - clients: HashMap::new(), - }; - - Ok(keyring) - } - - pub fn add_key_from_path(&mut self, path: &PathBuf, keep: bool) -> Result<(), KeyringError> { - let client_key: ClientKey = key_from_path(path)?; - self.clients.insert(client_key.id.clone(), client_key); - - Ok(()) - } -} - -fn key_from_path(path: &PathBuf) -> Result -where T: serde::de::DeserializeOwned -{ - - let mk_file = File::open(path)?; - let key = serde_cbor::from_reader(mk_file)?; - - Ok(key) -} diff --git a/coffer-server/src/coffer/mod.rs b/coffer-server/src/coffer/mod.rs deleted file mode 100644 index 4b17284..0000000 --- a/coffer-server/src/coffer/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -#[allow(unused_imports)] -use log::{debug, error, info, trace, warn}; -use quick_error::quick_error; - -use std::path::PathBuf; -use std::fs::File; -use std::io::Read; -use std::collections::HashMap; - -// do not provide a path to keyring through coffer module. keyring is hence -// effectively private outside coffer -mod keyring; -use keyring::Keyring; - -quick_error! { - #[derive(Debug)] - pub enum CofferError { - Keyring(err: keyring::KeyringError) { - from()} - Io(err: std::io::Error) { - from() - } - Cbor(err: serde_cbor::Error) { - from() - } - Coffer(err: &'static str) { - from() - } - } -} - -type Result = std::result::Result; -type Secrets = HashMap; // move this to a module if it gathers crust - diff --git a/coffer-server/src/coffer_map.rs b/coffer-server/src/coffer_map.rs new file mode 100644 index 0000000..cd07a28 --- /dev/null +++ b/coffer-server/src/coffer_map.rs @@ -0,0 +1,52 @@ +//! A simple, thread-safe coffer implementation backed by a hash map + +#[allow(unused_imports)] +use log::{debug, error, info, trace, warn}; + +use std::sync::RwLock; +use std::collections::HashMap; + +use coffer_common::coffer::*; + +pub struct CofferMap { + coffer: RwLock> +} + +impl CofferMap { + pub fn new() -> CofferMap { + CofferMap { + coffer: RwLock::new(HashMap::new()) + } + } +} + +impl Coffer for CofferMap { + fn put(&mut self, path: CofferPath, value: CofferValue) -> CofferResult<()> { + let mut lock = self.coffer.write().unwrap(); + + match (*lock).contains_key(&path) { + true => Err(CofferError::Msg("test")), + false => {(*lock).insert(path, value); Ok(())} + } + } + + fn push(&mut self, path: CofferPath, value: CofferValue) { + let mut lock = self.coffer.write().unwrap(); + + (*lock).insert(path, value); + } + + fn get(&self, path: CofferPath) -> CofferResult { + let lock = self.coffer.read().unwrap(); + + (*lock).get(&path) + .and_then(|v| Some(v.clone())) + .ok_or(CofferError::Msg("Key not found")) + } +} + +impl Default for CofferMap { + fn default() -> Self { + CofferMap::new() + } +} diff --git a/coffer-server/src/comm.rs b/coffer-server/src/comm.rs deleted file mode 100644 index 509c286..0000000 --- a/coffer-server/src/comm.rs +++ /dev/null @@ -1,62 +0,0 @@ -#[allow(unused_imports)] -use log::{debug, error, info, trace, warn}; - -use std::net::{TcpListener, SocketAddr, TcpStream}; -use std::sync::Arc; -use std::io::{Write}; -use std::io::Read; -use futures::executor::ThreadPool; - -use crate::coffer::Coffer; - -pub struct Channel { - pub executor: ThreadPool, - pub address: SocketAddr, - pub coffer: Arc -} - -impl Channel { - pub fn listen(self) { - - let listener:TcpListener = TcpListener::bind(self.address).unwrap(); - - listener.incoming().for_each(|inc| { - match inc { - Ok(tcp_stream) => self.executor.spawn_ok(handler(tcp_stream, self.coffer.clone())), - Err(e) => error!{"Failed binding incoming connection {}", e} - } - }) - } -} - -async fn handler(mut stream: TcpStream, coffer: Arc) { - let mut peek_buf = [0x00; 1]; - - while stream.peek(&mut peek_buf).unwrap() != 0 { - let mut len_buffer = [0x00; std::mem::size_of::()]; - stream.read_exact(&mut len_buffer); - let len = usize::from_be_bytes(len_buffer) as u64; - debug!{"Length {}", len} - - let mut buf: Vec = Vec::with_capacity(len as usize); - let mut handle = (&stream).take(len); - handle.read_to_end(&mut buf); - debug!{"Read vec {:?}", buf}; - - let res: Result = serde_cbor::from_slice(&buf); - - match res { - Ok(request) => { - if let Ok(secret) = coffer.get_secret(&request) { - writeln!(stream, "{}", secret) - .unwrap_or_else(|err| {error!{"Could not write key response to stream {}", err}}); - debug!{"Wrote {:?}", secret} - } else { - writeln!(stream, "") - .unwrap_or_else(|err| {error!{"Could not write key response to stream {}", err}}) - } - }, - Err(e) => error!{"Could not parse secret request: {}", e} - }; - } -} diff --git a/coffer-server/src/main.rs b/coffer-server/src/main.rs index 4f0b7f8..3862793 100644 --- a/coffer-server/src/main.rs +++ b/coffer-server/src/main.rs @@ -3,20 +3,18 @@ use log::{debug, error, info, trace, warn}; use env_logger; -use std::convert::TryInto; use std::path::PathBuf; use structopt::StructOpt; -use std::net::IpAddr; use std::net::SocketAddr; -use std::sync::Arc; -use tokio::prelude::*; +use coffer_common::certificate::Certificate; +use coffer_common::keyring::Keyring; -mod coffer; mod server; -mod comm; +mod coffer_map; -use comm::Channel; +use server::ServerBuilder; +use coffer_map::CofferMap; #[derive(StructOpt, Debug)] struct Args { @@ -29,13 +27,9 @@ struct Args { #[structopt(short, long, parse(from_os_str), env = "COFFER_SERVER_SECRETS", hide_env_values = true)] secrets: Option, - /// Port the coffer server listens on - #[structopt(short, long, env = "COFFER_SERVER_PORT", default_value = "9187")] - port: u16, - - /// Address coffer server should bind to + /// Address the coffer server should bind to #[structopt(short, long, parse(try_from_str), env = "COFFER_SERVER_ADDRESS", default_value = "127.0.0.1:9187")] - ip: SocketAddr, + address: SocketAddr, } #[tokio::main] @@ -45,9 +39,13 @@ async fn main() { _print_banner(); - info!{"Filling coffer"} - let coffer = coffer::Coffer::new_from_path_encrypted(&args.master, &args.secrets) - .expect("Could not fill coffer"); + let server = ServerBuilder::new() + .with_keyring(args.certificate.and_then(|cert_path| Some(Keyring::new(Certificate::from(cert_path))))) + .with_coffer(Some(CofferMap::new())) + .build() + .expect("Couldn't build server"); + + server.run(args.address).await; } fn _print_banner() { diff --git a/coffer-server/src/server.rs b/coffer-server/src/server.rs new file mode 100644 index 0000000..f326004 --- /dev/null +++ b/coffer-server/src/server.rs @@ -0,0 +1,127 @@ +#[allow(unused_imports)] +use log::{debug, error, info, trace, warn}; + +use quick_error::quick_error; + +use tokio::net::{TcpListener, TcpStream}; +use tokio::stream::StreamExt; +use tokio::sync::RwLock; + +use std::net::{ToSocketAddrs, SocketAddr}; +use std::sync::Arc; + +use coffer_common::keyring::Keyring; +use coffer_common::coffer::Coffer; +use coffer_common::certificate::{Certificate, CertificateError}; + +quick_error! { + #[derive(Debug)] + pub enum ServerError { + Cert(err: CertificateError) { + from() + } + Msg(err: &'static str) { + from(err) + display("{}", err) + } + Other(err: Box) { + cause(&**err) + } + } +} + +pub struct Server +where C: Coffer +{ + keyring: Arc>, + coffer: Arc> +} + +impl Server +where C: Coffer + Send + Sync + 'static +{ + pub async fn run(self, addr: T) + where T: ToSocketAddrs + { + debug!{"Building socket"} + let socket: SocketAddr = addr + .to_socket_addrs() + .expect("Could not convert to socket") + .next() + .expect("No socket could be built"); + + debug!{"Binding to socket {:?}", socket} + let mut listener = TcpListener::bind(socket).await + .expect(format!{"Could not bind to socket {}", socket}.as_str()); + + let server = async move { + let mut incoming = listener.incoming(); + + debug!{"Starting connection loop"} + while let Some(connection) = incoming.next().await { + debug!{"New incoming connection"} + match connection { + Ok(mut tcp_stream) => { + debug!{"Connection ok"} + debug!{"Spawning off connection handler"} + + let keyring = self.keyring.clone(); + let coffer = self.coffer.clone(); + tokio::spawn(Self::handle_connection(keyring, coffer, tcp_stream)); + } + Err(err) => error!{"Connection could not be established {}", err} + } + debug!{"Waiting for new connections"} + } + }; + + server.await + } + + async fn handle_connection(keyring: Arc>, + coffer: Arc>, + mut tcp_stream: TcpStream) + { + let (reader, mut writer) = tcp_stream.split(); + } +} + +pub struct ServerBuilder +where C: Coffer +{ + keyring: Option, + coffer: Option +} + +impl <'a, C> ServerBuilder +where C: Coffer + Default +{ + pub fn new() -> ServerBuilder { + ServerBuilder { + keyring: None, + coffer: None + } + } + + pub fn with_keyring(mut self, keyring: Option) -> ServerBuilder { + self.keyring = keyring; + self + } + + pub fn with_coffer(mut self, coffer: Option) -> ServerBuilder { + self.coffer = coffer; + self + } + + pub fn build(self) -> Result, ServerError> { + let keyring = match self.keyring { + Some(k) => Arc::new(RwLock::new(k)), + None => {let cert = Certificate::new()?; + Arc::new(RwLock::new(Keyring::new(cert)))} + }; + + let coffer = Arc::new(RwLock::new(self.coffer.unwrap_or_else(|| { C::default() } ))); + + Ok(Server {keyring, coffer}) + } +} diff --git a/coffer-server/src/server/mod.rs b/coffer-server/src/server/mod.rs deleted file mode 100644 index 0a2d0bc..0000000 --- a/coffer-server/src/server/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Public APIs for `coffer-server` - -use std::net::ToSocketAddrs; - -use tokio::prelude::*; -use tokio::net::TcpListener; - -async fn run_server(sock_addrs: T) { - let addr = sock_addrs.to_socket_addrs().unwrap().next().unwrap(); - let listener = TcpListener::bind(addr); -}