1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
use std::sync::Arc;
use tor_circmgr::CircMgr;
use tor_netdir::NetDirProvider;
use tor_rtcompat::Runtime;
use crate::{OnionServiceStatus, Result};
/// A handle to an instance of an onion service.
//
// TODO hs: We might want to wrap this in an Arc<Mutex<>>, and have an inner
// structure that contains these elements. Or we might want to refactor this in
// some other way.
pub struct OnionService<R: Runtime> {
/// Needs some kind of configuration about: what is our identity (if we know
/// it), is this anonymous, do we store persistent info and if so where and
/// how, etc.
///
/// Authorized client public keys might be here, or they might be in a
/// separate structure.
config: (),
/// A netdir provider to use in finding our directories and choosing our
/// introduction points.
netdir_provider: Arc<dyn NetDirProvider>,
/// A circuit manager to use in making circuits to our introduction points,
/// HsDirs, and rendezvous points.
// TODO hs: Maybe we can make a trait that only gives a minimal "build a
// circuit" API from CircMgr, so that we can have this be a dyn reference
// too?
circmgr: Arc<CircMgr<R>>,
/// Private keys in actual use for this onion service.
///
/// TODO hs: This will need heavy refactoring.
///
/// TODO hs: There's a separate blinded ID, certificate, and signing key
/// for each active time period.
keys: (),
/// Status for each active introduction point for this onion service.
intro_points: Vec<()>,
/// Status for our onion service descriptor
descriptor_status: (),
/// Object that handles incoming streams from the client.
stream_handler: Arc<dyn crate::StreamHandler>,
}
impl<R: Runtime> OnionService<R> {
/// Create (but do not launch) a new onion service.
pub fn new(config: (), netdir_provider: (), circmgr: ()) -> Self {
todo!(); // TODO hs
}
/// Change the configuration of this onion service.
///
/// (Not everything can be changed here. At the very least we'll need to say
/// that the identity of a service is fixed. We might want to make the
/// storage backing this, and the anonymity status, unchangeable.)
pub fn reconfigure(&self, new_config: ()) -> Result<()> {
todo!() // TODO hs
}
/// Tell this onion service about some new short-term keys it can use.
pub fn add_keys(&self, keys: ()) -> Result<()> {
todo!() // TODO hs
}
/// Return the current status of this onion service.
pub fn status(&self) -> OnionServiceStatus {
todo!() // TODO hs
}
// TODO hs let's also have a function that gives you a stream of Status
// changes? Or use a publish-based watcher?
/// Tell this onion service to begin running.
pub fn launch(&self) -> Result<()> {
todo!() // TODO hs
// This needs to launch at least the following tasks:
//
// - If we decide to use separate disk-based key provisioning, a task to
// monitor our keys directory.
// - If we own our identity key, a task to generate per-period sub-keys as
// needed.
// - A task to make sure that we have enough introduction point circuits
// at all times, and launch new ones as needed.
// - A task to see whether we have an up-to-date descriptor uploaded for
// each supported time period to every HsDir listed for us in the
// current directory, and if not, regenerate and upload our descriptor
// as needed.
// - A task to receive introduction requests from our introduction
// points, decide whether to answer them, and if so launch a new
// rendezvous task to:
// - finish the cryptographic handshake
// - build a circuit to the rendezvous point
// - Send the RENDEZVOUS1 reply
// - Add a virtual hop to the rendezvous circuit
// - Launch a new task to handle BEGIN requests on the rendezvous
// circuit, using our StreamHandler.
}
/// Tell this onion service to stop running.
///
/// It can be restarted with launch().
///
/// You can also shut down an onion service completely by dropping the last
/// Clone of it.
pub fn stop(&self) -> Result<()> {
todo!() // TODO hs
}
}
|