Skip to content

Commit

Permalink
Merge branch 'master' into 1343-int
Browse files Browse the repository at this point in the history
  • Loading branch information
bitprophet committed Dec 3, 2019
2 parents 25de1a7 + 84fa355 commit 9e6fc80
Show file tree
Hide file tree
Showing 100 changed files with 3,887 additions and 1,152 deletions.
51 changes: 40 additions & 11 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dist: xenial
language: python
sudo: false
cache:
Expand All @@ -8,33 +9,61 @@ python:
- "3.4"
- "3.5"
- "3.6"
- "3.7-dev"
- "pypy-5.6.0"
- "3.7"
- "3.8-dev"
- "pypy"
- "pypy3"
matrix:
allow_failures:
- python: "3.7-dev"
- python: "3.8-dev"
# Explicitly test against our oldest supported cryptography.io, in addition
# to whatever the latest default is.
include:
- python: 2.7
env: "CRYPTO_BEFORE=1.6"
- python: 3.6
env: "CRYPTO_BEFORE=1.6"
env: "OLDEST_CRYPTO=2.5"
- python: 3.7
env: "OLDEST_CRYPTO=2.5"
- python: 2.7
env: "USE_K5TEST=yes"
- python: 3.7
env: "USE_K5TEST=yes"
install:
# Ensure modern pip/etc to avoid some issues w/ older worker environs
- pip install pip==9.0.1 setuptools==36.6.0
# Grab a specific version of Cryptography if desired. Doing this before other
# installations ensures we don't have to do any downgrading/overriding.
- |
if [[ -n "$CRYPTO_BEFORE" ]]; then
pip install "cryptography<${CRYPTO_BEFORE}"
if [[ -n "$OLDEST_CRYPTO" ]]; then
pip install "cryptography==${OLDEST_CRYPTO}"
fi
# Self-install for setup.py-driven deps
- pip install -e .
# Self-install for setup.py-driven deps (plus additional
# safe-enough-for-all-matrix-cells optional deps)
# TODO: additional matrices or test steps to test all the entrypoints
- pip install -e ".[ed25519,invoke]"
# Dev (doc/test running) requirements
# TODO: use pipenv + whatever contexty-type stuff it has
# TODO: use poetry + whatever contexty-type stuff it has, should be more than
# just prod/dev split. Also apply to the above re: extras_require.
- pip install codecov # For codecov specifically
- pip install -r dev-requirements.txt
- |
if [[ -n "$USE_K5TEST" ]]; then
# we need a few commands and libraries
# Debian/Ubuntu package: commands used by package k5test
# libkrb5-dev: krb5-config
# krb5-kdc: kdb5_util, krb5kdc
# krb5-admin-server: kadmin.local, kprop, kadmind
# krb5-user: kinit, klist
#
# krb5-multidev: required to build gssapi
sudo apt-get -y install libkrb5-dev krb5-admin-server \
krb5-kdc krb5-user krb5-multidev && \
pip install k5test gssapi pyasn1
fi
# In case of problems uncomment the following to get the krb environment
# - |
# if [[ -n "$USE_K5TEST" ]]; then
# python -c 'from tests.util import k5shell; k5shell()' env | sort
# fi
script:
# Fast syntax check failures for more rapid feedback to submitters
# (Travis-oriented metatask that version checks Python, installs, runs.)
Expand Down
9 changes: 8 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Paramiko

:Paramiko: Python SSH module
:Copyright: Copyright (c) 2003-2009 Robey Pointer <[email protected]>
:Copyright: Copyright (c) 2013-2018 Jeff Forcier <[email protected]>
:Copyright: Copyright (c) 2013-2019 Jeff Forcier <[email protected]>
:License: `LGPL <https://www.gnu.org/copyleft/lesser.html>`_
:Homepage: http://www.paramiko.org/
:API docs: http://docs.paramiko.org
Expand Down Expand Up @@ -136,3 +136,10 @@ There are also unit tests here::
$ pytest

Which will verify that most of the core components are working correctly.

To test Kerberos/GSSAPI, you need a Kerberos environment. On UNIX you can
use the package k5test to setup a Kerberos environment on the fly::

$ pip install -r dev-requirements.txt
$ pip install k5test gssapi pyasn1
$ pytest
9 changes: 4 additions & 5 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
# Invocations for common project tasks
invoke>=1.0,<2.0
invocations>=1.2.0,<2.0
# NOTE: pytest-relaxed currently only works with pytest >=3, <3.3
pytest>=3.2,<3.3
pytest-relaxed==1.1.4
pytest==4.4.2
pytest-relaxed==1.1.5
# pytest-xdist for test dir watching and the inv guard task
pytest-xdist>=1.22,<2.0
pytest-xdist==1.28.0
mock==2.0.0
# Linting!
flake8==2.4.0
flake8==3.6.0
# Coverage!
coverage==3.7.1
codecov==1.6.3
Expand Down
22 changes: 16 additions & 6 deletions paramiko/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,22 @@
)
from paramiko.auth_handler import AuthHandler
from paramiko.ssh_gss import GSSAuth, GSS_AUTH_AVAILABLE, GSS_EXCEPTIONS
from paramiko.channel import Channel, ChannelFile
from paramiko.channel import (
Channel,
ChannelFile,
ChannelStderrFile,
ChannelStdinFile,
)
from paramiko.ssh_exception import (
SSHException,
PasswordRequiredException,
AuthenticationException,
BadAuthenticationType,
ChannelException,
BadHostKeyException,
AuthenticationException,
ChannelException,
ConfigParseError,
CouldNotCanonicalize,
PasswordRequiredException,
ProxyCommandFailure,
SSHException,
)
from paramiko.server import ServerInterface, SubsystemHandler, InteractiveQuery
from paramiko.rsakey import RSAKey
Expand All @@ -57,7 +64,7 @@
from paramiko.agent import Agent, AgentKey
from paramiko.pkey import PKey, PublicBlob
from paramiko.hostkeys import HostKeys
from paramiko.config import SSHConfig
from paramiko.config import SSHConfig, SSHConfigDict
from paramiko.proxy import ProxyCommand

from paramiko.common import (
Expand Down Expand Up @@ -99,6 +106,8 @@
"BufferedFile",
"Channel",
"ChannelException",
"ConfigParseError",
"CouldNotCanonicalize",
"DSSKey",
"ECDSAKey",
"Ed25519Key",
Expand All @@ -121,6 +130,7 @@
"SFTPServerInterface",
"SSHClient",
"SSHConfig",
"SSHConfigDict",
"SSHException",
"SecurityOptions",
"ServerInterface",
Expand Down
2 changes: 1 addition & 1 deletion paramiko/_version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__version_info__ = (2, 4, 2)
__version_info__ = (2, 7, 0)
__version__ = ".".join(map(str, __version_info__))
4 changes: 2 additions & 2 deletions paramiko/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ def _close(self):
def _send_message(self, msg):
msg = asbytes(msg)
self._conn.send(struct.pack(">I", len(msg)) + msg)
l = self._read_all(4)
msg = Message(self._read_all(struct.unpack(">I", l)[0]))
data = self._read_all(4)
msg = Message(self._read_all(struct.unpack(">I", data)[0]))
return ord(msg.get_byte()), msg

def _read_all(self, wanted):
Expand Down
38 changes: 34 additions & 4 deletions paramiko/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -889,12 +889,30 @@ def makefile_stderr(self, *params):
client, it only makes sense to open this file for reading. For a
server, it only makes sense to open this file for writing.
:return: `.ChannelFile` object which can be used for Python file I/O.
:returns:
`.ChannelStderrFile` object which can be used for Python file I/O.
.. versionadded:: 1.1
"""
return ChannelStderrFile(*([self] + list(params)))

def makefile_stdin(self, *params):
"""
Return a file-like object associated with this channel's stdin
stream.
The optional ``mode`` and ``bufsize`` arguments are interpreted the
same way as by the built-in ``file()`` function in Python. For a
client, it only makes sense to open this file for writing. For a
server, it only makes sense to open this file for reading.
:returns:
`.ChannelStdinFile` object which can be used for Python file I/O.
.. versionadded:: 2.6
"""
return ChannelStdinFile(*([self] + list(params)))

def fileno(self):
"""
Returns an OS-level file descriptor which can be used for polling, but
Expand Down Expand Up @@ -1348,8 +1366,11 @@ def _write(self, data):


class ChannelStderrFile(ChannelFile):
def __init__(self, channel, mode="r", bufsize=-1):
ChannelFile.__init__(self, channel, mode, bufsize)
"""
A file-like wrapper around `.Channel` stderr.
See `Channel.makefile_stderr` for details.
"""

def _read(self, size):
return self.channel.recv_stderr(size)
Expand All @@ -1359,4 +1380,13 @@ def _write(self, data):
return len(data)


# vim: set shiftwidth=4 expandtab :
class ChannelStdinFile(ChannelFile):
"""
A file-like wrapper around `.Channel` stdin.
See `Channel.makefile_stdin` for details.
"""

def close(self):
super(ChannelStdinFile, self).close()
self.channel.shutdown_write()
13 changes: 11 additions & 2 deletions paramiko/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ def connect(
auth_timeout=None,
gss_trust_dns=True,
passphrase=None,
disabled_algorithms=None,
):
"""
Connect to an SSH server and authenticate to it. The server's host key
Expand Down Expand Up @@ -310,6 +311,9 @@ def connect(
for the SSH banner to be presented.
:param float auth_timeout: an optional timeout (in seconds) to wait for
an authentication response.
:param dict disabled_algorithms:
an optional dict passed directly to `.Transport` and its keyword
argument of the same name.
:raises:
`.BadHostKeyException` -- if the server's host key could not be
Expand All @@ -327,6 +331,8 @@ def connect(
Added the ``gss_trust_dns`` argument.
.. versionchanged:: 2.4
Added the ``passphrase`` argument.
.. versionchanged:: 2.6
Added the ``disabled_algorithms`` argument.
"""
if not sock:
errors = {}
Expand Down Expand Up @@ -362,7 +368,10 @@ def connect(
raise NoValidConnectionsError(errors)

t = self._transport = Transport(
sock, gss_kex=gss_kex, gss_deleg_creds=gss_deleg_creds
sock,
gss_kex=gss_kex,
gss_deleg_creds=gss_deleg_creds,
disabled_algorithms=disabled_algorithms,
)
t.use_compression(compress=compress)
t.set_gss_host(
Expand Down Expand Up @@ -503,7 +512,7 @@ def exec_command(
if environment:
chan.update_environment(environment)
chan.exec_command(command)
stdin = chan.makefile("wb", bufsize)
stdin = chan.makefile_stdin("wb", bufsize)
stdout = chan.makefile("r", bufsize)
stderr = chan.makefile_stderr("r", bufsize)
return stdin, stdout, stderr
Expand Down
Loading

0 comments on commit 9e6fc80

Please sign in to comment.