Coverage for /pythoncovmergedfiles/medio/medio/src/paramiko/paramiko/ssh_exception.py: 52%

63 statements  

« prev     ^ index     » next       coverage.py v7.2.2, created at 2023-03-26 06:36 +0000

1# Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com> 

2# 

3# This file is part of paramiko. 

4# 

5# Paramiko is free software; you can redistribute it and/or modify it under the 

6# terms of the GNU Lesser General Public License as published by the Free 

7# Software Foundation; either version 2.1 of the License, or (at your option) 

8# any later version. 

9# 

10# Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY 

11# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 

12# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 

13# details. 

14# 

15# You should have received a copy of the GNU Lesser General Public License 

16# along with Paramiko; if not, write to the Free Software Foundation, Inc., 

17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 

18 

19import socket 

20 

21 

22class SSHException(Exception): 

23 """ 

24 Exception raised by failures in SSH2 protocol negotiation or logic errors. 

25 """ 

26 

27 pass 

28 

29 

30class AuthenticationException(SSHException): 

31 """ 

32 Exception raised when authentication failed for some reason. It may be 

33 possible to retry with different credentials. (Other classes specify more 

34 specific reasons.) 

35 

36 .. versionadded:: 1.6 

37 """ 

38 

39 pass 

40 

41 

42class PasswordRequiredException(AuthenticationException): 

43 """ 

44 Exception raised when a password is needed to unlock a private key file. 

45 """ 

46 

47 pass 

48 

49 

50class BadAuthenticationType(AuthenticationException): 

51 """ 

52 Exception raised when an authentication type (like password) is used, but 

53 the server isn't allowing that type. (It may only allow public-key, for 

54 example.) 

55 

56 .. versionadded:: 1.1 

57 """ 

58 

59 allowed_types = [] 

60 

61 # TODO 4.0: remove explanation kwarg 

62 def __init__(self, explanation, types): 

63 # TODO 4.0: remove this supercall unless it's actually required for 

64 # pickling (after fixing pickling) 

65 AuthenticationException.__init__(self, explanation, types) 

66 self.explanation = explanation 

67 self.allowed_types = types 

68 

69 def __str__(self): 

70 return "{}; allowed types: {!r}".format( 

71 self.explanation, self.allowed_types 

72 ) 

73 

74 

75class PartialAuthentication(AuthenticationException): 

76 """ 

77 An internal exception thrown in the case of partial authentication. 

78 """ 

79 

80 allowed_types = [] 

81 

82 def __init__(self, types): 

83 AuthenticationException.__init__(self, types) 

84 self.allowed_types = types 

85 

86 def __str__(self): 

87 return "Partial authentication; allowed types: {!r}".format( 

88 self.allowed_types 

89 ) 

90 

91 

92class ChannelException(SSHException): 

93 """ 

94 Exception raised when an attempt to open a new `.Channel` fails. 

95 

96 :param int code: the error code returned by the server 

97 

98 .. versionadded:: 1.6 

99 """ 

100 

101 def __init__(self, code, text): 

102 SSHException.__init__(self, code, text) 

103 self.code = code 

104 self.text = text 

105 

106 def __str__(self): 

107 return "ChannelException({!r}, {!r})".format(self.code, self.text) 

108 

109 

110class BadHostKeyException(SSHException): 

111 """ 

112 The host key given by the SSH server did not match what we were expecting. 

113 

114 :param str hostname: the hostname of the SSH server 

115 :param PKey got_key: the host key presented by the server 

116 :param PKey expected_key: the host key expected 

117 

118 .. versionadded:: 1.6 

119 """ 

120 

121 def __init__(self, hostname, got_key, expected_key): 

122 SSHException.__init__(self, hostname, got_key, expected_key) 

123 self.hostname = hostname 

124 self.key = got_key 

125 self.expected_key = expected_key 

126 

127 def __str__(self): 

128 msg = "Host key for server '{}' does not match: got '{}', expected '{}'" # noqa 

129 return msg.format( 

130 self.hostname, 

131 self.key.get_base64(), 

132 self.expected_key.get_base64(), 

133 ) 

134 

135 

136class IncompatiblePeer(SSHException): 

137 """ 

138 A disagreement arose regarding an algorithm required for key exchange. 

139 

140 .. versionadded:: 2.9 

141 """ 

142 

143 # TODO 4.0: consider making this annotate w/ 1..N 'missing' algorithms, 

144 # either just the first one that would halt kex, or even updating the 

145 # Transport logic so we record /all/ that /could/ halt kex. 

146 # TODO: update docstrings where this may end up raised so they are more 

147 # specific. 

148 pass 

149 

150 

151class ProxyCommandFailure(SSHException): 

152 """ 

153 The "ProxyCommand" found in the .ssh/config file returned an error. 

154 

155 :param str command: The command line that is generating this exception. 

156 :param str error: The error captured from the proxy command output. 

157 """ 

158 

159 def __init__(self, command, error): 

160 SSHException.__init__(self, command, error) 

161 self.command = command 

162 self.error = error 

163 

164 def __str__(self): 

165 return 'ProxyCommand("{}") returned nonzero exit status: {}'.format( 

166 self.command, self.error 

167 ) 

168 

169 

170class NoValidConnectionsError(socket.error): 

171 """ 

172 Multiple connection attempts were made and no families succeeded. 

173 

174 This exception class wraps multiple "real" underlying connection errors, 

175 all of which represent failed connection attempts. Because these errors are 

176 not guaranteed to all be of the same error type (i.e. different errno, 

177 `socket.error` subclass, message, etc) we expose a single unified error 

178 message and a ``None`` errno so that instances of this class match most 

179 normal handling of `socket.error` objects. 

180 

181 To see the wrapped exception objects, access the ``errors`` attribute. 

182 ``errors`` is a dict whose keys are address tuples (e.g. ``('127.0.0.1', 

183 22)``) and whose values are the exception encountered trying to connect to 

184 that address. 

185 

186 It is implied/assumed that all the errors given to a single instance of 

187 this class are from connecting to the same hostname + port (and thus that 

188 the differences are in the resolution of the hostname - e.g. IPv4 vs v6). 

189 

190 .. versionadded:: 1.16 

191 """ 

192 

193 def __init__(self, errors): 

194 """ 

195 :param dict errors: 

196 The errors dict to store, as described by class docstring. 

197 """ 

198 addrs = sorted(errors.keys()) 

199 body = ", ".join([x[0] for x in addrs[:-1]]) 

200 tail = addrs[-1][0] 

201 if body: 

202 msg = "Unable to connect to port {0} on {1} or {2}" 

203 else: 

204 msg = "Unable to connect to port {0} on {2}" 

205 super().__init__( 

206 None, msg.format(addrs[0][1], body, tail) # stand-in for errno 

207 ) 

208 self.errors = errors 

209 

210 def __reduce__(self): 

211 return (self.__class__, (self.errors,)) 

212 

213 

214class CouldNotCanonicalize(SSHException): 

215 """ 

216 Raised when hostname canonicalization fails & fallback is disabled. 

217 

218 .. versionadded:: 2.7 

219 """ 

220 

221 pass 

222 

223 

224class ConfigParseError(SSHException): 

225 """ 

226 A fatal error was encountered trying to parse SSH config data. 

227 

228 Typically this means a config file violated the ``ssh_config`` 

229 specification in a manner that requires exiting immediately, such as not 

230 matching ``key = value`` syntax or misusing certain ``Match`` keywords. 

231 

232 .. versionadded:: 2.7 

233 """ 

234 

235 pass