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("Problem with certificate on handshake")]
71 HandshakeCertErr(#[source] tor_cert::CertError),
72 #[error("Tried to extract too many bytes from a KDF")]
74 InvalidKDFOutputLength,
75 #[error("Tried to encrypt a cell for a nonexistent hop")]
77 NoSuchHop,
78 #[error("Bad relay cell authentication")]
81 BadCellAuth,
82 #[error("Circuit-extension handshake authentication failed")]
85 BadCircHandshakeAuth,
86 #[error("Handshake protocol violation: {0}")]
88 HandshakeProto(String),
89 #[error("Handshake failed due to expired certificates (possible clock skew)")]
94 HandshakeCertsExpired {
95 expired_by: Duration,
97 },
98 #[error("Channel protocol violation: {0}")]
101 ChanProto(String),
102 #[error("Circuit protocol violation: {0}")]
104 CircProto(String),
105 #[error("Channel closed")]
108 ChannelClosed(#[from] ChannelClosed),
109 #[error("Circuit closed")]
112 CircuitClosed,
113 #[error("Too many entries in map: can't allocate ID")]
115 IdRangeFull,
116 #[error("Stream ID {0} is already in use")]
118 IdUnavailable(StreamId),
119 #[error("Received a cell with a stream ID of zero")]
121 StreamIdZero,
122 #[error(
124 "Received a cell from {} on a closed or non-existent stream {}. \
125 Either they are violating the protocol, or we are expiring streams too aggressively",
126 src,
127 streamid
128 )]
129 UnknownStream {
130 src: Sensitive<PathEntry>,
132 streamid: StreamId,
134 },
135 #[error("Circuit extension refused: {0}")]
138 CircRefused(&'static str),
139 #[error("Invalid stream target address")]
141 BadStreamAddress,
142 #[error("Received an END cell with reason {0}")]
144 EndReceived(EndReason),
145 #[error("Stream not connected")]
147 NotConnected,
148 #[error("Stream protocol violation: {0}")]
150 StreamProto(String),
151
152 #[error("Received too many inbound cells")]
154 ExcessInboundCells,
155 #[error("Tried to send too many outbound cells")]
157 ExcessOutboundCells,
158
159 #[error("Received unexpected or excessive circuit padding from {}", _1.display())]
161 ExcessPadding(#[source] ExcessPadding, HopNum),
162
163 #[error("Peer identity mismatch: {0}")]
165 ChanMismatch(String),
166 #[error("Programming error")]
168 Bug(#[from] tor_error::Bug),
169 #[error("Remote resolve failed")]
171 ResolveError(#[source] ResolveError),
172 #[error("Relay has no {0} identity")]
175 MissingId(RelayIdType),
176 #[error("memory quota error")]
178 Memquota(#[from] tor_memquota::Error),
179}
180
181#[derive(Error, Debug, Clone)]
183#[error("Channel closed")]
184pub struct ChannelClosed;
185
186impl HasKind for ChannelClosed {
187 fn kind(&self) -> ErrorKind {
188 ErrorKind::CircuitCollapse
189 }
190}
191
192#[derive(Error, Debug, Clone)]
194#[non_exhaustive]
195pub enum ResolveError {
196 #[error("Received retriable transient error")]
198 Transient,
199 #[error("Received non-retriable error")]
201 Nontransient,
202 #[error("Received unrecognized result")]
204 Unrecognized,
205}
206
207impl Error {
208 pub(crate) fn from_cell_enc(err: tor_cell::Error, object: &'static str) -> Error {
211 Error::CellEncodeErr { object, err }
212 }
213
214 pub(crate) fn from_bytes_err(err: tor_bytes::Error, object: &'static str) -> Error {
217 Error::BytesErr { err, object }
218 }
219
220 pub(crate) fn from_bytes_enc(err: tor_bytes::EncodeError, object: &'static str) -> Error {
223 Error::EncodeErr { err, object }
224 }
225}
226
227impl From<std::io::Error> for Error {
228 fn from(err: std::io::Error) -> Self {
229 Self::ChanIoErr(Arc::new(err))
230 }
231}
232
233impl From<Error> for std::io::Error {
234 fn from(err: Error) -> std::io::Error {
235 use Error::*;
236 use std::io::ErrorKind;
237 let kind = match err {
238 ChanIoErr(e) | HandshakeIoErr(e) => match Arc::try_unwrap(e) {
239 Ok(e) => return e,
240 Err(arc) => return std::io::Error::new(arc.kind(), arc),
241 },
242
243 InvalidKDFOutputLength | NoSuchHop | BadStreamAddress => ErrorKind::InvalidInput,
244
245 NotConnected => ErrorKind::NotConnected,
246
247 EndReceived(end_reason) => end_reason.into(),
248
249 CircuitClosed => ErrorKind::ConnectionReset,
250
251 Memquota { .. } => ErrorKind::OutOfMemory,
252
253 BytesErr { .. }
254 | BadCellAuth
255 | BadCircHandshakeAuth
256 | HandshakeProto(_)
257 | HandshakeCertErr(_)
258 | ChanProto(_)
259 | HandshakeCertsExpired { .. }
260 | ChannelClosed(_)
261 | CircProto(_)
262 | CellDecodeErr { .. }
263 | CellEncodeErr { .. }
264 | EncodeErr { .. }
265 | ChanMismatch(_)
266 | StreamProto(_)
267 | MissingId(_)
268 | IdUnavailable(_)
269 | StreamIdZero
270 | UnknownStream { .. }
271 | ExcessInboundCells
272 | ExcessOutboundCells
273 | ExcessPadding(_, _) => ErrorKind::InvalidData,
274
275 Bug(ref e) if e.kind() == tor_error::ErrorKind::BadApiUsage => ErrorKind::InvalidData,
276
277 IdRangeFull | CircRefused(_) | ResolveError(_) | Bug(_) => ErrorKind::Other,
278 };
279 std::io::Error::new(kind, err)
280 }
281}
282
283impl HasKind for Error {
284 fn kind(&self) -> ErrorKind {
285 use Error as E;
286 use ErrorKind as EK;
287 use tor_bytes::Error as BytesError;
288 match self {
289 E::BytesErr {
290 err: BytesError::Bug(e),
291 ..
292 } => e.kind(),
293 E::BytesErr { .. } => EK::TorProtocolViolation,
294 E::ChanIoErr(_) => EK::LocalNetworkError,
295 E::HandshakeIoErr(_) => EK::TorAccessFailed,
296 E::HandshakeCertErr(_) => EK::TorProtocolViolation,
297 E::CellEncodeErr { err, .. } => err.kind(),
298 E::CellDecodeErr { err, .. } => err.kind(),
299 E::EncodeErr { .. } => EK::BadApiUsage,
300 E::InvalidKDFOutputLength => EK::Internal,
301 E::NoSuchHop => EK::BadApiUsage,
302 E::BadCellAuth => EK::TorProtocolViolation,
303 E::BadCircHandshakeAuth => EK::TorProtocolViolation,
304 E::HandshakeProto(_) => EK::TorAccessFailed,
305 E::HandshakeCertsExpired { .. } => EK::ClockSkew,
306 E::ChanProto(_) => EK::TorProtocolViolation,
307 E::CircProto(_) => EK::TorProtocolViolation,
308 E::ChannelClosed(e) => e.kind(),
309 E::CircuitClosed => EK::CircuitCollapse,
310 E::IdRangeFull => EK::BadApiUsage,
311 E::CircRefused(_) => EK::CircuitRefused,
312 E::BadStreamAddress => EK::BadApiUsage,
313 E::EndReceived(reason) => reason.kind(),
314 E::NotConnected => EK::BadApiUsage,
315 E::StreamProto(_) => EK::TorProtocolViolation,
316 E::ChanMismatch(_) => EK::RelayIdMismatch,
317 E::ResolveError(ResolveError::Nontransient) => EK::RemoteHostNotFound,
318 E::ResolveError(ResolveError::Transient) => EK::RemoteHostResolutionFailed,
319 E::ResolveError(ResolveError::Unrecognized) => EK::RemoteHostResolutionFailed,
320 E::MissingId(_) => EK::BadApiUsage,
321 E::IdUnavailable(_) => EK::BadApiUsage,
322 E::StreamIdZero => EK::BadApiUsage,
323 E::UnknownStream { .. } => EK::TorProtocolViolation,
324 E::ExcessInboundCells => EK::TorProtocolViolation,
325 E::ExcessOutboundCells => EK::Internal,
326 E::ExcessPadding(_, _) => EK::TorProtocolViolation,
327 E::Memquota(err) => err.kind(),
328 E::Bug(e) => e.kind(),
329 }
330 }
331}
332
333#[derive(Debug)]
336pub(crate) enum ReactorError {
337 Err(Error),
339 Shutdown,
341}
342
343impl From<Error> for ReactorError {
344 fn from(e: Error) -> ReactorError {
345 ReactorError::Err(e)
346 }
347}
348
349impl From<ChannelClosed> for ReactorError {
350 fn from(e: ChannelClosed) -> ReactorError {
351 ReactorError::Err(e.into())
352 }
353}
354
355impl From<Bug> for ReactorError {
356 fn from(e: Bug) -> ReactorError {
357 ReactorError::Err(e.into())
358 }
359}
360
361#[cfg(test)]
362impl ReactorError {
363 pub(crate) fn unwrap_err(self) -> Error {
365 match self {
366 ReactorError::Shutdown => panic!(),
367 ReactorError::Err(e) => e,
368 }
369 }
370}
371
372#[derive(Debug)]
374#[cfg(feature = "conflux")]
375#[allow(unused)] pub(crate) enum ConfluxHandshakeError {
377 Timeout,
379 Link(Error),
381 ChannelClosed,
383}
384
385#[derive(Debug, Clone, Error)]
387#[non_exhaustive]
388pub enum ExcessPadding {
389 #[error("Padding received when not negotiated with given hop")]
391 NoPaddingNegotiated,
392 #[error("Received padding in excess of negotiated framework's limit")]
394 PaddingExceedsLimit,
395}