1use safelog::Sensitive;
3use std::{sync::Arc, time::Duration};
4use thiserror::Error;
5use tor_cell::relaycell::{StreamId, msg::EndReason};
6use tor_error::{Bug, ErrorKind, HasKind};
7use tor_linkspec::RelayIdType;
8
9use crate::HopNum;
10use crate::client::circuit::PathEntry;
11
12#[derive(Error, Debug, Clone)]
18#[non_exhaustive]
19pub enum Error {
20 #[error("Unable to parse {object}")]
23 BytesErr {
24 object: &'static str,
26 #[source]
28 err: tor_bytes::Error,
29 },
30 #[error("IO error on channel with peer")]
33 ChanIoErr(#[source] Arc<std::io::Error>),
34 #[error("IO error while handshaking with peer")]
36 HandshakeIoErr(#[source] Arc<std::io::Error>),
37 #[error("Unable to generate or encode {object}")]
39 CellEncodeErr {
40 object: &'static str,
42 #[source]
44 err: tor_cell::Error,
45 },
46 #[error("Error while parsing {object}")]
48 CellDecodeErr {
49 object: &'static str,
51 #[source]
53 err: tor_cell::Error,
54 },
55 #[error("Problem while encoding {object}")]
61 EncodeErr {
62 object: &'static str,
64 #[source]
66 err: tor_bytes::EncodeError,
67 },
68 #[error("Error while parsing {object}")]
70 #[cfg(feature = "relay")]
71 LinkspecDecodeErr {
72 object: &'static str,
74 #[source]
76 err: tor_linkspec::decode::ChanTargetDecodeError,
77 },
78 #[error("Problem with certificate on handshake")]
81 HandshakeCertErr(#[source] tor_cert::CertError),
82 #[error("Tried to extract too many bytes from a KDF")]
84 InvalidKDFOutputLength,
85 #[error("Tried to encrypt a cell for a nonexistent hop")]
87 NoSuchHop,
88 #[error("Bad relay cell authentication")]
91 BadCellAuth,
92 #[error("Circuit-extension handshake authentication failed")]
95 BadCircHandshakeAuth,
96 #[error("Handshake protocol violation: {0}")]
98 HandshakeProto(String),
99 #[error("Handshake failed due to expired certificates (possible clock skew)")]
104 HandshakeCertsExpired {
105 expired_by: Duration,
107 },
108 #[error("Channel protocol violation: {0}")]
111 ChanProto(String),
112 #[error("Circuit protocol violation: {0}")]
114 CircProto(String),
115 #[error("Channel closed")]
118 ChannelClosed(#[from] ChannelClosed),
119 #[error("Circuit closed")]
122 CircuitClosed,
123 #[error("Too many entries in map: can't allocate ID")]
125 IdRangeFull,
126 #[error("Stream ID {0} is already in use")]
128 IdUnavailable(StreamId),
129 #[error("Received a cell with a stream ID of zero")]
131 StreamIdZero,
132 #[error(
134 "Received a cell from {} on a closed or non-existent stream {}. \
135 Either they are violating the protocol, or we are expiring streams too aggressively",
136 src,
137 streamid
138 )]
139 UnknownStream {
140 src: Sensitive<PathEntry>,
142 streamid: StreamId,
144 },
145 #[error("Circuit extension refused: {0}")]
148 CircRefused(&'static str),
149 #[error("Invalid stream target address")]
151 BadStreamAddress,
152 #[error("Received an END cell with reason {0}")]
154 EndReceived(EndReason),
155 #[error("Stream not connected")]
157 NotConnected,
158 #[error("Stream protocol violation: {0}")]
160 StreamProto(String),
161
162 #[error("Received too many inbound cells")]
164 ExcessInboundCells,
165 #[error("Tried to send too many outbound cells")]
167 ExcessOutboundCells,
168
169 #[error("Received unexpected or excessive circuit padding from {}", _1.display())]
171 ExcessPadding(#[source] ExcessPadding, HopNum),
172
173 #[error("Peer identity mismatch: {0}")]
175 ChanMismatch(String),
176 #[error("Programming error")]
178 Bug(#[from] tor_error::Bug),
179 #[error("Remote resolve failed")]
181 ResolveError(#[source] ResolveError),
182 #[error("Relay has no {0} identity")]
185 MissingId(RelayIdType),
186 #[error("memory quota error")]
188 Memquota(#[from] tor_memquota::Error),
189 #[cfg(feature = "relay")]
192 #[error("Authentication type {0} is unsupported")]
193 UnsupportedAuth(u16),
194}
195
196#[derive(Error, Debug, Clone)]
198#[error("Channel closed")]
199pub struct ChannelClosed;
200
201impl HasKind for ChannelClosed {
202 fn kind(&self) -> ErrorKind {
203 ErrorKind::CircuitCollapse
204 }
205}
206
207#[derive(Error, Debug, Clone)]
209#[non_exhaustive]
210pub enum ResolveError {
211 #[error("Received retriable transient error")]
213 Transient,
214 #[error("Received non-retriable error")]
216 Nontransient,
217 #[error("Received unrecognized result")]
219 Unrecognized,
220}
221
222impl Error {
223 pub(crate) fn from_cell_enc(err: tor_cell::Error, object: &'static str) -> Error {
226 Error::CellEncodeErr { object, err }
227 }
228
229 pub(crate) fn from_bytes_err(err: tor_bytes::Error, object: &'static str) -> Error {
232 Error::BytesErr { err, object }
233 }
234
235 pub(crate) fn from_bytes_enc(err: tor_bytes::EncodeError, object: &'static str) -> Error {
238 Error::EncodeErr { err, object }
239 }
240}
241
242impl From<std::io::Error> for Error {
243 fn from(err: std::io::Error) -> Self {
244 Self::ChanIoErr(Arc::new(err))
245 }
246}
247
248impl From<Error> for std::io::Error {
249 fn from(err: Error) -> std::io::Error {
250 use Error::*;
251 use std::io::ErrorKind;
252 let kind = match err {
253 ChanIoErr(e) | HandshakeIoErr(e) => match Arc::try_unwrap(e) {
254 Ok(e) => return e,
255 Err(arc) => return std::io::Error::new(arc.kind(), arc),
256 },
257
258 InvalidKDFOutputLength | NoSuchHop | BadStreamAddress => ErrorKind::InvalidInput,
259
260 NotConnected => ErrorKind::NotConnected,
261
262 EndReceived(end_reason) => end_reason.into(),
263
264 CircuitClosed => ErrorKind::ConnectionReset,
265
266 Memquota { .. } => ErrorKind::OutOfMemory,
267
268 BytesErr { .. }
269 | BadCellAuth
270 | BadCircHandshakeAuth
271 | HandshakeProto(_)
272 | HandshakeCertErr(_)
273 | ChanProto(_)
274 | HandshakeCertsExpired { .. }
275 | ChannelClosed(_)
276 | CircProto(_)
277 | CellDecodeErr { .. }
278 | CellEncodeErr { .. }
279 | EncodeErr { .. }
280 | ChanMismatch(_)
281 | StreamProto(_)
282 | MissingId(_)
283 | IdUnavailable(_)
284 | StreamIdZero
285 | UnknownStream { .. }
286 | ExcessInboundCells
287 | ExcessOutboundCells
288 | ExcessPadding(_, _) => ErrorKind::InvalidData,
289
290 #[cfg(feature = "relay")]
291 LinkspecDecodeErr { .. } => ErrorKind::InvalidData,
292 #[cfg(feature = "relay")]
293 UnsupportedAuth(_) => ErrorKind::Unsupported,
294
295 Bug(ref e) if e.kind() == tor_error::ErrorKind::BadApiUsage => ErrorKind::InvalidData,
296
297 IdRangeFull | CircRefused(_) | ResolveError(_) | Bug(_) => ErrorKind::Other,
298 };
299 std::io::Error::new(kind, err)
300 }
301}
302
303impl HasKind for Error {
304 fn kind(&self) -> ErrorKind {
305 use Error as E;
306 use ErrorKind as EK;
307 use tor_bytes::Error as BytesError;
308 match self {
309 E::BytesErr {
310 err: BytesError::Bug(e),
311 ..
312 } => e.kind(),
313 E::BytesErr { .. } => EK::TorProtocolViolation,
314 E::ChanIoErr(_) => EK::LocalNetworkError,
315 E::HandshakeIoErr(_) => EK::TorAccessFailed,
316 E::HandshakeCertErr(_) => EK::TorProtocolViolation,
317 E::CellEncodeErr { err, .. } => err.kind(),
318 E::CellDecodeErr { err, .. } => err.kind(),
319 #[cfg(feature = "relay")]
320 E::LinkspecDecodeErr { .. } => EK::TorProtocolViolation,
321 E::EncodeErr { .. } => EK::BadApiUsage,
322 E::InvalidKDFOutputLength => EK::Internal,
323 E::NoSuchHop => EK::BadApiUsage,
324 E::BadCellAuth => EK::TorProtocolViolation,
325 E::BadCircHandshakeAuth => EK::TorProtocolViolation,
326 E::HandshakeProto(_) => EK::TorAccessFailed,
327 E::HandshakeCertsExpired { .. } => EK::ClockSkew,
328 E::ChanProto(_) => EK::TorProtocolViolation,
329 E::CircProto(_) => EK::TorProtocolViolation,
330 E::ChannelClosed(e) => e.kind(),
331 E::CircuitClosed => EK::CircuitCollapse,
332 E::IdRangeFull => EK::BadApiUsage,
333 E::CircRefused(_) => EK::CircuitRefused,
334 E::BadStreamAddress => EK::BadApiUsage,
335 E::EndReceived(reason) => reason.kind(),
336 E::NotConnected => EK::BadApiUsage,
337 E::StreamProto(_) => EK::TorProtocolViolation,
338 E::ChanMismatch(_) => EK::RelayIdMismatch,
339 E::ResolveError(ResolveError::Nontransient) => EK::RemoteHostNotFound,
340 E::ResolveError(ResolveError::Transient) => EK::RemoteHostResolutionFailed,
341 E::ResolveError(ResolveError::Unrecognized) => EK::RemoteHostResolutionFailed,
342 E::MissingId(_) => EK::BadApiUsage,
343 E::IdUnavailable(_) => EK::BadApiUsage,
344 E::StreamIdZero => EK::BadApiUsage,
345 E::UnknownStream { .. } => EK::TorProtocolViolation,
346 E::ExcessInboundCells => EK::TorProtocolViolation,
347 E::ExcessOutboundCells => EK::Internal,
348 E::ExcessPadding(_, _) => EK::TorProtocolViolation,
349 E::Memquota(err) => err.kind(),
350 E::Bug(e) => e.kind(),
351 #[cfg(feature = "relay")]
352 E::UnsupportedAuth(_) => EK::RemoteProtocolViolation,
353 }
354 }
355}
356
357#[derive(Debug)]
360pub(crate) enum ReactorError {
361 Err(Error),
363 Shutdown,
365}
366
367impl From<Error> for ReactorError {
368 fn from(e: Error) -> ReactorError {
369 ReactorError::Err(e)
370 }
371}
372
373impl From<ChannelClosed> for ReactorError {
374 fn from(e: ChannelClosed) -> ReactorError {
375 ReactorError::Err(e.into())
376 }
377}
378
379impl From<Bug> for ReactorError {
380 fn from(e: Bug) -> ReactorError {
381 ReactorError::Err(e.into())
382 }
383}
384
385#[cfg(test)]
386impl ReactorError {
387 pub(crate) fn unwrap_err(self) -> Error {
389 match self {
390 ReactorError::Shutdown => panic!(),
391 ReactorError::Err(e) => e,
392 }
393 }
394}
395
396#[derive(Debug)]
398#[cfg(feature = "conflux")]
399#[allow(unused)] pub(crate) enum ConfluxHandshakeError {
401 Timeout,
403 Link(Error),
405 ChannelClosed,
407}
408
409#[derive(Debug, Clone, Error)]
411#[non_exhaustive]
412pub enum ExcessPadding {
413 #[error("Padding received when not negotiated with given hop")]
415 NoPaddingNegotiated,
416 #[error("Received padding in excess of negotiated framework's limit")]
418 PaddingExceedsLimit,
419}