summaryrefslogtreecommitdiff
path: root/paramiko
diff options
context:
space:
mode:
authorJeff Forcier <jeff@bitprophet.org>2023-03-10 13:55:53 -0500
committerJeff Forcier <jeff@bitprophet.org>2023-03-10 13:55:53 -0500
commitcbfdc10c8f94e7242420ad43cede3c96c33edc53 (patch)
treed6099c1a11c5964cfefecfc110d10718bf8f9a20 /paramiko
parent08eb98d63f5f03172ce4734096e7013a56c560ac (diff)
parente465da57a07072ccc9500c85cac1e86dda52d19b (diff)
downloadparamiko-cbfdc10c8f94e7242420ad43cede3c96c33edc53.tar.gz
Merge branch 'main' into 2013-int
Diffstat (limited to 'paramiko')
-rw-r--r--paramiko/agent.py18
-rw-r--r--paramiko/client.py21
-rw-r--r--paramiko/hostkeys.py6
-rw-r--r--paramiko/kex_gss.py4
-rw-r--r--paramiko/server.py15
-rw-r--r--paramiko/sftp_attr.py2
-rw-r--r--paramiko/sftp_client.py8
-rw-r--r--paramiko/sftp_server.py10
-rw-r--r--paramiko/sftp_si.py4
-rw-r--r--paramiko/transport.py10
10 files changed, 61 insertions, 37 deletions
diff --git a/paramiko/agent.py b/paramiko/agent.py
index c1a07390..1cc9075f 100644
--- a/paramiko/agent.py
+++ b/paramiko/agent.py
@@ -65,6 +65,9 @@ class AgentSSH:
no SSH agent was running (or it couldn't be contacted), an empty list
will be returned.
+ This method performs no IO, just returns the list of keys retreived
+ when the connection was made.
+
:return:
a tuple of `.AgentKey` objects representing keys available on the
SSH agent
@@ -277,6 +280,17 @@ class AgentClientProxy:
class AgentServerProxy(AgentSSH):
"""
+ Allows an SSH server to access a forwarded agent.
+
+ This also creates a unix domain socket on the system to allow external
+ programs to also access the agent. For this reason, you probably only want
+ to create one of these.
+
+ :meth:`connect` must be called before it is usable. This will also load the
+ list of keys the agent contains. You must also call :meth:`close` in
+ order to clean up the unix socket and the thread that maintains it.
+ (:class:`contextlib.closing` might be helpful to you.)
+
:param .Transport t: Transport used for SSH Agent communication forwarding
:raises: `.SSHException` -- mostly if we lost the agent
@@ -314,10 +328,10 @@ class AgentServerProxy(AgentSSH):
def get_env(self):
"""
- Helper for the environnement under unix
+ Helper for the environment under unix
:return:
- a dict containing the ``SSH_AUTH_SOCK`` environnement variables
+ a dict containing the ``SSH_AUTH_SOCK`` environment variables
"""
return {"SSH_AUTH_SOCK": self._get_filename()}
diff --git a/paramiko/client.py b/paramiko/client.py
index a9e4e233..1fe14b07 100644
--- a/paramiko/client.py
+++ b/paramiko/client.py
@@ -324,14 +324,19 @@ class SSHClient(ClosingContextManager):
`.Transport` instance to be used by this client. Defaults to
`.Transport.__init__`.
- :raises:
- `.BadHostKeyException` -- if the server's host key could not be
- verified
- :raises: `.AuthenticationException` -- if authentication failed
- :raises:
- `.SSHException` -- if there was any other error connecting or
- establishing an SSH session
- :raises socket.error: if a socket error occurred while connecting
+ :raises BadHostKeyException:
+ if the server's host key could not be verified.
+ :raises AuthenticationException: if authentication failed.
+ :raises socket.error:
+ if a socket error (other than connection-refused or
+ host-unreachable) occurred while connecting.
+ :raises NoValidConnectionsError:
+ if all valid connection targets for the requested hostname (eg IPv4
+ and IPv6) yielded connection-refused or host-unreachable socket
+ errors.
+ :raises SSHException:
+ if there was any other error connecting or establishing an SSH
+ session.
.. versionchanged:: 1.15
Added the ``banner_timeout``, ``gss_auth``, ``gss_kex``,
diff --git a/paramiko/hostkeys.py b/paramiko/hostkeys.py
index b189aac6..bbfa5755 100644
--- a/paramiko/hostkeys.py
+++ b/paramiko/hostkeys.py
@@ -20,6 +20,7 @@
from base64 import encodebytes, decodebytes
import binascii
import os
+import re
from collections.abc import MutableMapping
from hashlib import sha1
@@ -328,7 +329,8 @@ class HostKeyEntry:
"""
Parses the given line of text to find the names for the host,
the type of key, and the key data. The line is expected to be in the
- format used by the OpenSSH known_hosts file.
+ format used by the OpenSSH known_hosts file. Fields are separated by a
+ single space or tab.
Lines are expected to not have leading or trailing whitespace.
We don't bother to check for comments or empty lines. All of
@@ -337,7 +339,7 @@ class HostKeyEntry:
:param str line: a line from an OpenSSH known_hosts file
"""
log = get_logger("paramiko.hostkeys")
- fields = line.split(" ")
+ fields = re.split(" |\t", line)
if len(fields) < 3:
# Bad number of fields
msg = "Not enough fields found in known_hosts in line {} ({!r})"
diff --git a/paramiko/kex_gss.py b/paramiko/kex_gss.py
index e3fbb36e..2a5f29e3 100644
--- a/paramiko/kex_gss.py
+++ b/paramiko/kex_gss.py
@@ -125,7 +125,7 @@ class KexGSSGroup1:
Parse the next packet.
:param ptype: The (string) type of the incoming packet
- :param `.Message` m: The paket content
+ :param `.Message` m: The packet content
"""
if self.transport.server_mode and (ptype == MSG_KEXGSS_INIT):
return self._parse_kexgss_init(m)
@@ -380,7 +380,7 @@ class KexGSSGex:
Parse the next packet.
:param ptype: The (string) type of the incoming packet
- :param `.Message` m: The paket content
+ :param `.Message` m: The packet content
"""
if ptype == MSG_KEXGSS_GROUPREQ:
return self._parse_kexgss_groupreq(m)
diff --git a/paramiko/server.py b/paramiko/server.py
index b68607e1..6b0bb0f6 100644
--- a/paramiko/server.py
+++ b/paramiko/server.py
@@ -255,7 +255,7 @@ class ServerInterface:
We don't check if the krb5 principal is allowed to log in on
the server, because there is no way to do that in python. So
if you develop your own SSH server with paramiko for a cetain
- plattform like Linux, you should call C{krb5_kuserok()} in
+ platform like Linux, you should call C{krb5_kuserok()} in
your local kerberos library to make sure that the
krb5_principal has an account on the server and is allowed to
log in as a user.
@@ -287,7 +287,7 @@ class ServerInterface:
We don't check if the krb5 principal is allowed to log in on
the server, because there is no way to do that in python. So
if you develop your own SSH server with paramiko for a cetain
- plattform like Linux, you should call C{krb5_kuserok()} in
+ platform like Linux, you should call C{krb5_kuserok()} in
your local kerberos library to make sure that the
krb5_principal has an account on the server and is allowed
to log in as a user.
@@ -454,10 +454,10 @@ class ServerInterface:
subsystem; ``False`` if that subsystem can't or won't be provided.
"""
transport = channel.get_transport()
- handler_class, larg, kwarg = transport._get_subsystem_handler(name)
+ handler_class, args, kwargs = transport._get_subsystem_handler(name)
if handler_class is None:
return False
- handler = handler_class(channel, name, self, *larg, **kwarg)
+ handler = handler_class(channel, name, self, *args, **kwargs)
handler.start()
return True
@@ -517,6 +517,9 @@ class ServerInterface:
:param .Channel channel: the `.Channel` the request arrived on
:return: ``True`` if the AgentForward was loaded; ``False`` if not
+
+ If ``True`` is returned, the server should create an
+ :class:`AgentServerProxy` to access the agent.
"""
return False
@@ -634,7 +637,7 @@ class InteractiveQuery:
class SubsystemHandler(threading.Thread):
"""
- Handler for a subsytem in server mode. If you create a subclass of this
+ Handler for a subsystem in server mode. If you create a subclass of this
class and pass it to `.Transport.set_subsystem_handler`, an object of this
class will be created for each request for this subsystem. Each new object
will be executed within its own new thread by calling `start_subsystem`.
@@ -642,7 +645,7 @@ class SubsystemHandler(threading.Thread):
For example, if you made a subclass ``MP3Handler`` and registered it as the
handler for subsystem ``"mp3"``, then whenever a client has successfully
- authenticated and requests subsytem ``"mp3"``, an object of class
+ authenticated and requests subsystem ``"mp3"``, an object of class
``MP3Handler`` will be created, and `start_subsystem` will be called on
it from a new thread.
"""
diff --git a/paramiko/sftp_attr.py b/paramiko/sftp_attr.py
index eb4dd900..18ffbf86 100644
--- a/paramiko/sftp_attr.py
+++ b/paramiko/sftp_attr.py
@@ -24,7 +24,7 @@ from paramiko.common import x80000000, o700, o70, xffffffff
class SFTPAttributes:
"""
Representation of the attributes of a file (or proxied file) for SFTP in
- client or server mode. It attemps to mirror the object returned by
+ client or server mode. It attempts to mirror the object returned by
`os.stat` as closely as possible, so it may have the following fields,
with the same meanings as those returned by an `os.stat` object:
diff --git a/paramiko/sftp_client.py b/paramiko/sftp_client.py
index d91a3951..31ac1292 100644
--- a/paramiko/sftp_client.py
+++ b/paramiko/sftp_client.py
@@ -817,17 +817,17 @@ class SFTPClient(BaseSFTP, ClosingContextManager):
# ...internals...
- def _request(self, t, *arg):
- num = self._async_request(type(None), t, *arg)
+ def _request(self, t, *args):
+ num = self._async_request(type(None), t, *args)
return self._read_response(num)
- def _async_request(self, fileobj, t, *arg):
+ def _async_request(self, fileobj, t, *args):
# this method may be called from other threads (prefetch)
self._lock.acquire()
try:
msg = Message()
msg.add_int(self.request_number)
- for item in arg:
+ for item in args:
if isinstance(item, int64):
msg.add_int64(item)
elif isinstance(item, int):
diff --git a/paramiko/sftp_server.py b/paramiko/sftp_server.py
index 6cb7ec62..cd3910dc 100644
--- a/paramiko/sftp_server.py
+++ b/paramiko/sftp_server.py
@@ -98,7 +98,7 @@ class SFTPServer(BaseSFTP, SubsystemHandler):
name,
server,
sftp_si=SFTPServerInterface,
- *largs,
+ *args,
**kwargs
):
"""
@@ -124,7 +124,7 @@ class SFTPServer(BaseSFTP, SubsystemHandler):
# map of handle-string to SFTPHandle for files & folders:
self.file_table = {}
self.folder_table = {}
- self.server = sftp_si(server, *largs, **kwargs)
+ self.server = sftp_si(server, *args, **kwargs)
def _log(self, level, msg):
if issubclass(type(msg), list):
@@ -221,10 +221,10 @@ class SFTPServer(BaseSFTP, SubsystemHandler):
# ...internals...
- def _response(self, request_number, t, *arg):
+ def _response(self, request_number, t, *args):
msg = Message()
msg.add_int(request_number)
- for item in arg:
+ for item in args:
# NOTE: this is a very silly tiny class used for SFTPFile mostly
if isinstance(item, int64):
msg.add_int64(item)
@@ -259,7 +259,7 @@ class SFTPServer(BaseSFTP, SubsystemHandler):
desc = SFTP_DESC[code]
except IndexError:
desc = "Unknown"
- # some clients expect a "langauge" tag at the end
+ # some clients expect a "language" tag at the end
# (but don't mind it being blank)
self._response(request_number, CMD_STATUS, code, desc, "")
diff --git a/paramiko/sftp_si.py b/paramiko/sftp_si.py
index 26b0ac9b..72b5db94 100644
--- a/paramiko/sftp_si.py
+++ b/paramiko/sftp_si.py
@@ -40,7 +40,7 @@ class SFTPServerInterface:
clients & servers obey the requirement that paths be encoded in UTF-8.
"""
- def __init__(self, server, *largs, **kwargs):
+ def __init__(self, server, *args, **kwargs):
"""
Create a new SFTPServerInterface object. This method does nothing by
default and is meant to be overridden by subclasses.
@@ -48,7 +48,7 @@ class SFTPServerInterface:
:param .ServerInterface server:
the server object associated with this channel and SFTP subsystem
"""
- super().__init__(*largs, **kwargs)
+ super().__init__(*args, **kwargs)
def session_started(self):
"""
diff --git a/paramiko/transport.py b/paramiko/transport.py
index 0c6c3ad1..98cdae03 100644
--- a/paramiko/transport.py
+++ b/paramiko/transport.py
@@ -1010,7 +1010,7 @@ class Transport(threading.Thread, ClosingContextManager):
:raises:
`.SSHException` -- if the request is rejected, the session ends
- prematurely or there is a timeout openning a channel
+ prematurely or there is a timeout opening a channel
.. versionchanged:: 1.15
Added the ``window_size`` and ``max_packet_size`` arguments.
@@ -1417,7 +1417,7 @@ class Transport(threading.Thread, ClosingContextManager):
finally:
self.lock.release()
- def set_subsystem_handler(self, name, handler, *larg, **kwarg):
+ def set_subsystem_handler(self, name, handler, *args, **kwargs):
"""
Set the handler class for a subsystem in server mode. If a request
for this subsystem is made on an open ssh channel later, this handler
@@ -1433,7 +1433,7 @@ class Transport(threading.Thread, ClosingContextManager):
"""
try:
self.lock.acquire()
- self.subsystem_table[name] = (handler, larg, kwarg)
+ self.subsystem_table[name] = (handler, args, kwargs)
finally:
self.lock.release()
@@ -1694,7 +1694,7 @@ class Transport(threading.Thread, ClosingContextManager):
def auth_interactive_dumb(self, username, handler=None, submethods=""):
"""
- Autenticate to the server interactively but dumber.
+ Authenticate to the server interactively but dumber.
Just print the prompt and / or instructions to stdout and send back
the response. This is good for situations where partial auth is
achieved by key and then the user has to enter a 2fac token.
@@ -2060,7 +2060,7 @@ class Transport(threading.Thread, ClosingContextManager):
reply.add_string("")
reply.add_string("en")
# NOTE: Post-open channel messages do not need checking; the above will
- # reject attemps to open channels, meaning that even if a malicious
+ # reject attempts to open channels, meaning that even if a malicious
# user tries to send a MSG_CHANNEL_REQUEST, it will simply fall under
# the logic that handles unknown channel IDs (as the channel list will
# be empty.)