Skip to content

Commit

Permalink
clean whole structure
Browse files Browse the repository at this point in the history
  • Loading branch information
soywod committed Dec 19, 2024
1 parent 04bb004 commit 851d378
Show file tree
Hide file tree
Showing 53 changed files with 980 additions and 663 deletions.
26 changes: 15 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,41 +35,45 @@ full = [
"secret-service-rust-crypto-std",
]

## Linux Secret service
#
secret-service = ["dep:num", "dep:once_cell", "dep:rand"]
# Linux Secret service
#
secret-service = []

# Linux Secret service,
# D-Bus implementation (requires libdbus)
#
secret-service-dbus = ["dep:dbus", "secret-service"]
secret-service-dbus-blocking = ["dep:dbus-codegen", "secret-service-dbus"]
secret-service-dbus-nonblock = ["dep:dbus-codegen", "dbus/futures", "secret-service-dbus"]
secret-service-dbus-std = ["secret-service-dbus-blocking"]
secret-service-dbus-tokio = ["dep:dbus-tokio", "dep:tokio", "secret-service-dbus-nonblock"]
#

# Linux Secret service,
# Z-Bus implementation (pure Rust)
#
secret-service-zbus = ["dep:serde", "dep:zbus", "serde?/derive", "secret-service"]
secret-service-zbus-std = ["zbus?/blocking-api", "secret-service-zbus"]
secret-service-zbus-async-std = ["dep:async-std", "secret-service-zbus"]
secret-service-zbus-tokio = ["dep:tokio", "secret-service-zbus"]

# Linux Secret service,
# Crypto provider (for encrypted sessions)
#
# Crypto (for encrypted sessions)
#
secret-service-openssl-std = ["dep:openssl"]
secret-service-rust-crypto-std = ["dep:aes", "dep:block-padding", "dep:cbc", "dep:hkdf", "dep:sha2"]
secret-service-crypto = ["dep:num", "dep:once_cell", "dep:rand"]
secret-service-openssl-std = ["dep:openssl", "secret-service-crypto"]
secret-service-rust-crypto-std = ["dep:aes", "dep:block-padding", "dep:cbc", "dep:hkdf", "dep:sha2", "secret-service-crypto"]

## MacOS/iOS Keychain
# MacOS/iOS Keychain
#
apple-keychain = []
apple-keychain-std = ["dep:security-framework", "apple-keychain"]

## Windows Credentials
# Windows Credentials
#
windows-credentials = []
windows-credentials-std = ["dep:byteorder", "dep:windows-sys", "windows-credentials"]

## Vendored
# Vendored
#
vendored = ["dbus?/vendored", "openssl?/vendored"]

Expand Down
10 changes: 5 additions & 5 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ fn main() {
feature = "secret-service-dbus-tokio"
))]
fn generate_dbus_apis() {
let _ = std::fs::remove_file("./src/secret_service/dbus/blocking/api.rs");
let _ = std::fs::remove_file("./src/secret_service/dbus/nonblock/api.rs");
let _ = std::fs::remove_file("./src/secret-service/dbus/blocking/api.rs");
let _ = std::fs::remove_file("./src/secret-service/dbus/nonblock/api.rs");

let xml = include_str!("./src/secret_service/dbus/api.xml");
let xml = include_str!("./src/secret-service/dbus/api.xml");

let mut opts = dbus_codegen::GenOpts::default();
opts.methodtype = None;
Expand All @@ -32,7 +32,7 @@ fn generate_dbus_blocking_api(xml: &str, opts: &mut dbus_codegen::GenOpts) {

let api = dbus_codegen::generate(xml, &opts).expect("should generate D-Bus blocking API");

std::fs::write("./src/secret_service/dbus/blocking/api.rs", api)
std::fs::write("./src/secret-service/dbus/blocking/api.rs", api)
.expect("should write generated Secret Service blocking API");
}

Expand All @@ -42,6 +42,6 @@ fn generate_dbus_nonblock_api(xml: &str, opts: &mut dbus_codegen::GenOpts) {

let api = dbus_codegen::generate(xml, &opts).expect("should generate D-Bus nonblock API");

std::fs::write("./src/secret_service/dbus/nonblock/api.rs", api)
std::fs::write("./src/secret-service/dbus/nonblock/api.rs", api)
.expect("should write generated Secret Service nonblock API");
}
37 changes: 19 additions & 18 deletions examples/std.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::env;

#[cfg(feature = "secret-service-crypto")]
use keyring::secret_service::crypto::sans_io::Algorithm;
#[cfg(feature = "secret-service")]
use keyring::secret_service::crypto::{Algorithm, Provider};
use keyring::secret_service::crypto::std::Crypto;
use keyring::std::Keyring;
use secrecy::ExposeSecret;

Expand All @@ -14,29 +16,28 @@ fn main() {
println!("using entry key: {key:?}");
println!("using entry value: {val:?}");

#[cfg(feature = "secret-service")]
#[cfg(feature = "secret-service-crypto")]
let ss_crypto_algorithm = match env::var("SS_CRYPTO_ALGORITHM") {
Ok(crypto) if crypto.trim().eq_ignore_ascii_case("plain") => Algorithm::Plain,
Ok(crypto) if crypto.trim().eq_ignore_ascii_case("dh") => Algorithm::Dh,
#[cfg(feature = "secret-service-crypto")]
Ok(crypto) if crypto.trim().eq_ignore_ascii_case("dh") => Algorithm::dh(),
_ => Algorithm::Plain,
};

#[cfg(feature = "secret-service")]
let ss_crypto_provider =
match env::var("SS_CRYPTO_PROVIDER").expect("missing SS_CRYPTO_PROVIDER env var") {
#[cfg(feature = "secret-service-openssl-std")]
var if var.trim().eq_ignore_ascii_case("openssl") => {
Provider::Openssl(ss_crypto_algorithm.clone())
}
#[cfg(feature = "secret-service-rust-crypto-std")]
var if var.trim().eq_ignore_ascii_case("rust-crypto") => {
Provider::RustCrypto(ss_crypto_algorithm.clone())
}
_ => panic!("cannot select std secret service crypto provider"),
};
let ss_crypto_provider = match env::var("SS_CRYPTO_PROVIDER") {
#[cfg(feature = "secret-service-openssl-std")]
Ok(var) if var.trim().eq_ignore_ascii_case("openssl") => {
Crypto::Openssl(ss_crypto_algorithm.clone())
}
#[cfg(feature = "secret-service-rust-crypto-std")]
Ok(var) if var.trim().eq_ignore_ascii_case("rust-crypto") => {
Crypto::RustCrypto(ss_crypto_algorithm.clone())
}
_ => Crypto::None,
};

let mut keyring = match env::var("KEYRING_PROVIDER").expect("missing KEYRING_PROVIDER env var")
{
let mut keyring = match env::var("KEYRING_PROVIDER").expect("missing KEYRING_PROVIDER") {
#[cfg(feature = "apple-keychain-std")]
var if var.trim().eq_ignore_ascii_case("apple-keychain") => {
println!("using Apple Keychain");
Expand All @@ -49,7 +50,7 @@ fn main() {
}
#[cfg(feature = "secret-service-dbus-std")]
var if var.trim().eq_ignore_ascii_case("dbus-secret-service") => {
println!("using Secret Service with D-Bus");
println!("using Secret Service: D-Bus");
println!("using Secret Service crypto provider: {ss_crypto_provider:?}");
Keyring::dbus_secret_service(&service, ss_crypto_provider).unwrap()
}
Expand Down
File renamed without changes.
15 changes: 8 additions & 7 deletions src/apple/std.rs → src/apple-keychain/std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use security_framework::{
};
use thiserror::Error;

use crate::{Flow, PutSecret, TakeSecret};
use crate::sans_io::{GetKey, PutSecret, TakeSecret};

#[derive(Debug, Error)]
pub enum Error {
Expand Down Expand Up @@ -33,22 +33,23 @@ impl IoConnector {
}
}

pub fn read(&self, flow: &mut impl PutSecret) -> Result<()> {
pub fn read<F: GetKey + PutSecret>(&self, flow: &mut F) -> Result<()> {
let secret =
get_generic_password(&self.service, flow.key()).map_err(Error::ReadSecretError)?;
get_generic_password(&self.service, flow.get_key()).map_err(Error::ReadSecretError)?;
flow.put_secret(secret.into());
Ok(())
}

pub fn write(&self, flow: &mut impl TakeSecret) -> Result<()> {
pub fn write<F: GetKey + TakeSecret>(&self, flow: &mut F) -> Result<()> {
let secret = flow.take_secret().ok_or(Error::WriteUndefinedSecretError)?;
let secret = secret.expose_secret();
set_generic_password(&self.service, flow.key(), secret).map_err(Error::WriteSecretError)?;
set_generic_password(&self.service, flow.get_key(), secret)
.map_err(Error::WriteSecretError)?;
Ok(())
}

pub fn delete(&self, flow: &mut impl Flow) -> Result<()> {
delete_generic_password(&self.service, flow.key()).map_err(Error::DeleteSecretError)?;
pub fn delete<F: GetKey>(&self, flow: &mut F) -> Result<()> {
delete_generic_password(&self.service, flow.get_key()).map_err(Error::DeleteSecretError)?;
Ok(())
}
}
6 changes: 0 additions & 6 deletions src/io.rs

This file was deleted.

13 changes: 7 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
#![doc = include_str!("../README.md")]

#[cfg(feature = "apple-keychain")]
pub mod apple;
pub mod flow;
pub mod io;
#[path = "apple-keychain/mod.rs"]
pub mod apple_keychain;
#[path = "sans-io.rs"]
pub mod sans_io;
#[cfg(feature = "secret-service")]
#[path = "secret-service/mod.rs"]
pub mod secret_service;
pub mod std;
#[cfg(feature = "windows-credentials")]
pub mod windows;

pub use self::{flow::*, io::*};
#[path = "windows-credentials/mod.rs"]
pub mod windows_credentials;
80 changes: 68 additions & 12 deletions src/flow.rs → src/sans-io.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,66 @@
use secrecy::SecretSlice;

use crate::Io;
//! # Sans I/O
//!
//! This module contains the state machine [`Flow`] and [`Io`]
//! definitions, as well as commonly-used flows definition like
//! [`ReadEntryFlow`], [`WriteEntryFlow`] and [`DeleteEntryFlow`].
pub trait Flow {
fn key(&self) -> &str;
}
use secrecy::SecretSlice;

/// The type of I/O generated by keyring [`Flow`] state machines.
///
/// This enum is the representation of I/Os that need to be performed
/// outside of [`Flow`]s.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Io {
Read,
Write,
Delete,
}

/// Trait used for building keyring-related sans I/O state machine
/// flows.
///
/// A flow is defined as an iterable state machine, where every
/// `.next()` call produces a potential [`Io`] that needs to be
/// performed outside of the flow, and makes the state go forward. No
/// [`Io`] produced means that the flow is terminated and does not
/// require any longer [`Io`] to be performed.
pub trait Flow: Iterator {}

/// Trait dedicated to flows that operate on specific keyring entries.
///
/// This trait make sure that the given flow knows how to retrieve the
/// key of the targeted keyring entry.
pub trait GetKey: Flow {
fn get_key(&self) -> &str;
}

/// Trait dedicated to flows that needs to take secrets.
///
/// This trait make sure that the given flow knows how to take a
/// secret from its inner state.
pub trait TakeSecret: Flow {
fn take_secret(&mut self) -> Option<SecretSlice<u8>>;
}

/// Trait dedicated to flows that needs to put secrets.
///
/// This trait make sure that the given flow knows how to put a secret
/// into its inner state.
pub trait PutSecret: Flow {
fn put_secret(&mut self, secret: SecretSlice<u8>);
}

/// [`Flow`] for reading a secret from a keyring entry.
#[derive(Clone, Debug)]
pub struct ReadEntryFlow {
key: String,
secret: Option<SecretSlice<u8>>,
}

impl ReadEntryFlow {
/// Creates a new [`ReadEntryFlow`] from the given keyring entry
/// key.
pub fn new(key: impl ToString) -> Self {
Self {
key: key.to_string(),
Expand All @@ -41,8 +81,10 @@ impl Iterator for ReadEntryFlow {
}
}

impl Flow for ReadEntryFlow {
fn key(&self) -> &str {
impl Flow for ReadEntryFlow {}

impl GetKey for ReadEntryFlow {
fn get_key(&self) -> &str {
self.key.as_str()
}
}
Expand All @@ -59,13 +101,16 @@ impl PutSecret for ReadEntryFlow {
}
}

/// [`Flow`] for writing a secret into a keyring entry.
#[derive(Clone, Debug)]
pub struct WriteEntryFlow {
key: String,
secret: Option<SecretSlice<u8>>,
}

impl WriteEntryFlow {
/// Creates a new [`WriteEntryFlow`] from the given keyring entry
/// key and the given secret.
pub fn new(key: impl ToString, secret: impl Into<SecretSlice<u8>>) -> Self {
Self {
key: key.to_string(),
Expand All @@ -86,8 +131,10 @@ impl Iterator for WriteEntryFlow {
}
}

impl Flow for WriteEntryFlow {
fn key(&self) -> &str {
impl Flow for WriteEntryFlow {}

impl GetKey for WriteEntryFlow {
fn get_key(&self) -> &str {
self.key.as_str()
}
}
Expand All @@ -98,6 +145,13 @@ impl TakeSecret for WriteEntryFlow {
}
}

impl PutSecret for WriteEntryFlow {
fn put_secret(&mut self, secret: SecretSlice<u8>) {
self.secret.replace(secret);
}
}

/// [`Flow`] for deleting a secret from a keyring entry.
#[derive(Clone, Debug)]
pub struct DeleteEntryFlow {
key: String,
Expand Down Expand Up @@ -126,8 +180,10 @@ impl Iterator for DeleteEntryFlow {
}
}

impl Flow for DeleteEntryFlow {
fn key(&self) -> &str {
impl Flow for DeleteEntryFlow {}

impl GetKey for DeleteEntryFlow {
fn get_key(&self) -> &str {
self.key.as_str()
}
}
8 changes: 8 additions & 0 deletions src/secret-service/crypto/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#[cfg(feature = "secret-service-openssl-std")]
pub mod openssl;
#[cfg(feature = "secret-service-rust-crypto-std")]
#[path = "rust-crypto/mod.rs"]
pub mod rust_crypto;
#[path = "sans-io/mod.rs"]
pub mod sans_io;
pub mod std;
File renamed without changes.
Loading

0 comments on commit 851d378

Please sign in to comment.