mirror of
https://github.com/rosenpass/rosenpass.git
synced 2025-12-12 15:49:22 -08:00
feat: Expand Rosenpass unix socket API documentation
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
// Note: This is business logic; tested through the integration tests in
|
||||
// rosenpass/tests/
|
||||
|
||||
use std::{borrow::BorrowMut, collections::VecDeque, os::fd::OwnedFd};
|
||||
|
||||
use anyhow::Context;
|
||||
@@ -20,37 +23,80 @@ use crate::{
|
||||
|
||||
use super::{supply_keypair_response_status, Server as ApiServer};
|
||||
|
||||
/// Stores the state of the API handler.
|
||||
///
|
||||
/// This is used in the context [ApiHandlerContext]; [ApiHandlerContext] exposes both
|
||||
/// the [AppServer] and the API handler state.
|
||||
///
|
||||
/// [ApiHandlerContext] is what actually contains the API handler functions.
|
||||
#[derive(Debug)]
|
||||
pub struct ApiHandler {
|
||||
_dummy: (),
|
||||
}
|
||||
|
||||
impl ApiHandler {
|
||||
/// Construct an [Self]
|
||||
#[allow(clippy::new_without_default)]
|
||||
pub fn new() -> Self {
|
||||
Self { _dummy: () }
|
||||
}
|
||||
}
|
||||
|
||||
/// The implementation of the API requires both access to its own state [ApiHandler] and to the
|
||||
/// [AppServer] the API is supposed to operate on.
|
||||
///
|
||||
/// This trait provides both; it implements a pattern to allow for multiple - **potentially
|
||||
/// overlapping** mutable references to be passed to the API handler functions.
|
||||
///
|
||||
/// This relatively complex scheme is chosen to appease the borrow checker: We want flexibility
|
||||
/// with regard to where the [ApiHandler] is stored and we need a mutable reference to
|
||||
/// [ApiHandler]. We also need a mutable reference to [AppServer]. Achieving this by using the
|
||||
/// direct method would be impossible because the [ApiHandler] is actually stored somewhere inside
|
||||
/// [AppServer]. The borrow checker does not allow this.
|
||||
///
|
||||
/// What we have instead is – in practice – a reference to [AppServer] and a function (as part of
|
||||
/// the trait) that extracts an [ApiHandler] reference from [AppServer], which is allowed by the
|
||||
/// borrow checker. A benefit of the use of a trait here is that we could, if desired, also store
|
||||
/// the [ApiHandler] outside [AppServer]. It really depends on the trait.
|
||||
pub trait ApiHandlerContext {
|
||||
/// Retrieve the [ApiHandler]
|
||||
fn api_handler(&self) -> &ApiHandler;
|
||||
/// Retrieve the [AppServer]
|
||||
fn app_server(&self) -> &AppServer;
|
||||
/// Retrieve the [ApiHandler]
|
||||
fn api_handler_mut(&mut self) -> &mut ApiHandler;
|
||||
/// Retrieve the [AppServer]
|
||||
fn app_server_mut(&mut self) -> &mut AppServer;
|
||||
}
|
||||
|
||||
/// This is the Error raised by [ApiServer::supply_keypair]; it contains both
|
||||
/// the underlying error message as well as the status value
|
||||
/// returned by the API.
|
||||
///
|
||||
/// [ApiServer::supply_keypair] generally constructs a [Self] by using one of the
|
||||
/// utility functions [SupplyKeypairErrorExt].
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
#[error("Error in SupplyKeypair")]
|
||||
struct SupplyKeypairError {
|
||||
/// The status code communicated via the Rosenpass API
|
||||
status: u128,
|
||||
/// The underlying error that caused the Rosenpass API level Error
|
||||
#[source]
|
||||
cause: anyhow::Error,
|
||||
}
|
||||
|
||||
trait SupplyKeypairErrorExt<T> {
|
||||
/// Imbue any Error (that can be represented as [anyhow::Error]) with
|
||||
/// an arbitrary error code
|
||||
fn e_custom(self, status: u128) -> Result<T, SupplyKeypairError>;
|
||||
/// Imbue any Error (that can be represented as [anyhow::Error]) with
|
||||
/// the [supply_keypair_response_status::INTERNAL_ERROR] error code
|
||||
fn einternal(self) -> Result<T, SupplyKeypairError>;
|
||||
/// Imbue any Error (that can be represented as [anyhow::Error]) with
|
||||
/// the [supply_keypair_response_status::KEYPAIR_ALREADY_SUPPLIED] error code
|
||||
fn ealready_supplied(self) -> Result<T, SupplyKeypairError>;
|
||||
/// Imbue any Error (that can be represented as [anyhow::Error]) with
|
||||
/// the [supply_keypair_response_status::INVALID_REQUEST] error code
|
||||
fn einvalid_req(self) -> Result<T, SupplyKeypairError>;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,8 +140,10 @@ impl Message for SupplyKeypairRequest {
|
||||
pub mod supply_keypair_response_status {
|
||||
pub const OK: u128 = 0;
|
||||
pub const KEYPAIR_ALREADY_SUPPLIED: u128 = 1;
|
||||
// TODO: This is not actually part of the API. Remove.
|
||||
pub const INTERNAL_ERROR: u128 = 2;
|
||||
pub const INVALID_REQUEST: u128 = 3;
|
||||
/// TODO: Deprectaed, remove
|
||||
pub const IO_ERROR: u128 = 4;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@ use std::{collections::VecDeque, os::fd::OwnedFd};
|
||||
use zerocopy::{ByteSlice, ByteSliceMut};
|
||||
|
||||
pub trait Server {
|
||||
/// This implements the handler for the [crate::api::RequestMsgType::Ping] API message
|
||||
///
|
||||
/// It merely takes a buffer and returns that same buffer.
|
||||
fn ping(
|
||||
&mut self,
|
||||
req: &PingRequest,
|
||||
@@ -10,6 +13,47 @@ pub trait Server {
|
||||
res: &mut PingResponse,
|
||||
) -> anyhow::Result<()>;
|
||||
|
||||
/// Supply the cryptographic server keypair through file descriptor passing in the API
|
||||
///
|
||||
/// This implements the handler for the [crate::api::RequestMsgType::SupplyKeypair] API message.
|
||||
///
|
||||
/// # File descriptors
|
||||
///
|
||||
/// 1. The secret key (size must match exactly); the file descriptor must be backed by either
|
||||
/// of
|
||||
/// - file-system file
|
||||
/// - [memfd](https://man.archlinux.org/man/memfd.2.en)
|
||||
/// - [memfd_secret](https://man.archlinux.org/man/memfd.2.en)
|
||||
/// 2. The public key (size must match exactly); the file descriptor must be backed by either
|
||||
/// of
|
||||
/// - file-system file
|
||||
/// - [memfd](https://man.archlinux.org/man/memfd.2.en)
|
||||
/// - [memfd_secret](https://man.archlinux.org/man/memfd.2.en)
|
||||
///
|
||||
/// # API Return Status
|
||||
///
|
||||
/// 1. [crate::api::supply_keypair_response_status::OK] - Indicates success
|
||||
/// 2. [crate::api::supply_keypair_response_status::KEYPAIR_ALREADY_SUPPLIED] – The endpoint was used but
|
||||
/// the server already has server keys
|
||||
/// 3. [crate::api::supply_keypair_response_status::INVALID_REQUEST] – Malformed request; could be:
|
||||
/// - Missing file descriptors for public key
|
||||
/// - File descriptors contain data of invalid length
|
||||
/// - Invalid file descriptor type
|
||||
///
|
||||
/// # Description
|
||||
///
|
||||
/// At startup, if no server keys are specified in the rosenpass configuration, and if the API
|
||||
/// is enabled, the Rosenpass process waits for server keys to be supplied to the API. Before
|
||||
/// then, any messages for the rosenpass cryptographic protocol are ignored and dropped – all
|
||||
/// cryptographic operations require access to the server keys.
|
||||
///
|
||||
/// Both private and public keys are specified through file descriptors and both are read from
|
||||
/// their respective file descriptors into process memory. A file descriptor based transport is
|
||||
/// used because of the excessive size of Classic McEliece public keys (100kb and up).
|
||||
///
|
||||
/// The file descriptors for the keys need not be backed by a file on disk. You can supply a
|
||||
/// [memfd](https://man.archlinux.org/man/memfd.2.en) or [memfd_secret](https://man.archlinux.org/man/memfd_secret.2.en)
|
||||
/// backed file descriptor if the server keys are not backed by a file system file.
|
||||
fn supply_keypair(
|
||||
&mut self,
|
||||
req: &super::SupplyKeypairRequest,
|
||||
@@ -17,6 +61,27 @@ pub trait Server {
|
||||
res: &mut super::SupplyKeypairResponse,
|
||||
) -> anyhow::Result<()>;
|
||||
|
||||
/// Supply a new UDP listen socket through file descriptor passing via the API
|
||||
///
|
||||
/// This implements the handler for the [crate::api::RequestMsgType::AddListenSocket] API message.
|
||||
///
|
||||
/// # File descriptors
|
||||
///
|
||||
/// 1. The listen socket; must be backed by a UDP network listen socket
|
||||
///
|
||||
/// # API Return Status
|
||||
///
|
||||
/// 1. [crate::api::add_listen_socket_response_status::OK] - Indicates success
|
||||
/// 2. [add_listen_socket_response_status::INVALID_REQUEST] – Malformed request; could be:
|
||||
/// - Missing file descriptors for public key
|
||||
/// - Invalid file descriptor type
|
||||
/// 3. [crate::api::add_listen_socket_response_status::INTERNAL_ERROR] – Some other, non-fatal error
|
||||
/// occured. Check the logs on log
|
||||
///
|
||||
/// # Description
|
||||
///
|
||||
/// This endpoint allows you to supply a UDP listen socket; it will be used to perform
|
||||
/// cryptographic key exchanges via the Rosenpass protocol.
|
||||
fn add_listen_socket(
|
||||
&mut self,
|
||||
req: &super::AddListenSocketRequest,
|
||||
|
||||
Reference in New Issue
Block a user