summaryrefslogtreecommitdiff
path: root/crates/arti-client/src/config.rs
blob: 3d4d7c03bab2b0de8628215a08acf48f75cee004 (plain)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! Types and functions to configure a Tor client.
//!
//! Some of these are re-exported from lower-level crates.

use crate::{Error, Result};
use derive_builder::Builder;
use serde::Deserialize;
use std::path::PathBuf;

/// Types for configuring how Tor circuits are built.
pub mod circ {
    pub use tor_circmgr::{
        CircMgrConfig, CircMgrConfigBuilder, CircuitTiming, CircuitTimingBuilder, PathConfig,
        PathConfigBuilder, RequestTiming, RequestTimingBuilder,
    };
}

/// Types for configuring how Tor accesses its directory information.
pub mod dir {
    pub use tor_dirmgr::{
        Authority, AuthorityBuilder, DirMgrConfig, DirMgrConfigBuilder, DownloadScheduleConfig,
        DownloadScheduleConfigBuilder, FallbackDir, FallbackDirBuilder, NetworkConfig,
        NetworkConfigBuilder,
    };
}

/// Configuration for client behaviour relating to addresses.
///
/// This type is immutable once constructed. To create an object of this type,
/// use [`ClientAddrConfigBuilder`].
#[derive(Debug, Clone, Builder, Deserialize)]
#[builder]
pub struct ClientAddrConfig {
    /// Should we allow attempts to make Tor connections to local addresses?
    ///
    /// This option is off by default, since (by default) Tor exits will
    /// always reject connections to such addresses.
    #[builder(default)]
    pub(crate) allow_local_addrs: bool,
}

// NOTE: it seems that `unwrap` may be safe because of builder defaults
// check `derive_builder` documentation for details
// https://docs.rs/derive_builder/0.10.2/derive_builder/#default-values
#[allow(clippy::unwrap_used)]
impl Default for ClientAddrConfig {
    fn default() -> Self {
        ClientAddrConfigBuilder::default().build().unwrap()
    }
}

/// A configuration used to bootstrap a [`TorClient`](crate::TorClient).
///
/// In order to connect to the Tor network, Arti needs to know a few
/// well-known directories on the network, and the public keys of the
/// network's directory authorities.  It also needs a place on disk to
/// store persistent state and cached directory information.
///
/// Most users will create a TorClientConfig by running
/// [`TorClientConfig::sane_defaults`].
///
/// If you need to override the locations where Arti stores its information,
/// you can make a TorClientConfig with [`TorClientConfig::with_directories`].
///
/// Finally, you can get fine-grained control over the members of a a
/// TorClientConfig using [`TorClientConfigBuilder`].
#[derive(Clone, Debug, Builder)]
pub struct TorClientConfig {
    /// A directory suitable for storing persistent Tor state in.
    ///
    /// This is distinct from the cache directory set in `dir_cfg`:
    /// it is _not_ safe to delete this information regularly.
    ///
    /// Multiple instances of Arti may share the same state directory.
    pub(crate) state_cfg: PathBuf,

    /// Configuration for the network directory manager.
    ///
    /// This includes information on how to find and authenticate the
    /// Tor network, how to frequently to retry directory downloads,
    /// and where to store cached directory information.
    pub(crate) dir_cfg: dir::DirMgrConfig,

    /// Configuration for the network circuit manager.
    ///
    /// This includes information about how to build paths through the
    /// Tor network, and how to retry failed circuits.
    pub(crate) circ_cfg: circ::CircMgrConfig,

    /// Configures how the client interprets addresses on the network.
    pub(crate) addr_cfg: ClientAddrConfig,
}

impl TorClientConfig {
    /// Returns a `TorClientConfig` using reasonably sane defaults.
    ///
    /// This uses `tor_config`'s definitions for `APP_LOCAL_DATA` and
    /// `APP_CACHE` for the state and cache directories respectively.
    ///
    /// (On unix, this usually works out to `~/.local/share/arti` and
    /// `~/.cache/arti`, depending on your environment.  We use the
    /// `directories` crate for reasonable defaults on other platforms.)
    pub fn sane_defaults() -> Result<Self> {
        let state_dir = tor_config::CfgPath::new("${APP_LOCAL_DATA}".into())
            .path()
            .map_err(|e| Error::Configuration(format!("failed to find APP_LOCAL_DATA: {:?}", e)))?;
        let cache_dir = tor_config::CfgPath::new("${APP_CACHE}".into())
            .path()
            .map_err(|e| Error::Configuration(format!("failed to find APP_CACHE: {:?}", e)))?;

        Self::with_directories(state_dir, cache_dir)
    }

    /// Returns a `TorClientConfig` using the specified state and cache directories.
    ///
    /// All other configuration options are set to their defaults.
    pub fn with_directories<P, Q>(state_dir: P, cache_dir: Q) -> Result<Self>
    where
        P: Into<PathBuf>,
        Q: Into<PathBuf>,
    {
        Ok(Self {
            state_cfg: state_dir.into(),
            dir_cfg: dir::DirMgrConfig::builder()
                .cache_path(cache_dir.into())
                .build()
                .map_err(|e| {
                    Error::Configuration(format!("failed to build DirMgrConfig: {}", e))
                })?,
            circ_cfg: Default::default(),
            addr_cfg: Default::default(),
        })
    }

    /// Return a new builder to construct a `TorClientConfig`.
    pub fn builder() -> TorClientConfigBuilder {
        TorClientConfigBuilder::default()
    }
}