Skip to main content

tor_dircommon/
authority.rs

1//! Information about directory authorities
2//!
3//! From a client's point of view, an authority's role is to sign the
4//! consensus directory.
5
6use std::net::SocketAddr;
7
8use derive_deftly::Deftly;
9use getset::Getters;
10use tor_config::define_list_builder_accessors;
11use tor_config::derive::prelude::*;
12use tor_llcrypto::pk::rsa::RsaIdentity;
13
14/// The contact information for all directory authorities this implementation is
15/// aware of.
16///
17/// This data structure makes use of proposal 330 in order to distinguish
18/// authorities by their responsibilities, hence why the fields are divided.
19#[derive(Debug, Clone, Deftly, Eq, PartialEq, Getters)]
20#[derive_deftly(TorConfig)]
21pub struct AuthorityContacts {
22    // NOTE: We aren't using list builders here, since these never actually used sub-builders,
23    // and therefore has a slightly different API.
24    // We might later decide to change these to proper list-builders;
25    // if so, it will be an API break.
26    //
27    /// The [`RsaIdentity`] keys that may be used to sign valid consensus documents.
28    #[deftly(tor_config(no_magic, setter(skip), default = "default_v3idents()"))]
29    #[getset(get = "pub")]
30    v3idents: Vec<RsaIdentity>,
31
32    /// The endpoints of authorities where upload of router descriptors and other
33    /// documents is possible.
34    ///
35    /// This section is primarily of interest for relays.
36    ///
37    /// The use of nested a [`Vec`] serves the purpose to assign multiple IPs to
38    /// a single logical authority, such as having an IPv4 and IPv6 address.
39    #[deftly(tor_config(no_magic, setter(skip), default = "default_uploads()"))]
40    #[getset(get = "pub")]
41    uploads: Vec<Vec<SocketAddr>>,
42
43    /// The endpoints of authorities where download of network documents is possible.
44    ///
45    /// This section is primarily of interest for directory mirrors.
46    ///
47    /// The use of nested a [`Vec`] serves the purpose to assign multiple IPs to
48    /// a single logical authority, such as having an IPv4 and IPv6 address.
49    #[deftly(tor_config(no_magic, setter(skip), default = "default_downloads()"))]
50    #[getset(get = "pub")]
51    downloads: Vec<Vec<SocketAddr>>,
52
53    /// The endpoints of authorities where voting for consensus documents is possible.
54    ///
55    /// This section is primarily of interest for other directory authorities.
56    ///
57    /// The use of nested a [`Vec`] serves the purpose to assign multiple IPs to
58    /// a single logical authority, such as having an IPv4 and IPv6 address.
59    #[deftly(tor_config(no_magic, setter(skip), default = "default_votes()"))]
60    #[getset(get = "pub")]
61    votes: Vec<Vec<SocketAddr>>,
62}
63
64define_list_builder_accessors! {
65    struct AuthorityContactsBuilder {
66        pub v3idents: [RsaIdentity],
67        pub uploads: [Vec<SocketAddr>],
68        pub downloads: [Vec<SocketAddr>],
69        pub votes: [Vec<SocketAddr>],
70    }
71}
72
73/// Returns a list of the default [`RsaIdentity`]s for the directory authorities.
74fn default_v3idents() -> Vec<RsaIdentity> {
75    fn rsa(hex: &str) -> RsaIdentity {
76        RsaIdentity::from_hex(hex).expect("invalid hex?!?")
77    }
78
79    vec![
80        rsa("27102BC123E7AF1D4741AE047E160C91ADC76B21"), // bastet
81        rsa("0232AF901C31A04EE9848595AF9BB7620D4C5B2E"), // dannenberg
82        rsa("E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58"), // dizum
83        rsa("70849B868D606BAECFB6128C5E3D782029AA394F"), // faravahar
84        rsa("ED03BB616EB2F60BEC80151114BB25CEF515B226"), // gabelmoo
85        rsa("23D15D965BC35114467363C165C4F724B64B4F66"), // longclaw
86        rsa("49015F787433103580E3B66A1707A00E60F2D15B"), // maatuska
87        rsa("F533C81CEF0BC0267857C99B2F471ADF249FA232"), // moria1
88        rsa("2F3DF9CA0E5D36F2685A2DA67184EB8DCB8CBA8C"), // tor26
89    ]
90}
91
92/// Returns a list of the [`SocketAddr`] for the directory authorities.
93///
94/// The nested [`Vec`] serves dual-stack purposes
95/// (i.e. many IPs mapping to one logical authority).
96fn default_uploads() -> Vec<Vec<SocketAddr>> {
97    /// Converts a [`str`] to a [`SocketAddr`].
98    fn sa(s: &str) -> SocketAddr {
99        s.parse().expect("invalid socket address?!?")
100    }
101
102    vec![
103        // bastet
104        vec![
105            sa("204.13.164.118:80"),
106            sa("[2620:13:4000:6000::1000:118]:80"),
107        ],
108        // dannenberg
109        vec![sa("193.23.244.244:80"), sa("[2001:678:558:1000::244]:80")],
110        // dizum
111        vec![sa("45.66.35.11:80"), sa("[2a09:61c0::1337]:80")],
112        // faravahar
113        vec![sa("216.218.219.41:80"), sa("[2001:470:164:2::2]:80")],
114        // gabelmoo
115        vec![
116            sa("131.188.40.189:80"),
117            sa("[2001:638:a000:4140::ffff:189]:80"),
118        ],
119        // longclaw
120        vec![sa("199.58.81.140:80")],
121        // maatuska
122        vec![sa("171.25.193.9:443"), sa("[2001:67c:289c::9]:443")],
123        // moria1
124        vec![sa("128.31.0.39:9231")],
125        // tor26
126        vec![sa("217.196.147.77:80"), sa("[2a02:16a8:662:2203::1]:80")],
127    ]
128}
129
130/// For now, an alias to [`default_uploads()`].
131fn default_downloads() -> Vec<Vec<SocketAddr>> {
132    default_uploads()
133}
134
135/// For now, an alias to [`default_uploads()`].
136fn default_votes() -> Vec<Vec<SocketAddr>> {
137    default_uploads()
138}
139
140#[cfg(test)]
141mod test {
142    // @@ begin test lint list maintained by maint/add_warning @@
143    #![allow(clippy::bool_assert_comparison)]
144    #![allow(clippy::clone_on_copy)]
145    #![allow(clippy::dbg_macro)]
146    #![allow(clippy::mixed_attributes_style)]
147    #![allow(clippy::print_stderr)]
148    #![allow(clippy::print_stdout)]
149    #![allow(clippy::single_char_pattern)]
150    #![allow(clippy::unwrap_used)]
151    #![allow(clippy::unchecked_time_subtraction)]
152    #![allow(clippy::useless_vec)]
153    #![allow(clippy::needless_pass_by_value)]
154    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
155    #![allow(clippy::unnecessary_wraps)]
156
157    use super::*;
158
159    #[test]
160    fn default_auths() {
161        let dflt = AuthorityContacts::builder().build().unwrap();
162        assert_eq!(dflt.v3idents, default_v3idents());
163        assert_eq!(dflt.uploads, default_uploads());
164        assert_eq!(dflt.downloads, default_downloads());
165        assert_eq!(dflt.votes, default_votes());
166
167        assert_eq!(
168            dflt.v3idents[8],
169            RsaIdentity::from_hex("2F3DF9CA0E5D36F2685A2DA67184EB8DCB8CBA8C").unwrap()
170        );
171        assert_eq!(
172            dflt.uploads[8],
173            vec![
174                "217.196.147.77:80".parse().unwrap(),
175                "[2a02:16a8:662:2203::1]:80".parse().unwrap()
176            ]
177        );
178        assert_eq!(dflt.uploads[8], dflt.downloads[8]);
179        assert_eq!(dflt.uploads[8], dflt.votes[8]);
180    }
181}