Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/trunk' into src-move-8214-5
Browse files Browse the repository at this point in the history
  • Loading branch information
glyph committed Jul 31, 2016
2 parents df0d45e + d76a49a commit 6659c6b
Show file tree
Hide file tree
Showing 112 changed files with 2,888 additions and 1,811 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ It includes modules for many different purposes, including the following:
- ``twisted.conch``: SSHv2 and Telnet clients and servers and terminal emulators
- ``twisted.words``: Clients and servers for IRC, XMPP, and other IM protocols
- ``twisted.mail``: IMAPv4, POP3, SMTP clients and servers
- ``twisted.positioning``: Tools for communicating with NMEA-compatible GPS recievers
- ``twisted.positioning``: Tools for communicating with NMEA-compatible GPS receivers
- ``twisted.names``: DNS client and tools for making your own DNS servers
- ``twisted.trial``: A unit testing framework that integrates well with Twisted-based code.

Expand Down
11 changes: 5 additions & 6 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ build: off
test: off

# Don't build branch if there is an open PR, to prevent double builds.
# For now, Appveyour will only build PR commits and not commits to master or
# For now, Appveyor will only build PR commits and not commits to master or
# commits on random branches without an associated PR.
skip_branch_with_pr: true

Expand All @@ -34,11 +34,6 @@ environment:
- PYTHON: C:\Python27-x64
TOXENV: py27-coverage-windows,codecov-publish

# Some tests are failing on Appveyor and they will be fixed in a separate
# ticket.
matrix:
allow_failures:
- PYTHON: C:\Python27-x64

install:
# Get some information about the build environment.
Expand All @@ -54,5 +49,9 @@ install:
# The build system itself is handled by tox.
- "%PYTHON%\\Scripts\\pip install tox"

# Install OpenSSH through chocolatey
- "choco install win32-openssh -confirm"
- cmd: "SET PATH=%PATH%;C:\\Program Files\\OpenSSH-Win64"

test_script:
- "%PYTHON%\\python -m tox -e %TOXENV%"
2 changes: 1 addition & 1 deletion docs/mail/tutorial/smtpclient/smtpclient.rst
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ change gets us:
A meagre amount of progress, but the service still raises an
A meager amount of progress, but the service still raises an
exception. This time, it's because we haven't specified
a *protocol class* for the factory to use. We'll do that in
the next example.
Expand Down
5 changes: 4 additions & 1 deletion src/twisted/conch/avatar.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# -*- test-case-name: twisted.conch.test.test_conch -*-

from __future__ import absolute_import, division

from zope.interface import implementer

from twisted.conch.error import ConchError
from twisted.conch.interfaces import IConchUser
from twisted.conch.ssh.connection import OPEN_UNKNOWN_CHANNEL_TYPE
from twisted.python import log
from twisted.python.compat import nativeString


@implementer(IConchUser)
Expand All @@ -32,7 +35,7 @@ def lookupSubsystem(self, subsystem, data):

def gotGlobalRequest(self, requestType, data):
# XXX should this use method dispatch?
requestType = requestType.replace('-', '_')
requestType = nativeString(requestType.replace(b'-', b'_'))
f = getattr(self, "global_%s" % requestType, None)
if not f:
return 0
Expand Down
6 changes: 3 additions & 3 deletions src/twisted/conch/client/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,16 @@ def isInKnownHosts(host, pubKey, options):
os.mkdir(os.path.expanduser('~/.ssh'))
kh_file = options['known-hosts'] or _KNOWN_HOSTS
try:
known_hosts = open(os.path.expanduser(kh_file))
known_hosts = open(os.path.expanduser(kh_file), 'rb')
except IOError:
return 0
with known_hosts:
for line in known_hosts.xreadlines():
for line in known_hosts.readlines():
split = line.split()
if len(split) < 3:
continue
hosts, hostKeyType, encodedKey = split[:3]
if host not in hosts.split(','): # incorrect host
if host not in hosts.split(b','): # incorrect host
continue
if hostKeyType != keyType: # incorrect type of key
continue
Expand Down
54 changes: 29 additions & 25 deletions src/twisted/conch/client/knownhosts.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
@since: 8.2
"""

from __future__ import absolute_import, division

import hmac
from binascii import Error as DecodeError, b2a_base64
from binascii import Error as DecodeError, b2a_base64, a2b_base64
from contextlib import closing
from hashlib import sha1

Expand All @@ -22,6 +24,7 @@
from twisted.conch.interfaces import IKnownHostEntry
from twisted.conch.error import HostKeyChanged, UserRejectedKey, InvalidEntry
from twisted.conch.ssh.keys import Key, BadKeyError
from twisted.python.compat import nativeString


def _b64encode(s):
Expand Down Expand Up @@ -58,11 +61,11 @@ def _extractCommon(string):
splitkey = keyAndComment.split(None, 1)
if len(splitkey) == 2:
keyString, comment = splitkey
comment = comment.rstrip("\n")
comment = comment.rstrip(b"\n")
else:
keyString = splitkey[0]
comment = None
key = Key.fromString(keyString.decode('base64'))
key = Key.fromString(a2b_base64(keyString))
return hostnames, keyType, key, comment


Expand All @@ -73,13 +76,13 @@ class _BaseEntry(object):
represent keys and key types the same way.
@ivar keyType: The type of the key; either ssh-dss or ssh-rsa.
@type keyType: L{str}
@type keyType: L{bytes}
@ivar publicKey: The server public key indicated by this line.
@type publicKey: L{twisted.conch.ssh.keys.Key}
@ivar comment: Trailing garbage after the key line.
@type comment: L{str}
@type comment: L{bytes}
"""

def __init__(self, keyType, publicKey, comment):
Expand Down Expand Up @@ -110,7 +113,7 @@ class PlainEntry(_BaseEntry):
file.
@ivar _hostnames: the list of all host-names associated with this entry.
@type _hostnames: L{list} of L{str}
@type _hostnames: L{list} of L{bytes}
"""

def __init__(self, hostnames, keyType, publicKey, comment):
Expand All @@ -126,7 +129,7 @@ def fromString(cls, string):
@param string: a space-separated string formatted like "hostname
key-type base64-key-data comment".
@type string: L{str}
@type string: L{bytes}
@raise DecodeError: if the key is not valid encoded as valid base64.
Expand All @@ -142,7 +145,7 @@ def fromString(cls, string):
@rtype: L{PlainEntry}
"""
hostnames, keyType, key, comment = _extractCommon(string)
self = cls(hostnames.split(","), keyType, key, comment)
self = cls(hostnames.split(b","), keyType, key, comment)
return self

fromString = classmethod(fromString)
Expand All @@ -154,7 +157,7 @@ def matchesHost(self, hostname):
@param hostname: A hostname or IP address literal to check against this
entry.
@type hostname: L{str}
@type hostname: L{bytes}
@return: C{True} if this entry is for the given hostname or IP address,
C{False} otherwise.
Expand All @@ -172,12 +175,12 @@ def toString(self):
information.
@rtype: L{bytes}
"""
fields = [','.join(self._hostnames),
fields = [b','.join(self._hostnames),
self.keyType,
_b64encode(self.publicKey.blob())]
if self.comment is not None:
fields.append(self.comment)
return ' '.join(fields)
return b' '.join(fields)



Expand Down Expand Up @@ -218,7 +221,7 @@ def toString(self):
used to initialize this entry but without a trailing newline.
@rtype: L{bytes}
"""
return self._string.rstrip("\n")
return self._string.rstrip(b"\n")



Expand Down Expand Up @@ -255,7 +258,7 @@ class HashedEntry(_BaseEntry, FancyEqMixin):
known_hosts file as opposed to a plaintext one.
"""

MAGIC = '|1|'
MAGIC = b'|1|'

compareAttributes = (
"_hostSalt", "_hostHash", "keyType", "publicKey", "comment")
Expand Down Expand Up @@ -289,11 +292,11 @@ def fromString(cls, string):
information from C{string}.
"""
stuff, keyType, key, comment = _extractCommon(string)
saltAndHash = stuff[len(cls.MAGIC):].split("|")
saltAndHash = stuff[len(cls.MAGIC):].split(b"|")
if len(saltAndHash) != 2:
raise InvalidEntry()
hostSalt, hostHash = saltAndHash
self = cls(hostSalt.decode("base64"), hostHash.decode("base64"),
self = cls(a2b_base64(hostSalt), a2b_base64(hostHash),
keyType, key, comment)
return self

Expand Down Expand Up @@ -325,13 +328,13 @@ def toString(self):
hashed.
@rtype: L{bytes}
"""
fields = [self.MAGIC + '|'.join([_b64encode(self._hostSalt),
_b64encode(self._hostHash)]),
fields = [self.MAGIC + b'|'.join([_b64encode(self._hostSalt),
_b64encode(self._hostHash)]),
self.keyType,
_b64encode(self.publicKey.blob())]
if self.comment is not None:
fields.append(self.comment)
return ' '.join(fields)
return b' '.join(fields)



Expand Down Expand Up @@ -467,7 +470,7 @@ def gotHasKey(result):
if not self.hasHostKey(ip, key):
ui.warn("Warning: Permanently added the %s host key for "
"IP address '%s' to the list of known hosts." %
(key.type(), ip))
(key.type(), nativeString(ip)))
self.addHostKey(ip, key)
self.save()
return result
Expand All @@ -485,7 +488,8 @@ def promptResponse(response):
"can't be established.\n"
"RSA key fingerprint is %s.\n"
"Are you sure you want to continue connecting (yes/no)? " %
(hostname, ip, key.fingerprint()))
(nativeString(hostname), nativeString(ip),
key.fingerprint()))
return proceed.addCallback(promptResponse)
return hhk.addCallback(gotHasKey)

Expand All @@ -508,7 +512,7 @@ def addHostKey(self, hostname, key):
@rtype: L{HashedEntry}
"""
salt = secureRandom(20)
keyType = "ssh-" + key.type().lower()
keyType = key.sshType()
entry = HashedEntry(salt, _hmacedString(salt, hostname),
keyType, key, None)
self._added.append(entry)
Expand All @@ -524,15 +528,15 @@ def save(self):
p.makedirs()

if self._clobber:
mode = "w"
mode = "wb"
else:
mode = "a"
mode = "ab"

with self._savePath.open(mode) as hostsFileObj:
if self._added:
hostsFileObj.write(
"\n".join([entry.toString() for entry in self._added]) +
"\n")
b"\n".join([entry.toString() for entry in self._added]) +
b"\n")
self._added = []
self._clobber = False

Expand Down
Loading

0 comments on commit 6659c6b

Please sign in to comment.