Skip to content

Commit

Permalink
Merge branch 'master' into xla/rfc-p2p-node
Browse files Browse the repository at this point in the history
  • Loading branch information
xla committed Sep 2, 2021
2 parents ca18311 + e6f7361 commit 7543b9a
Show file tree
Hide file tree
Showing 209 changed files with 4,729 additions and 1,074 deletions.
2 changes: 1 addition & 1 deletion .rustfmt.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ force_explicit_abi = true

license_template_path = ".license-header-check"

ignore = ["librad/src/internal/canonical/formatter.rs"]
ignore = ["link-canonical/src/formatter.rs"]
13 changes: 11 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
[workspace]
members = [
"clib",
"copy",
"daemon",
"data",
"e2e",
"git-ext",
"git-helpers",
"git-trailers",
"librad",
"link-canonical",
"link-crypto",
"link-git-protocol",
"link-identities",
"macros",
"seed",
"std-ext",
Expand All @@ -15,9 +21,12 @@ members = [

[patch.crates-io.git2]
git = "https://github.com/radicle-dev/git2-rs.git"
rev = "9f4101f632d33fdba72b2fe0614a790259c1f6f3"
rev = "ae027b9e7b125f56397bbb7d8652b3427deeede6"

[patch.crates-io.libgit2-sys]
git = "https://github.com/radicle-dev/git2-rs.git"
rev = "9f4101f632d33fdba72b2fe0614a790259c1f6f3"
rev = "ae027b9e7b125f56397bbb7d8652b3427deeede6"

[patch.crates-io.thrussh-encoding]
git = "https://github.com/FintanH/thrussh.git"
branch = "generic-agent"
30 changes: 30 additions & 0 deletions clib/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[package]
name = "link-clib"
version = "0.1.0"
authors = ["The Radicle Team <[email protected]>"]
edition = "2018"
license = "GPL-3.0-or-later"

[lib]
doctest = true
test = false

[features]
unsafe = []

[dependencies]
serde_json = "1.0"
serde = "1.0"
thiserror = "1.0"

[dependencies.librad]
path = "../librad"

[dependencies.minicbor]
version = "0.9.1"
features = ["std"]

[dependencies.thrussh-agent]
git = "https://github.com/FintanH/thrussh"
branch = "generic-agent"
default-features = false
12 changes: 12 additions & 0 deletions clib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# CLIB

When a CLI needs a LIB, one gets a CLIB.

This package provides the common data types and functions that can be
used across the different set of CLI packages.

* `clib::keys` - common functions for setting up of and retrival from the secret key
storage.
* `clib::ser` - serialization formats required for CLI output.
* `clib::storage` - common functions for setting up read-only and
read-write storage.
104 changes: 104 additions & 0 deletions clib/src/keys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright © 2021 The Radicle Link Contributors
//
// This file is part of radicle-link, distributed under the GPLv3 with Radicle
// Linking Exception. For full terms see the included LICENSE file.

use std::sync::Arc;

use thiserror::Error;
use thrussh_agent::client::ClientStream;

use librad::{
crypto::{
keystore::{
crypto::{Crypto, KdfParams, Pwhash, SecretBoxError},
file,
pinentry::Prompt,
sign::ssh::{self, SshAgent},
FileStorage,
Keystore as _,
},
BoxedSigner,
IntoSecretKeyError,
SomeSigner,
},
git::storage::ReadOnly,
profile::Profile,
PublicKey,
SecretKey,
};

/// The filename for storing the secret key.
pub const LIBRAD_KEY_FILE: &str = "librad.key";

#[derive(Debug, Error)]
pub enum Error {
#[error(transparent)]
File(#[from] file::Error<SecretBoxError<std::io::Error>, IntoSecretKeyError>),
#[error(transparent)]
SshConnect(#[from] ssh::error::Connect),
}

/// Create a [`Prompt`] for unlocking the key storage.
pub fn prompt() -> Pwhash<Prompt<'static>> {
let prompt = Prompt::new("please enter your passphrase: ");
Pwhash::new(prompt, KdfParams::recommended())
}

/// Create a [`Prompt`] for unlocking the key storage.
///
/// # Safety
///
/// The encryption of the file store will be weak but fast. So this not intended
/// for production use.
#[cfg(feature = "unsafe")]
pub fn unsafe_prompt() -> Pwhash<Prompt<'static>> {
use librad::crypto::keystore::crypto::KDF_PARAMS_TEST;

let prompt = Prompt::new("please enter your passphrase: ");
Pwhash::new(prompt, *KDF_PARAMS_TEST)
}

/// Create a [`FileStorage`] for [`SecretKey`]s.
pub fn file_storage<C>(profile: &Profile, crypto: C) -> FileStorage<C, PublicKey, SecretKey, ()>
where
C: Crypto,
{
FileStorage::new(&profile.paths().keys_dir().join(LIBRAD_KEY_FILE), crypto)
}

/// Get the signer from the file store, decrypting the secret key by asking for
/// a passphrase via a prompt.
pub fn signer_prompt(profile: &Profile) -> Result<BoxedSigner, Error> {
let store = file_storage(profile, prompt());
let key = store.get_key()?.secret_key;
Ok(key.into())
}

pub async fn signer_ssh<S>(profile: &Profile) -> Result<BoxedSigner, Error>
where
S: ClientStream + Unpin + 'static,
{
let storage = ReadOnly::open(profile.paths()).unwrap();
let peer_id = storage.peer_id();
let agent = SshAgent::new((**peer_id).into());
let signer = agent.connect::<S>().await?;
Ok(SomeSigner {
signer: Arc::new(signer),
}
.into())
}

/// Get the signer from the file store, decrypting the secret key by asking for
/// a passphrase via a prompt.
///
/// # Safety
///
/// The encryption of the file store will be weak but fast. So this not intended
/// for production use.
#[cfg(feature = "unsafe")]
pub fn unsafe_signer_prompt(profile: &Profile) -> Result<BoxedSigner, Error> {
let store = file_storage(profile, unsafe_prompt());
let key = store.get_key()?.secret_key;
Ok(key.into())
}
6 changes: 4 additions & 2 deletions test/src/librad/internal.rs → clib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright © 2019-2020 The Radicle Foundation <[email protected]>
// Copyright © 2021 The Radicle Link Contributors
//
// This file is part of radicle-link, distributed under the GPLv3 with Radicle
// Linking Exception. For full terms see the included LICENSE file.

pub mod canonical;
pub mod keys;
pub mod ser;
pub mod storage;
66 changes: 66 additions & 0 deletions clib/src/ser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright © 2021 The Radicle Link Contributors
//
// This file is part of radicle-link, distributed under the GPLv3 with Radicle
// Linking Exception. For full terms see the included LICENSE file.

use std::{fmt, str::FromStr};

use thiserror::Error;

use minicbor::Encode;
use serde::Serialize;

#[derive(Debug, Error)]
pub enum Error {
#[error(transparent)]
Json(#[from] serde_json::Error),
#[error(transparent)]
Cbor(#[from] minicbor::encode::Error<std::io::Error>),
#[error(transparent)]
Utf8(#[from] std::string::FromUtf8Error),
}

/// An enumeration of the formats the CLI can output. Note that since any of
/// these formats can be used, the corresponding data type needs to implement
/// the required traits.
#[derive(Debug, Clone, Copy)]
pub enum Format {
/// Requires the data type to implement [`Serialize`].
Json,
/// Requires the data type to implement [`Encode`].
Cbor,
}

impl fmt::Display for Format {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Json => write!(f, "json"),
Self::Cbor => write!(f, "cbor"),
}
}
}

impl FromStr for Format {
type Err = &'static str;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"json" => Ok(Self::Json),
"cbor" => Ok(Self::Cbor),
_ => Err("unknown format type"),
}
}
}

impl Format {
/// Serialize the `val` to a `String`.
pub fn format<T>(&self, val: &T) -> Result<String, Error>
where
T: Serialize + Encode,
{
match self {
Self::Json => Ok(serde_json::to_string(val)?),
Self::Cbor => Ok(String::from_utf8(minicbor::to_vec(val)?)?),
}
}
}
63 changes: 63 additions & 0 deletions clib/src/storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright © 2021 The Radicle Link Contributors
//
// This file is part of radicle-link, distributed under the GPLv3 with Radicle
// Linking Exception. For full terms see the included LICENSE file.

use thiserror::Error;

use librad::{
crypto::BoxedSigner,
git::storage::{error, read, ReadOnly, Storage},
profile::Profile,
};

use super::keys;

#[derive(Debug, Error)]
pub enum Error {
#[error(transparent)]
ReadInit(#[from] read::error::Init),
#[error(transparent)]
ReadWriteInit(#[from] error::Init),
#[error(transparent)]
Keys(#[from] super::keys::Error),
}

/// Intialise a [`ReadOnly`] storage.
pub fn read_only(profile: &Profile) -> Result<ReadOnly, Error> {
let paths = profile.paths();
Ok(ReadOnly::open(paths)?)
}

pub mod prompt {
use super::*;

/// Initialise [`Storage`].
///
/// The decryption will happen by prompting the person for their passphrase
/// at the command line.
pub fn storage(profile: &Profile) -> Result<(BoxedSigner, Storage), Error> {
let paths = profile.paths();
let signer = keys::signer_prompt(profile)?;
Ok((signer.clone(), Storage::open(paths, signer)?))
}
}

pub mod ssh {
use thrussh_agent::client::ClientStream;

use super::*;

/// Initialise [`Storage`].
///
/// The signing key will be retrieved from the ssh-agent. If the key was not
/// added to the agent then this result in an error.
pub async fn storage<S>(profile: &Profile) -> Result<(BoxedSigner, Storage), Error>
where
S: ClientStream + Unpin + 'static,
{
let paths = profile.paths();
let signer = keys::signer_ssh::<S>(profile).await?;
Ok((signer.clone(), Storage::open(paths, signer)?))
}
}
1 change: 0 additions & 1 deletion copy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ either = "1.3"
librad = { path = "../librad" }
nonempty = "0.6"
radicle-git-ext = { path = "../git-ext" }
radicle-keystore = "0"
thiserror = "1.0"
tracing = "0.1"

Expand Down
2 changes: 1 addition & 1 deletion copy/src/cli/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::path::PathBuf;

use argh::FromArgs;

use librad::{git::Urn, internal::canonical::Cstring, peer::PeerId};
use librad::{canonical::Cstring, git::Urn, PeerId};

/// Management of Radicle projects and their working copies.
///
Expand Down
20 changes: 12 additions & 8 deletions copy/src/cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,25 @@ use std::{
use anyhow::anyhow;

use librad::{
crypto::{
keystore::{
crypto::{self, Pwhash},
pinentry::Prompt,
FileStorage,
Keystore,
},
BoxedSigner,
SomeSigner,
},
git::{
identities::{self, local},
storage::Storage,
Urn,
},
git_ext::{OneLevel, RefLike},
keys::{PublicKey, SecretKey},
profile::Profile,
signer::{BoxedSigner, SomeSigner},
};
use radicle_keystore::{
crypto::{self, Pwhash},
pinentry::Prompt,
FileStorage,
Keystore,
PublicKey,
SecretKey,
};

use super::args::{community, garden, Args, Command, Community, Garden};
Expand Down
4 changes: 2 additions & 2 deletions copy/src/garden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use either::Either;

use librad::{
self,
crypto::BoxedSigner,
git::{
identities::{self, local::LocalIdentity, Project},
local::{
Expand All @@ -21,8 +22,7 @@ use librad::{
},
identities::{delegation::Indirect, payload},
paths::Paths,
peer::PeerId,
signer::BoxedSigner,
PeerId,
};

use crate::{include, sealed};
Expand Down
Loading

0 comments on commit 7543b9a

Please sign in to comment.