Skip to content

Commit

Permalink
Merge branch 'master' into switch-to-cryptography
Browse files Browse the repository at this point in the history
Conflicts:
	paramiko/ecdsakey.py
	paramiko/util.py
  • Loading branch information
alex committed Dec 18, 2014
2 parents 37756f3 + 681f325 commit b3884d2
Show file tree
Hide file tree
Showing 31 changed files with 258 additions and 158 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
language: python
sudo: false
python:
- "2.6"
- "2.7"
Expand Down
2 changes: 1 addition & 1 deletion demos/demo_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def check_channel_pty_request(self, channel, term, width, height, pixelwidth,
print('Authenticated!')

server.event.wait(10)
if not server.event.isSet():
if not server.event.is_set():
print('*** Client never asked for a shell.')
sys.exit(1)

Expand Down
8 changes: 5 additions & 3 deletions paramiko/_winapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,14 @@ def __init__(self, *args, **kwargs):
super(SECURITY_ATTRIBUTES, self).__init__(*args, **kwargs)
self.nLength = ctypes.sizeof(SECURITY_ATTRIBUTES)

def _get_descriptor(self):
@property
def descriptor(self):
return self._descriptor
def _set_descriptor(self, descriptor):

@descriptor.setter
def descriptor(self, value):
self._descriptor = descriptor
self.lpSecurityDescriptor = ctypes.addressof(descriptor)
descriptor = property(_get_descriptor, _set_descriptor)

def GetTokenInformation(token, information_class):
"""
Expand Down
3 changes: 2 additions & 1 deletion paramiko/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ def _connect(self, conn):
self._keys = tuple(keys)

def _close(self):
#self._conn.close()
if self._conn is not None:
self._conn.close()
self._conn = None
self._keys = ()

Expand Down
2 changes: 1 addition & 1 deletion paramiko/auth_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def wait_for_response(self, event):
if (e is None) or issubclass(e.__class__, EOFError):
e = AuthenticationException('Authentication failed.')
raise e
if event.isSet():
if event.is_set():
break
if not self.is_authenticated():
e = self.transport.get_exception()
Expand Down
6 changes: 3 additions & 3 deletions paramiko/ber.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def __repr__(self):

def decode(self):
return self.decode_next()

def decode_next(self):
if self.idx >= len(self.content):
return None
Expand Down Expand Up @@ -89,6 +89,7 @@ def decode_next(self):
# 1: boolean (00 false, otherwise true)
raise BERException('Unknown ber encoding type %d (robey is lazy)' % ident)

@staticmethod
def decode_sequence(data):
out = []
ber = BER(data)
Expand All @@ -98,7 +99,6 @@ def decode_sequence(data):
break
out.append(x)
return out
decode_sequence = staticmethod(decode_sequence)

def encode_tlv(self, ident, val):
# no need to support ident > 31 here
Expand All @@ -125,9 +125,9 @@ def encode(self, x):
else:
raise BERException('Unknown type for encoding: %s' % repr(type(x)))

@staticmethod
def encode_sequence(data):
ber = BER()
for item in data:
ber.encode(item)
return ber.asbytes()
encode_sequence = staticmethod(encode_sequence)
8 changes: 4 additions & 4 deletions paramiko/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ def exit_status_ready(self):
.. versionadded:: 1.7.3
"""
return self.closed or self.status_event.isSet()
return self.closed or self.status_event.is_set()

def recv_exit_status(self):
"""
Expand All @@ -305,7 +305,7 @@ def recv_exit_status(self):
.. versionadded:: 1.2
"""
self.status_event.wait()
assert self.status_event.isSet()
assert self.status_event.is_set()
return self.exit_status

def send_exit_status(self, status):
Expand Down Expand Up @@ -890,7 +890,7 @@ def _set_remote_channel(self, chanid, window_size, max_packet_size):
self.out_max_packet_size = self.transport. \
_sanitize_packet_size(max_packet_size)
self.active = 1
self._log(DEBUG, 'Max packet out: %d bytes' % max_packet_size)
self._log(DEBUG, 'Max packet out: %d bytes' % self.out_max_packet_size)

def _request_success(self, m):
self._log(DEBUG, 'Sesch channel %d request ok' % self.chanid)
Expand Down Expand Up @@ -1077,7 +1077,7 @@ def _event_pending(self):

def _wait_for_event(self):
self.event.wait()
assert self.event.isSet()
assert self.event.is_set()
if self.event_ready:
return
e = self.transport.get_exception()
Expand Down
6 changes: 5 additions & 1 deletion paramiko/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,11 @@ def asbytes(s):
# lower bound on the max packet size we'll accept from the remote host
# Minimum packet size is 32768 bytes according to
# http://www.ietf.org/rfc/rfc4254.txt
MIN_PACKET_SIZE = 2 ** 15
MIN_WINDOW_SIZE = 2 ** 15

# However, according to http://www.ietf.org/rfc/rfc4253.txt it is perfectly
# legal to accept a size much smaller, as OpenSSH client does as size 16384.
MIN_PACKET_SIZE = 2 ** 12

# Max windows size according to http://www.ietf.org/rfc/rfc4254.txt
MAX_WINDOW_SIZE = 2**32 -1
44 changes: 17 additions & 27 deletions paramiko/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import fnmatch
import os
import re
import shlex
import socket

SSH_PORT = 22
Expand Down Expand Up @@ -54,7 +55,6 @@ def parse(self, file_obj):
:param file file_obj: a file-like object to read the config file from
"""

host = {"host": ['*'], "config": {}}
for line in file_obj:
line = line.rstrip('\r\n').lstrip()
Expand All @@ -73,6 +73,9 @@ def parse(self, file_obj):
'host': self._get_hosts(value),
'config': {}
}
elif key == 'proxycommand' and value.lower() == 'none':
# Proxycommands of none should not be added as an actual value. (Issue #415)
continue
else:
if value.startswith('"') and value.endswith('"'):
value = value[1:-1]
Expand All @@ -93,13 +96,15 @@ def lookup(self, hostname):
"""
Return a dict of config options for a given hostname.
The host-matching rules of OpenSSH's ``ssh_config`` man page are used,
which means that all configuration options from matching host
specifications are merged, with more specific hostmasks taking
precedence. In other words, if ``"Port"`` is set under ``"Host *"``
and also ``"Host *.example.com"``, and the lookup is for
``"ssh.example.com"``, then the port entry for ``"Host *.example.com"``
will win out.
The host-matching rules of OpenSSH's ``ssh_config`` man page are used:
For each parameter, the first obtained value will be used. The
configuration files contain sections separated by ``Host''
specifications, and that section is only applied for hosts that match
one of the patterns given in the specification.
Since the first obtained value for each parameter is used, more host-
specific declarations should be given near the beginning of the file,
and general defaults at the end.
The keys in the returned dict are all normalized to lowercase (look for
``"port"``, not ``"Port"``. The values are processed according to the
Expand Down Expand Up @@ -220,25 +225,10 @@ def _get_hosts(self, host):
"""
Return a list of host_names from host value.
"""
i, length = 0, len(host)
hosts = []
while i < length:
if host[i] == '"':
end = host.find('"', i + 1)
if end < 0:
raise Exception("Unparsable host %s" % host)
hosts.append(host[i + 1:end])
i = end + 1
elif not host[i].isspace():
end = i + 1
while end < length and not host[end].isspace() and host[end] != '"':
end += 1
hosts.append(host[i:end])
i = end
else:
i += 1

return hosts
try:
return shlex.split(host)
except ValueError:
raise Exception("Unparsable host %s" % host)


class LazyFqdn(object):
Expand Down
2 changes: 1 addition & 1 deletion paramiko/dsskey.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ def write_private_key_file(self, filename, password=None):
def write_private_key(self, file_obj, password=None):
self._write_private_key('DSA', file_obj, self._encode_key(), password)

@staticmethod
def generate(bits=1024, progress_func=None):
"""
Generate a new private DSS key. This factory function can be used to
Expand All @@ -208,7 +209,6 @@ def generate(bits=1024, progress_func=None):
))
key.x = numbers.x
return key
generate = staticmethod(generate)

### internals...

Expand Down
5 changes: 2 additions & 3 deletions paramiko/ecdsakey.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import base64
import binascii
import textwrap
from hashlib import sha256

from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends import default_backend
Expand All @@ -36,7 +35,7 @@
from paramiko.dsskey import _DSSSigValue
from paramiko.message import Message
from paramiko.pkey import PKey
from paramiko.py3compat import byte_chr, u
from paramiko.py3compat import byte_chr
from paramiko.ssh_exception import SSHException
from paramiko.util import deflate_long, inflate_long

Expand Down Expand Up @@ -157,6 +156,7 @@ def write_private_key(self, file_obj, password=None):
key = self.signing_key or self.verifying_key
self._write_private_key('EC', file_obj, key.to_der(), password)

@staticmethod
def generate(curve=ec.SECP256R1(), progress_func=None):
"""
Generate a new private RSA key. This factory function can be used to
Expand All @@ -168,7 +168,6 @@ def generate(curve=ec.SECP256R1(), progress_func=None):
signing_key = SigningKey.generate(curve)
key = ECDSAKey(vals=(signing_key, signing_key.get_verifying_key()))
return key
generate = staticmethod(generate)

### internals...

Expand Down
16 changes: 12 additions & 4 deletions paramiko/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ def readline(self, size=None):
if not (self._flags & self.FLAG_READ):
raise IOError('File not open for reading')
line = self._rbuffer
truncated = False
while True:
if self._at_trailing_cr and (self._flags & self.FLAG_UNIVERSAL_NEWLINE) and (len(line) > 0):
# edge case: the newline may be '\r\n' and we may have read
Expand All @@ -220,11 +221,11 @@ def readline(self, size=None):
# enough.
if (size is not None) and (size >= 0):
if len(line) >= size:
# truncate line and return
# truncate line
self._rbuffer = line[size:]
line = line[:size]
self._pos += len(line)
return line if self._flags & self.FLAG_BINARY else u(line)
truncated = True
break
n = size - len(line)
else:
n = self._bufsize
Expand All @@ -246,10 +247,17 @@ def readline(self, size=None):
rpos = line.find(cr_byte)
if (rpos >= 0) and (rpos < pos or pos < 0):
pos = rpos
if pos == -1:
# we couldn't find a newline in the truncated string, return it
self._pos += len(line)
return line if self._flags & self.FLAG_BINARY else u(line)
xpos = pos + 1
if (line[pos] == cr_byte_value) and (xpos < len(line)) and (line[xpos] == linefeed_byte_value):
xpos += 1
self._rbuffer = line[xpos:]
# if the string was truncated, _rbuffer needs to have the string after
# the newline character plus the truncated part of the line we stored
# earlier in _rbuffer
self._rbuffer = line[xpos:] + self._rbuffer if truncated else line[xpos:]
lf = line[pos:xpos]
line = line[:pos] + linefeed_byte
if (len(self._rbuffer) == 0) and (lf == cr_byte):
Expand Down
4 changes: 2 additions & 2 deletions paramiko/hostkeys.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ def values(self):
ret.append(self.lookup(k))
return ret

@staticmethod
def hash_host(hostname, salt=None):
"""
Return a "hashed" form of the hostname, as used by OpenSSH when storing
Expand All @@ -274,7 +275,6 @@ def hash_host(hostname, salt=None):
hmac = HMAC(salt, b(hostname), sha1).digest()
hostkey = '|1|%s|%s' % (u(encodebytes(salt)), u(encodebytes(hmac)))
return hostkey.replace('\n', '')
hash_host = staticmethod(hash_host)


class InvalidHostKey(Exception):
Expand All @@ -294,6 +294,7 @@ def __init__(self, hostnames=None, key=None):
self.hostnames = hostnames
self.key = key

@classmethod
def from_line(cls, line, lineno=None):
"""
Parses the given line of text to find the names for the host,
Expand Down Expand Up @@ -336,7 +337,6 @@ def from_line(cls, line, lineno=None):
raise InvalidHostKey(line, e)

return cls(names, key)
from_line = classmethod(from_line)

def to_line(self):
"""
Expand Down
4 changes: 2 additions & 2 deletions paramiko/pkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ def verify_ssh_sig(self, data, msg):
"""
return False

@classmethod
def from_private_key_file(cls, filename, password=None):
"""
Create a key object by reading a private key file. If the private
Expand All @@ -192,8 +193,8 @@ def from_private_key_file(cls, filename, password=None):
"""
key = cls(filename=filename, password=password)
return key
from_private_key_file = classmethod(from_private_key_file)

@classmethod
def from_private_key(cls, file_obj, password=None):
"""
Create a key object by reading a private key from a file (or file-like)
Expand All @@ -213,7 +214,6 @@ def from_private_key(cls, file_obj, password=None):
"""
key = cls(file_obj=file_obj, password=password)
return key
from_private_key = classmethod(from_private_key)

def write_private_key_file(self, filename, password=None):
"""
Expand Down
2 changes: 1 addition & 1 deletion paramiko/rsakey.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ def write_private_key_file(self, filename, password=None):
def write_private_key(self, file_obj, password=None):
self._write_private_key('RSA', file_obj, self._encode_key(), password)

@staticmethod
def generate(bits, progress_func=None):
"""
Generate a new private RSA key. This factory function can be used to
Expand All @@ -175,7 +176,6 @@ def generate(bits, progress_func=None):
key.dmq1 = numbers.dmq1
key.iqmp = numbers.iqmp
return key
generate = staticmethod(generate)

### internals...

Expand Down
Loading

0 comments on commit b3884d2

Please sign in to comment.