1
//! Owned variants of [`ChanTarget`] and [`CircTarget`].
2

            
3
use safelog::Redactable;
4
use serde::{Deserialize, Serialize};
5
use std::fmt::{self, Display};
6
use std::net::SocketAddr;
7
use tor_config::impl_standard_builder;
8
use tor_llcrypto::pk;
9

            
10
use crate::{
11
    ChanTarget, ChannelMethod, CircTarget, HasAddrs, HasChanMethod, HasRelayIds, RelayIdRef,
12
    RelayIdType,
13
};
14

            
15
/// RelayIds is an owned copy of the set of known identities of a relay.
16
///
17
/// Note that an object of this type will not necessarily have every type of
18
/// identity: it's possible that we don't know all the identities, or that one
19
/// of the identity types has become optional.
20
#[derive(
21
    Debug,
22
    Clone,
23
    Eq,
24
    PartialEq,
25
    Hash,
26
    PartialOrd,
27
    Ord,
28
    Serialize,
29
    Deserialize,
30
    derive_builder::Builder,
31
)]
32
#[builder(derive(Debug))]
33
pub struct RelayIds {
34
    /// Copy of the ed25519 id from the underlying ChanTarget.
35
    #[serde(rename = "ed25519")]
36
    #[builder(default, setter(strip_option))]
37
    ed_identity: Option<pk::ed25519::Ed25519Identity>,
38
    /// Copy of the rsa id from the underlying ChanTarget.
39
    #[serde(rename = "rsa")]
40
    #[builder(default, setter(strip_option))]
41
    rsa_identity: Option<pk::rsa::RsaIdentity>,
42
}
43
impl_standard_builder! { RelayIds : !Deserialize + !Builder + !Default }
44

            
45
impl HasRelayIds for RelayIds {
46
121456256
    fn identity(&self, key_type: RelayIdType) -> Option<crate::RelayIdRef<'_>> {
47
121456256
        match key_type {
48
67383526
            RelayIdType::Ed25519 => self.ed_identity.as_ref().map(RelayIdRef::from),
49
54072730
            RelayIdType::Rsa => self.rsa_identity.as_ref().map(RelayIdRef::from),
50
        }
51
121456256
    }
52
}
53

            
54
impl RelayIds {
55
    /// Return an empty set of identities.
56
    ///
57
    /// This is _not_ a `Default` method, since this is not what you should
58
    /// usually construct.
59
5284
    pub const fn empty() -> Self {
60
5284
        Self {
61
5284
            ed_identity: None,
62
5284
            rsa_identity: None,
63
5284
        }
64
5284
    }
65

            
66
    /// Construct a new `RelayIds` object from another object that implements
67
    /// [`HasRelayIds`].
68
    ///
69
    /// Note that it is possible to construct an _empty_ `RelayIds` object if
70
    /// the input does not contain any recognized identity type.
71
3492059
    pub fn from_relay_ids<T: HasRelayIds + ?Sized>(other: &T) -> Self {
72
        Self {
73
3492059
            ed_identity: other
74
3492059
                .identity(RelayIdType::Ed25519)
75
3492059
                .map(|r| *r.unwrap_ed25519()),
76
3492059
            rsa_identity: other.identity(RelayIdType::Rsa).map(|r| *r.unwrap_rsa()),
77
        }
78
3492059
    }
79
}
80

            
81
impl std::fmt::Display for RelayIds {
82
1162
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83
1162
        write!(f, "{}", self.display_relay_ids())
84
1162
    }
85
}
86
impl Redactable for RelayIds {
87
2
    fn display_redacted(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88
2
        write!(f, "{}", self.display_relay_ids().redacted())
89
2
    }
90
}
91

            
92
/// OwnedChanTarget is a summary of a [`ChanTarget`] that owns all of its
93
/// members.
94
#[derive(Debug, Clone, derive_builder::Builder)]
95
#[builder(derive(Debug))]
96
pub struct OwnedChanTarget {
97
    /// Copy of the addresses from the underlying ChanTarget.
98
    #[builder(default)]
99
    addrs: Vec<SocketAddr>,
100
    /// Copy of the channel methods from the underlying ChanTarget.
101
    //
102
    // TODO: in many cases this will be redundant with addrs; if we allocate a
103
    // lot of these objects, we might want to handle that.
104
    #[builder(default = "self.make_method()")]
105
    method: ChannelMethod,
106
    /// Identities that this relay provides.
107
    #[builder(sub_builder)]
108
    ids: RelayIds,
109
}
110
impl_standard_builder! { OwnedChanTarget : !Deserialize + !Builder + !Default }
111

            
112
impl OwnedChanTargetBuilder {
113
    /// Set the ed25519 identity in this builder to `id`.
114
47458
    pub fn ed_identity(&mut self, id: pk::ed25519::Ed25519Identity) -> &mut Self {
115
47458
        self.ids().ed_identity(id);
116
47458
        self
117
47458
    }
118

            
119
    /// Set the RSA identity in this builder to `id`.
120
47690
    pub fn rsa_identity(&mut self, id: pk::rsa::RsaIdentity) -> &mut Self {
121
47690
        self.ids().rsa_identity(id);
122
47690
        self
123
47690
    }
124

            
125
    /// Helper: make a channel method if none was specified.
126
47570
    fn make_method(&self) -> ChannelMethod {
127
47570
        ChannelMethod::Direct(self.addrs.clone().unwrap_or_default())
128
47570
    }
129
}
130

            
131
impl HasAddrs for OwnedChanTarget {
132
183470
    fn addrs(&self) -> impl Iterator<Item = SocketAddr> {
133
183470
        self.addrs.iter().copied()
134
183470
    }
135
}
136

            
137
impl HasChanMethod for OwnedChanTarget {
138
186130
    fn chan_method(&self) -> ChannelMethod {
139
186130
        self.method.clone()
140
186130
    }
141
}
142

            
143
impl HasRelayIds for OwnedChanTarget {
144
9638654
    fn identity(&self, key_type: RelayIdType) -> Option<RelayIdRef<'_>> {
145
9638654
        self.ids.identity(key_type)
146
9638654
    }
147
}
148

            
149
impl ChanTarget for OwnedChanTarget {}
150

            
151
impl OwnedChanTarget {
152
    /// Construct a OwnedChanTarget from a given ChanTarget.
153
2164069
    pub fn from_chan_target<C>(target: &C) -> Self
154
2164069
    where
155
2164069
        C: ChanTarget + ?Sized,
156
    {
157
2164069
        OwnedChanTarget {
158
2164069
            addrs: target.addrs().collect(),
159
2164069
            method: target.chan_method(),
160
2164069
            ids: RelayIds::from_relay_ids(target),
161
2164069
        }
162
2164069
    }
163

            
164
    /// Return a mutable reference to this [`OwnedChanTarget`]'s [`ChannelMethod`]
165
    ///
166
406
    pub fn chan_method_mut(&mut self) -> &mut ChannelMethod {
167
406
        &mut self.method
168
406
    }
169
}
170

            
171
/// Primarily for error reporting and logging
172
impl Display for OwnedChanTarget {
173
2
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
174
2
        write!(f, "{}", self.display_chan_target())
175
2
    }
176
}
177

            
178
impl Redactable for OwnedChanTarget {
179
    fn display_redacted(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180
        self.display_chan_target().display_redacted(f)
181
    }
182

            
183
    fn debug_redacted(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184
        self.display_chan_target().debug_redacted(f)
185
    }
186
}
187

            
188
/// OwnedCircTarget is a summary of a [`CircTarget`] that owns all its
189
/// members.
190
#[derive(Debug, Clone, derive_builder::Builder)]
191
#[builder(derive(Debug))]
192
pub struct OwnedCircTarget {
193
    /// The fields from this object when considered as a ChanTarget.
194
    #[builder(sub_builder)]
195
    chan_target: OwnedChanTarget,
196
    /// The ntor key to use when extending to this CircTarget
197
    ntor_onion_key: pk::curve25519::PublicKey,
198
    /// The subprotocol versions that this CircTarget supports.
199
    protocols: tor_protover::Protocols,
200
}
201
impl_standard_builder! { OwnedCircTarget : !Deserialize + !Builder + !Default }
202

            
203
impl OwnedCircTarget {
204
    /// Construct an OwnedCircTarget from a given CircTarget.
205
78606
    pub fn from_circ_target<C>(target: &C) -> Self
206
78606
    where
207
78606
        C: CircTarget + ?Sized,
208
    {
209
78606
        OwnedCircTarget {
210
78606
            chan_target: OwnedChanTarget::from_chan_target(target),
211
78606
            ntor_onion_key: *target.ntor_onion_key(),
212
78606
            // TODO: I don't like having to clone here.  Our underlying
213
78606
            // protovers parsing uses an Arc, IIRC.  Can we expose that here?
214
78606
            protocols: target.protovers().clone(),
215
78606
        }
216
78606
    }
217

            
218
    /// Return a mutable view of this OwnedCircTarget as an [`OwnedChanTarget`].
219
    pub fn chan_target_mut(&mut self) -> &mut OwnedChanTarget {
220
        &mut self.chan_target
221
    }
222

            
223
    /// Return a  view of this OwnedCircTarget as an [`OwnedChanTarget`].
224
348
    pub fn chan_target(&self) -> &OwnedChanTarget {
225
348
        &self.chan_target
226
348
    }
227
}
228

            
229
impl HasAddrs for OwnedCircTarget {
230
2328
    fn addrs(&self) -> impl Iterator<Item = SocketAddr> {
231
2328
        self.chan_target.addrs()
232
2328
    }
233
}
234

            
235
impl HasRelayIds for OwnedCircTarget {
236
4438992
    fn identity(&self, key_type: RelayIdType) -> Option<RelayIdRef<'_>> {
237
4438992
        self.chan_target.identity(key_type)
238
4438992
    }
239
}
240
impl HasChanMethod for OwnedCircTarget {
241
4412
    fn chan_method(&self) -> ChannelMethod {
242
4412
        self.chan_target.chan_method()
243
4412
    }
244
}
245

            
246
impl ChanTarget for OwnedCircTarget {}
247

            
248
impl CircTarget for OwnedCircTarget {
249
3372
    fn ntor_onion_key(&self) -> &pk::curve25519::PublicKey {
250
3372
        &self.ntor_onion_key
251
3372
    }
252
3372
    fn protovers(&self) -> &tor_protover::Protocols {
253
3372
        &self.protocols
254
3372
    }
255
}
256

            
257
/// A value that can be converted into an OwnedChanTarget.
258
pub trait IntoOwnedChanTarget {
259
    /// Convert this value into an [`OwnedChanTarget`].
260
    fn to_owned(self) -> OwnedChanTarget;
261

            
262
    /// Convert this value into an [`LoggedChanTarget`].
263
    fn to_logged(self) -> LoggedChanTarget
264
    where
265
        Self: Sized,
266
    {
267
        self.to_owned().into()
268
    }
269
}
270

            
271
impl<'a, T: ChanTarget + ?Sized> IntoOwnedChanTarget for &'a T {
272
    fn to_owned(self) -> OwnedChanTarget {
273
        OwnedChanTarget::from_chan_target(self)
274
    }
275
}
276

            
277
impl IntoOwnedChanTarget for OwnedChanTarget {
278
    fn to_owned(self) -> OwnedChanTarget {
279
        self
280
    }
281
}
282

            
283
/// An `OwnedChanTarget` suitable for logging and including in errors
284
pub type LoggedChanTarget = safelog::BoxSensitive<OwnedChanTarget>;
285

            
286
#[cfg(test)]
287
mod test {
288
    // @@ begin test lint list maintained by maint/add_warning @@
289
    #![allow(clippy::bool_assert_comparison)]
290
    #![allow(clippy::clone_on_copy)]
291
    #![allow(clippy::dbg_macro)]
292
    #![allow(clippy::mixed_attributes_style)]
293
    #![allow(clippy::print_stderr)]
294
    #![allow(clippy::print_stdout)]
295
    #![allow(clippy::single_char_pattern)]
296
    #![allow(clippy::unwrap_used)]
297
    #![allow(clippy::unchecked_time_subtraction)]
298
    #![allow(clippy::useless_vec)]
299
    #![allow(clippy::needless_pass_by_value)]
300
    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
301
    use super::*;
302
    use itertools::Itertools;
303

            
304
    #[test]
305
    #[allow(clippy::redundant_clone)]
306
    fn chan_target() {
307
        let ti = OwnedChanTarget::builder()
308
            .addrs(vec!["127.0.0.1:11".parse().unwrap()])
309
            .ed_identity([42; 32].into())
310
            .rsa_identity([45; 20].into())
311
            .build()
312
            .unwrap();
313

            
314
        let ti2 = OwnedChanTarget::from_chan_target(&ti);
315
        assert_eq!(ti.addrs().collect_vec(), ti2.addrs().collect_vec());
316
        assert!(ti.same_relay_ids(&ti2));
317

            
318
        assert_eq!(format!("{:?}", ti), format!("{:?}", ti2));
319
        assert_eq!(format!("{:?}", ti), format!("{:?}", ti.clone()));
320
    }
321

            
322
    #[test]
323
    #[allow(clippy::redundant_clone)]
324
    fn circ_target() {
325
        let mut builder = OwnedCircTarget::builder();
326
        builder
327
            .chan_target()
328
            .addrs(vec!["127.0.0.1:11".parse().unwrap()])
329
            .ed_identity([42; 32].into())
330
            .rsa_identity([45; 20].into());
331
        let ct = builder
332
            .ntor_onion_key([99; 32].into())
333
            .protocols("FlowCtrl=7".parse().unwrap())
334
            .build()
335
            .unwrap();
336
        let ch = ct.chan_target.clone();
337

            
338
        assert_eq!(ct.addrs().collect_vec(), ch.addrs().collect_vec());
339
        assert!(ct.same_relay_ids(&ch));
340
        assert_eq!(ct.ntor_onion_key().as_bytes(), &[99; 32]);
341
        assert_eq!(&ct.protovers().to_string(), "FlowCtrl=7");
342
        let ct2 = OwnedCircTarget::from_circ_target(&ct);
343
        assert_eq!(format!("{:?}", ct), format!("{:?}", ct2));
344
        assert_eq!(format!("{:?}", ct), format!("{:?}", ct.clone()));
345
    }
346

            
347
    #[test]
348
    fn format_relay_ids() {
349
        let mut builder = RelayIds::builder();
350
        builder
351
            .ed_identity([42; 32].into())
352
            .rsa_identity([45; 20].into());
353
        let ids = builder.build().unwrap();
354
        assert_eq!(
355
            format!("{}", ids),
356
            "ed25519:KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio $2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d"
357
        );
358
        assert_eq!(format!("{}", ids.redacted()), "ed25519:Ki…");
359
    }
360
}