1
//! Define an error type for the tor-proto crate.
2
use std::{sync::Arc, time::Duration};
3
use thiserror::Error;
4
use tor_cell::relaycell::{msg::EndReason, StreamId};
5
use tor_error::{Bug, ErrorKind, HasKind};
6
use tor_linkspec::RelayIdType;
7

            
8
/// An error type for the tor-proto crate.
9
///
10
/// This type should probably be split into several.  There's more
11
/// than one kind of error that can occur while doing something with
12
/// the Tor protocol.
13
#[derive(Error, Debug, Clone)]
14
#[non_exhaustive]
15
pub enum Error {
16
    /// An error that occurred in the tor_bytes crate while decoding an
17
    /// object.
18
    #[error("Unable to parse {object}")]
19
    BytesErr {
20
        /// What we were trying to parse.
21
        object: &'static str,
22
        /// The error that occurred while parsing it.
23
        #[source]
24
        err: tor_bytes::Error,
25
    },
26
    /// An error that occurred from the io system when using a
27
    /// channel.
28
    #[error("IO error on channel with peer")]
29
    ChanIoErr(#[source] Arc<std::io::Error>),
30
    /// An error from the io system that occurred when trying to connect a channel.
31
    #[error("IO error while handshaking with peer")]
32
    HandshakeIoErr(#[source] Arc<std::io::Error>),
33
    /// An error occurred while trying to create or encode a cell.
34
    #[error("Unable to generate or encode {object}")]
35
    CellEncodeErr {
36
        /// The object we were trying to create or encode.
37
        object: &'static str,
38
        /// The error that occurred.
39
        #[source]
40
        err: tor_cell::Error,
41
    },
42
    /// An error occurred while trying to decode or parse a cell.
43
    #[error("Error while parsing {object}")]
44
    CellDecodeErr {
45
        /// The object we were trying to decode.
46
        object: &'static str,
47
        /// The error that occurred.
48
        #[source]
49
        err: tor_cell::Error,
50
    },
51
    /// An error occurred while trying to create or encode some non-cell
52
    /// message.
53
    ///
54
    /// This is likely the result of a bug: either in this crate, or the code
55
    /// that provided the input.
56
    #[error("Problem while encoding {object}")]
57
    EncodeErr {
58
        /// What we were trying to create or encode.
59
        object: &'static str,
60
        /// The error that occurred.
61
        #[source]
62
        err: tor_bytes::EncodeError,
63
    },
64
    /// We found a problem with one of the certificates in the channel
65
    /// handshake.
66
    #[error("Problem with certificate on handshake")]
67
    HandshakeCertErr(#[source] tor_cert::CertError),
68
    /// We tried to produce too much output for a key derivation function.
69
    #[error("Tried to extract too many bytes from a KDF")]
70
    InvalidKDFOutputLength,
71
    /// We tried to encrypt a message to a hop that wasn't there.
72
    #[error("Tried to encrypt a cell for a nonexistent hop")]
73
    NoSuchHop,
74
    /// The authentication information on this cell was completely wrong,
75
    /// or the cell was corrupted.
76
    #[error("Bad relay cell authentication")]
77
    BadCellAuth,
78
    /// A circuit-extension handshake failed due to a mismatched authentication
79
    /// value.
80
    #[error("Circuit-extension handshake authentication failed")]
81
    BadCircHandshakeAuth,
82
    /// Handshake protocol violation.
83
    #[error("Handshake protocol violation: {0}")]
84
    HandshakeProto(String),
85
    /// Handshake broken, maybe due to clock skew.
86
    ///
87
    /// (If the problem can't be due to clock skew, we return HandshakeProto
88
    /// instead.)
89
    #[error("Handshake failed due to expired certificates (possible clock skew)")]
90
    HandshakeCertsExpired {
91
        /// For how long has the circuit been expired?
92
        expired_by: Duration,
93
    },
94
    /// Protocol violation at the channel level, other than at the handshake
95
    /// stage.
96
    #[error("Channel protocol violation: {0}")]
97
    ChanProto(String),
98
    /// Protocol violation at the circuit level
99
    #[error("Circuit protocol violation: {0}")]
100
    CircProto(String),
101
    /// Channel is closed, or became closed while we were trying to do some
102
    /// operation.
103
    #[error("Channel closed")]
104
    ChannelClosed(#[from] ChannelClosed),
105
    /// Circuit is closed, or became closed while we were trying to so some
106
    /// operation.
107
    #[error("Circuit closed")]
108
    CircuitClosed,
109
    /// Can't allocate any more circuit or stream IDs on a channel.
110
    #[error("Too many entries in map: can't allocate ID")]
111
    IdRangeFull,
112
    /// Received a stream request with a stream ID that is already in use for another stream.
113
    #[error("Stream ID {0} is already in use")]
114
    IdUnavailable(StreamId),
115
    /// Received a cell with a stream ID of zero.
116
    #[error("Received a cell with a stream ID of zero")]
117
    StreamIdZero,
118
    /// Couldn't extend a circuit because the extending relay or the
119
    /// target relay refused our request.
120
    #[error("Circuit extension refused: {0}")]
121
    CircRefused(&'static str),
122
    /// Tried to make or use a stream to an invalid destination address.
123
    #[error("Invalid stream target address")]
124
    BadStreamAddress,
125
    /// Received an End cell from the other end of a stream.
126
    #[error("Received an END cell with reason {0}")]
127
    EndReceived(EndReason),
128
    /// Stream was already closed when we tried to use it.
129
    #[error("Stream not connected")]
130
    NotConnected,
131
    /// Stream protocol violation
132
    #[error("Stream protocol violation: {0}")]
133
    StreamProto(String),
134

            
135
    /// Excessive data received from a circuit hop.
136
    #[error("Received too many inbound cells")]
137
    ExcessInboundCells,
138
    /// Tried to send too many cells to a circuit hop.
139
    #[error("Tried to send too many outbound cells")]
140
    ExcessOutboundCells,
141

            
142
    /// Channel does not match target
143
    #[error("Peer identity mismatch: {0}")]
144
    ChanMismatch(String),
145
    /// There was a programming error somewhere in our code, or the calling code.
146
    #[error("Programming error")]
147
    Bug(#[from] tor_error::Bug),
148
    /// Remote DNS lookup failed.
149
    #[error("Remote resolve failed")]
150
    ResolveError(#[source] ResolveError),
151
    /// We tried to do something with a that we couldn't, because of an identity key type
152
    /// that the relay doesn't have.
153
    #[error("Relay has no {0} identity")]
154
    MissingId(RelayIdType),
155
    /// Memory quota error
156
    #[error("memory quota error")]
157
    Memquota(#[from] tor_memquota::Error),
158
}
159

            
160
/// Error which indicates that the channel was closed.
161
#[derive(Error, Debug, Clone)]
162
#[error("Channel closed")]
163
pub struct ChannelClosed;
164

            
165
impl HasKind for ChannelClosed {
166
    fn kind(&self) -> ErrorKind {
167
        ErrorKind::CircuitCollapse
168
    }
169
}
170

            
171
/// Details about an error received while resolving a domain
172
#[derive(Error, Debug, Clone)]
173
#[non_exhaustive]
174
pub enum ResolveError {
175
    /// A transient error which can be retried
176
    #[error("Received retriable transient error")]
177
    Transient,
178
    /// A non transient error, which shouldn't be retried
179
    #[error("Received non-retriable error")]
180
    Nontransient,
181
    /// Could not parse the response properly
182
    #[error("Received unrecognized result")]
183
    Unrecognized,
184
}
185

            
186
impl Error {
187
    /// Create an error from a tor_cell error that has occurred while trying to
188
    /// encode or create something of type `object`
189
    pub(crate) fn from_cell_enc(err: tor_cell::Error, object: &'static str) -> Error {
190
        Error::CellEncodeErr { object, err }
191
    }
192

            
193
    /// Create an error from a tor_cell error that has occurred while trying to
194
    /// decode something of type `object`
195
114
    pub(crate) fn from_cell_dec(err: tor_cell::Error, object: &'static str) -> Error {
196
114
        match err {
197
114
            tor_cell::Error::ChanProto(msg) => Error::ChanProto(msg),
198
            _ => Error::CellDecodeErr { err, object },
199
        }
200
114
    }
201

            
202
    /// Create an error for a tor_bytes error that occurred while parsing
203
    /// something of type `object`.
204
8
    pub(crate) fn from_bytes_err(err: tor_bytes::Error, object: &'static str) -> Error {
205
8
        Error::BytesErr { err, object }
206
8
    }
207

            
208
    /// Create an error for a tor_bytes error that occurred while encoding
209
    /// something of type `object`.
210
    pub(crate) fn from_bytes_enc(err: tor_bytes::EncodeError, object: &'static str) -> Error {
211
        Error::EncodeErr { err, object }
212
    }
213
}
214

            
215
impl From<Error> for std::io::Error {
216
    fn from(err: Error) -> std::io::Error {
217
        use std::io::ErrorKind;
218
        use Error::*;
219
        let kind = match err {
220
            ChanIoErr(e) | HandshakeIoErr(e) => match Arc::try_unwrap(e) {
221
                Ok(e) => return e,
222
                Err(arc) => return std::io::Error::new(arc.kind(), arc),
223
            },
224

            
225
            InvalidKDFOutputLength | NoSuchHop | BadStreamAddress => ErrorKind::InvalidInput,
226

            
227
            NotConnected => ErrorKind::NotConnected,
228

            
229
            EndReceived(end_reason) => end_reason.into(),
230

            
231
            CircuitClosed => ErrorKind::ConnectionReset,
232

            
233
            Memquota { .. } => ErrorKind::OutOfMemory,
234

            
235
            BytesErr { .. }
236
            | BadCellAuth
237
            | BadCircHandshakeAuth
238
            | HandshakeProto(_)
239
            | HandshakeCertErr(_)
240
            | ChanProto(_)
241
            | HandshakeCertsExpired { .. }
242
            | ChannelClosed(_)
243
            | CircProto(_)
244
            | CellDecodeErr { .. }
245
            | CellEncodeErr { .. }
246
            | EncodeErr { .. }
247
            | ChanMismatch(_)
248
            | StreamProto(_)
249
            | MissingId(_)
250
            | IdUnavailable(_)
251
            | StreamIdZero
252
            | ExcessInboundCells
253
            | ExcessOutboundCells => ErrorKind::InvalidData,
254

            
255
            Bug(ref e) if e.kind() == tor_error::ErrorKind::BadApiUsage => ErrorKind::InvalidData,
256

            
257
            IdRangeFull | CircRefused(_) | ResolveError(_) | Bug(_) => ErrorKind::Other,
258
        };
259
        std::io::Error::new(kind, err)
260
    }
261
}
262

            
263
impl HasKind for Error {
264
    fn kind(&self) -> ErrorKind {
265
        use tor_bytes::Error as BytesError;
266
        use Error as E;
267
        use ErrorKind as EK;
268
        match self {
269
            E::BytesErr {
270
                err: BytesError::Bug(e),
271
                ..
272
            } => e.kind(),
273
            E::BytesErr { .. } => EK::TorProtocolViolation,
274
            E::ChanIoErr(_) => EK::LocalNetworkError,
275
            E::HandshakeIoErr(_) => EK::TorAccessFailed,
276
            E::HandshakeCertErr(_) => EK::TorProtocolViolation,
277
            E::CellEncodeErr { err, .. } => err.kind(),
278
            E::CellDecodeErr { err, .. } => err.kind(),
279
            E::EncodeErr { .. } => EK::BadApiUsage,
280
            E::InvalidKDFOutputLength => EK::Internal,
281
            E::NoSuchHop => EK::BadApiUsage,
282
            E::BadCellAuth => EK::TorProtocolViolation,
283
            E::BadCircHandshakeAuth => EK::TorProtocolViolation,
284
            E::HandshakeProto(_) => EK::TorAccessFailed,
285
            E::HandshakeCertsExpired { .. } => EK::ClockSkew,
286
            E::ChanProto(_) => EK::TorProtocolViolation,
287
            E::CircProto(_) => EK::TorProtocolViolation,
288
            E::ChannelClosed(e) => e.kind(),
289
            E::CircuitClosed => EK::CircuitCollapse,
290
            E::IdRangeFull => EK::BadApiUsage,
291
            E::CircRefused(_) => EK::CircuitRefused,
292
            E::BadStreamAddress => EK::BadApiUsage,
293
            E::EndReceived(reason) => reason.kind(),
294
            E::NotConnected => EK::BadApiUsage,
295
            E::StreamProto(_) => EK::TorProtocolViolation,
296
            E::ChanMismatch(_) => EK::RelayIdMismatch,
297
            E::ResolveError(ResolveError::Nontransient) => EK::RemoteHostNotFound,
298
            E::ResolveError(ResolveError::Transient) => EK::RemoteHostResolutionFailed,
299
            E::ResolveError(ResolveError::Unrecognized) => EK::RemoteHostResolutionFailed,
300
            E::MissingId(_) => EK::BadApiUsage,
301
            E::IdUnavailable(_) => EK::BadApiUsage,
302
            E::StreamIdZero => EK::BadApiUsage,
303
            E::ExcessInboundCells => EK::TorProtocolViolation,
304
            E::ExcessOutboundCells => EK::Internal,
305
            E::Memquota(err) => err.kind(),
306
            E::Bug(e) => e.kind(),
307
        }
308
    }
309
}
310

            
311
/// Internal type: Error return value from reactor's run_once
312
/// function: indicates an error or a shutdown.
313
#[derive(Debug)]
314
pub(crate) enum ReactorError {
315
    /// The reactor should shut down with an abnormal exit condition.
316
    Err(Error),
317
    /// The reactor should shut down without an error, since all is well.
318
    Shutdown,
319
}
320

            
321
impl From<Error> for ReactorError {
322
244
    fn from(e: Error) -> ReactorError {
323
244
        ReactorError::Err(e)
324
244
    }
325
}
326

            
327
impl From<ChannelClosed> for ReactorError {
328
    fn from(e: ChannelClosed) -> ReactorError {
329
        ReactorError::Err(e.into())
330
    }
331
}
332

            
333
impl From<Bug> for ReactorError {
334
    fn from(e: Bug) -> ReactorError {
335
        ReactorError::Err(e.into())
336
    }
337
}
338

            
339
#[cfg(test)]
340
impl ReactorError {
341
    /// Tests only: assert that this is an Error, and return it.
342
48
    pub(crate) fn unwrap_err(self) -> Error {
343
48
        match self {
344
            ReactorError::Shutdown => panic!(),
345
48
            ReactorError::Err(e) => e,
346
48
        }
347
48
    }
348
}
349

            
350
/// An error type for client-side conflux handshakes.
351
#[derive(Debug)]
352
#[cfg(feature = "conflux")]
353
#[allow(unused)] // TODO(conflux): remove
354
pub(crate) enum ConfluxHandshakeError {
355
    /// Timeout while waiting for CONFLUX_LINKED response.
356
    Timeout,
357
    /// An error that occurred while sending the CONFLUX_LINK message.
358
    Link(Error),
359
    /// The channel was closed.
360
    ChannelClosed,
361
}