arti/rpc/superuser.rs
1//! Administrative RPC functionality.
2//!
3//! In general, RPC function is "administrative", and requires superuser access,
4//! whenever it can affect other applications.
5//!
6//! This is not a perfect sandbox: applications can _always_ interfere with one another's traffic by
7//! consuming resources (like bandwidth or CPU) in a way that introduces side channels.
8
9use arti_client::TorClient;
10use derive_deftly::Deftly;
11use std::sync::Arc;
12use tor_rpcbase::{self as rpc};
13use tor_rtcompat::Runtime;
14
15/// An object representing superuser access to Arti over an RPC session.
16///
17/// In general, RPC function is "administrative", and requires superuser access,
18/// whenever it can affect other applications.
19#[derive(Deftly)]
20#[derive_deftly(rpc::Object)]
21pub(super) struct RpcSuperuser<R: Runtime> {
22 /// A view of the underlying TorClient managed by this RpcSuperuser object.
23 tor_client: TorClient<R>,
24}
25
26impl<R: Runtime> RpcSuperuser<R> {
27 /// Construct a new RpcSuperuser object.
28 pub(super) fn new(tor_client: TorClient<R>) -> Self {
29 RpcSuperuser { tor_client }
30 }
31
32 /// Ensure that every RPC method is registered for this instantiation of TorClient.
33 ///
34 /// We can't use [`rpc::static_rpc_invoke_fn`] for these, since TorClient is
35 /// parameterized.
36 pub(super) fn rpc_methods() -> Vec<rpc::dispatch::InvokerEnt> {
37 rpc::invoker_ent_list![enter_dormant_mode_on_rpcsuperuser::<R>,]
38 }
39}
40
41/// Enter "dormant mode".
42///
43/// Currently, the only available dormant mode is "soft dormant mode",
44/// which suspends most background operations until any client request
45/// is received.
46///
47/// Since this method affects all applications using the Arti process,
48/// it requires administrative permissions.
49///
50/// ## Limitations
51///
52/// As of 2026 March, this functionality is not perfectly implemented,
53/// and likely does not interact well with onion services.
54/// Additionally, there are likely background operations that
55/// this operation doesn't cover.
56///
57/// This method returns a reply immediately, but it may take a little
58/// while before all of the background tasks finish their work and stop.
59#[derive(Debug, serde::Deserialize, serde::Serialize, Deftly)]
60#[derive_deftly(rpc::DynMethod)]
61#[deftly(rpc(method_name = "arti:enter_dormant_mode"))]
62struct EnterDormantMode {}
63
64impl rpc::RpcMethod for EnterDormantMode {
65 type Output = rpc::Nil;
66 type Update = rpc::NoUpdates;
67}
68
69/// Implementation for [`EnterDormantMode`] on [`RpcSuperuser`].
70async fn enter_dormant_mode_on_rpcsuperuser<R: Runtime>(
71 session: Arc<RpcSuperuser<R>>,
72 _method: Box<EnterDormantMode>,
73 _ctx: Arc<dyn rpc::Context>,
74) -> Result<rpc::Nil, rpc::RpcError> {
75 use arti_client::DormantMode;
76 session.tor_client.set_dormant(DormantMode::Soft);
77 Ok(rpc::Nil::default())
78}