/ crates / tor-socksproto / src / err.rs
err.rs
 1  //! Declare an error type for tor_socksproto
 2  use std::borrow::Cow;
 3  
 4  use thiserror::Error;
 5  
 6  use tor_error::{ErrorKind, HasKind};
 7  
 8  /// An error that occurs while negotiating a SOCKS handshake.
 9  #[derive(Clone, Error, Debug)]
10  #[non_exhaustive]
11  pub enum Error {
12      /// The SOCKS client didn't implement SOCKS correctly.
13      ///
14      /// (Or, more likely, we didn't account for its behavior.)
15      #[error("SOCKS protocol syntax violation")]
16      Syntax,
17  
18      /// Failed to decode a SOCKS message.
19      #[error("Error decoding SOCKS message")]
20      Decode(#[from] tor_bytes::Error),
21  
22      /// The SOCKS client declared a SOCKS version number that isn't
23      /// one we support.
24      ///
25      /// In all likelihood, this is somebody trying to use the port for
26      /// some protocol other than SOCKS.
27      #[error("Unrecognized SOCKS protocol version {0}")]
28      BadProtocol(u8),
29  
30      /// The SOCKS client tried to use a SOCKS feature that we don't
31      /// support at all.
32      #[error("SOCKS feature ({0}) not implemented")]
33      NotImplemented(Cow<'static, str>),
34  
35      /// Tried to progress the SOCKS handshake when it was already
36      /// finished.  This is a programming error.
37      #[error("SOCKS handshake was finished; no need to call this again")]
38      AlreadyFinished(tor_error::Bug),
39  
40      /// The SOCKS proxy refused our authentication.
41      #[error("SOCKS Authentication failed")]
42      AuthRejected,
43  
44      /// During the protocol exchange, we needed to handle a handshake bigger than our buffer
45      #[error("SOCKS protocol message size limit {limit} exceeded")]
46      MessageTooLong {
47          /// The limit in bytes
48          limit: usize,
49      },
50  
51      /// Peer closed connection during SOCKS handshake
52      #[error("peer closed connection during SOCKS handshake")]
53      UnexpectedEof,
54  
55      /// The peer sent payload data too early
56      ///
57      /// The peer sent data after its part of the protocol exchange,
58      /// without waiting for our side of it to complete,
59      /// in circumstances where we consider that a protocol violation by the peer.
60      ///
61      /// Returned only by
62      /// [`Finished::into_output_forbid_pipelining`](crate::Finished::into_output_forbid_pipelining).
63      #[error("SOCKS peer inappropriately pipelined (optimistically sent) payload data")]
64      ForbiddenPipelining,
65  
66      /// The program (perhaps this module, perhaps Arti, perhaps the caller) is buggy
67      #[error("Bug while handling SOCKS handshake")]
68      Bug(#[from] tor_error::Bug),
69  }
70  
71  // Note: at present, tor-socksproto isn't used in any settings where ErrorKind
72  // is used.  This is provided for future-proofing, since someday we'll want to
73  // have SOCKS protocol support internally as well as in the `arti` proxy.
74  impl HasKind for Error {
75      fn kind(&self) -> ErrorKind {
76          use Error as E;
77          use ErrorKind as EK;
78          match self {
79              E::Decode(tor_bytes::Error::Incomplete { .. }) => {
80                  // This variant should always get converted before a user can
81                  // see it.
82                  EK::Internal
83              }
84              E::Syntax | E::Decode(_) | E::BadProtocol(_) => EK::LocalProtocolViolation,
85              E::NotImplemented(_) => EK::NotImplemented,
86              E::AuthRejected => EK::LocalProtocolViolation,
87              E::UnexpectedEof => EK::LocalProtocolViolation,
88              E::ForbiddenPipelining => EK::LocalProtocolViolation,
89              E::MessageTooLong { .. } => EK::Internal, // We should select a buffer big enough!
90              E::AlreadyFinished(e) => e.kind(),
91              E::Bug(e) => e.kind(),
92          }
93      }
94  }