diff --git a/src/clap.rs b/src/clap.rs index 446398c7..1057bb96 100644 --- a/src/clap.rs +++ b/src/clap.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; -use clap::Parser; +use clap::{Parser, Subcommand}; /// Commandline arguments #[derive(Parser, Debug)] @@ -11,6 +11,43 @@ pub struct Args { #[arg(short, long)] /// Optional argument to the path of a conduwuit config TOML file pub config: Option, + + #[clap(subcommand)] + /// Optional subcommand to export the homeserver signing key and exit + pub signing_key: Option, +} + +#[derive(Debug, Subcommand)] +pub enum SigningKey { + /// Filesystem path to export the homeserver signing key to. + /// The output will be: `ed25519 ` which + /// is Synapse's format + ExportPath { + path: PathBuf, + }, + + /// Filesystem path for conduwuit to attempt to read and import the + /// homeserver signing key. The expected format is Synapse's format: + /// `ed25519 ` + ImportPath { + path: PathBuf, + + #[arg(long)] + /// Optional argument to import the key but don't overwrite our signing + /// key, and instead add it to `old_verify_keys`. This field tells other + /// servers that this is our old public key that can still be used to + /// sign old events. + /// + /// See https://spec.matrix.org/v1.9/server-server-api/#get_matrixkeyv2server for more details. + add_to_old_public_keys: bool, + + #[arg(long)] + /// Timestamp (`expired_ts`) in seconds since UNIX epoch that the old + /// homeserver signing key stopped being used. + /// + /// See https://spec.matrix.org/v1.9/server-server-api/#get_matrixkeyv2server for more details. + timestamp: u64, + }, } /// Parse commandline arguments into structured data diff --git a/src/database/key_value/globals.rs b/src/database/key_value/globals.rs index 63d0e2b6..058a1a04 100644 --- a/src/database/key_value/globals.rs +++ b/src/database/key_value/globals.rs @@ -211,9 +211,10 @@ lasttimelinecount_cache: {lasttimelinecount_cache}\n" .map(|key| (version, key)) }) .and_then(|(version, key)| { + debug!("Keypair bytes: {:?}", key); let keypair = Ed25519KeyPair::from_der(key, version) .map_err(|_| Error::bad_database("Private or public keys are invalid.")); - debug!("Private and public key bytes: {keypair:?}"); + debug!("Private and public key: {keypair:?}"); keypair }) } diff --git a/src/main.rs b/src/main.rs index 03c9bdf6..31e4dd20 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,8 +15,12 @@ use axum::{ use axum_server::{bind, bind_rustls, tls_rustls::RustlsConfig, Handle as ServerHandle}; #[cfg(feature = "axum_dual_protocol")] use axum_server_dual_protocol::ServerExt; -use conduit::api::{client_server, server_server}; +use base64::{engine::general_purpose, Engine as _}; pub use conduit::*; // Re-export everything from the library crate +use conduit::{ + api::{client_server, server_server}, + clap::{Args, SigningKey}, +}; use either::Either::{Left, Right}; use figment::{ providers::{Env, Format, Toml}, @@ -28,12 +32,15 @@ use http::{ }; #[cfg(unix)] use hyperlocal::SocketIncoming; -use ruma::api::{ - client::{ - error::{Error as RumaError, ErrorBody, ErrorKind}, - uiaa::UiaaResponse, +use ruma::{ + api::{ + client::{ + error::{Error as RumaError, ErrorBody, ErrorKind}, + uiaa::UiaaResponse, + }, + IncomingRequest, }, - IncomingRequest, + serde::Base64, }; #[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))] use tikv_jemallocator::Jemalloc; @@ -73,7 +80,7 @@ async fn main() { } else if args.config.is_some() { Figment::new() .merge( - Toml::file(args.config.expect( + Toml::file(args.config.as_ref().expect( "conduwuit config commandline argument was specified, but appears to be invalid. This should be \ set to the path of a valid TOML file.", )) @@ -169,8 +176,16 @@ async fn main() { let config = &services().globals.config; - /* ad-hoc config validation/checks */ + /* homeserver signing keypair subcommand stuff */ + if let Some(subcommands) = &args.signing_key { + if signing_key_operations(subcommands).await.is_ok() { + return; + } + } + debug!("Ed25519KeyPair: {:?}", services().globals.keypair()); + + /* ad-hoc config validation/checks */ if config.unix_socket_path.is_some() && !cfg!(unix) { error!( "UNIX socket support is only available on *nix platforms. Please remove \"unix_socket_path\" from your \ @@ -912,3 +927,36 @@ fn maximize_fd_limit() -> Result<(), nix::errno::Errno> { Ok(()) } + +/// Homeserver signing key commands/operations +async fn signing_key_operations(subcommands: &SigningKey) -> Result<()> { + match subcommands { + SigningKey::ExportPath { + path, + } => { + let mut file = tokio::fs::File::create(path).await?; + let mut content = String::new(); + + content.push_str("ed25519 "); + + let version = services().globals.keypair().version(); + + content.push_str(version); + content.push(' '); + + let keypair = services().globals.keypair(); + debug!("Ed25519KeyPair: {:?}", keypair); + + //let key_base64 = Base64::new(key); + + Ok(()) + }, + SigningKey::ImportPath { + path, + add_to_old_public_keys, + timestamp, + } => { + unimplemented!() + }, + } +}