diff options
Diffstat (limited to 'lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh')
15 files changed, 0 insertions, 6345 deletions
diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/__init__.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/__init__.py deleted file mode 100755 index 4b7f024b..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -# - -""" -An SSHv2 implementation for Twisted. Part of the Twisted.Conch package. - -Maintainer: Paul Swartz -""" diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/address.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/address.py deleted file mode 100755 index c06f2bfa..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/address.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- test-case-name: twisted.conch.test.test_address -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -Address object for SSH network connections. - -Maintainer: Paul Swartz - -@since: 12.1 -""" -from zope.interface import implements -from twisted.internet.interfaces import IAddress -from twisted.python import util - - - -class SSHTransportAddress(object, util.FancyEqMixin): - """ - Object representing an SSH Transport endpoint. - - @ivar address: A instance of an object which implements I{IAddress} to - which this transport address is connected. - """ - - implements(IAddress) - - compareAttributes = ('address',) - - def __init__(self, address): - self.address = address - - def __repr__(self): - return 'SSHTransportAddress(%r)' % (self.address,) - - def __hash__(self): - return hash(('SSH', self.address)) - diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/agent.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/agent.py deleted file mode 100755 index c1bf1a09..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/agent.py +++ /dev/null @@ -1,294 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -Implements the SSH v2 key agent protocol. This protocol is documented in the -SSH source code, in the file -U{PROTOCOL.agent<http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent>}. - -Maintainer: Paul Swartz -""" - -import struct - -from twisted.conch.ssh.common import NS, getNS, getMP -from twisted.conch.error import ConchError, MissingKeyStoreError -from twisted.conch.ssh import keys -from twisted.internet import defer, protocol - - - -class SSHAgentClient(protocol.Protocol): - """ - The client side of the SSH agent protocol. This is equivalent to - ssh-add(1) and can be used with either ssh-agent(1) or the SSHAgentServer - protocol, also in this package. - """ - - def __init__(self): - self.buf = '' - self.deferreds = [] - - - def dataReceived(self, data): - self.buf += data - while 1: - if len(self.buf) <= 4: - return - packLen = struct.unpack('!L', self.buf[:4])[0] - if len(self.buf) < 4 + packLen: - return - packet, self.buf = self.buf[4:4 + packLen], self.buf[4 + packLen:] - reqType = ord(packet[0]) - d = self.deferreds.pop(0) - if reqType == AGENT_FAILURE: - d.errback(ConchError('agent failure')) - elif reqType == AGENT_SUCCESS: - d.callback('') - else: - d.callback(packet) - - - def sendRequest(self, reqType, data): - pack = struct.pack('!LB',len(data) + 1, reqType) + data - self.transport.write(pack) - d = defer.Deferred() - self.deferreds.append(d) - return d - - - def requestIdentities(self): - """ - @return: A L{Deferred} which will fire with a list of all keys found in - the SSH agent. The list of keys is comprised of (public key blob, - comment) tuples. - """ - d = self.sendRequest(AGENTC_REQUEST_IDENTITIES, '') - d.addCallback(self._cbRequestIdentities) - return d - - - def _cbRequestIdentities(self, data): - """ - Unpack a collection of identities into a list of tuples comprised of - public key blobs and comments. - """ - if ord(data[0]) != AGENT_IDENTITIES_ANSWER: - raise ConchError('unexpected response: %i' % ord(data[0])) - numKeys = struct.unpack('!L', data[1:5])[0] - keys = [] - data = data[5:] - for i in range(numKeys): - blob, data = getNS(data) - comment, data = getNS(data) - keys.append((blob, comment)) - return keys - - - def addIdentity(self, blob, comment = ''): - """ - Add a private key blob to the agent's collection of keys. - """ - req = blob - req += NS(comment) - return self.sendRequest(AGENTC_ADD_IDENTITY, req) - - - def signData(self, blob, data): - """ - Request that the agent sign the given C{data} with the private key - which corresponds to the public key given by C{blob}. The private - key should have been added to the agent already. - - @type blob: C{str} - @type data: C{str} - @return: A L{Deferred} which fires with a signature for given data - created with the given key. - """ - req = NS(blob) - req += NS(data) - req += '\000\000\000\000' # flags - return self.sendRequest(AGENTC_SIGN_REQUEST, req).addCallback(self._cbSignData) - - - def _cbSignData(self, data): - if ord(data[0]) != AGENT_SIGN_RESPONSE: - raise ConchError('unexpected data: %i' % ord(data[0])) - signature = getNS(data[1:])[0] - return signature - - - def removeIdentity(self, blob): - """ - Remove the private key corresponding to the public key in blob from the - running agent. - """ - req = NS(blob) - return self.sendRequest(AGENTC_REMOVE_IDENTITY, req) - - - def removeAllIdentities(self): - """ - Remove all keys from the running agent. - """ - return self.sendRequest(AGENTC_REMOVE_ALL_IDENTITIES, '') - - - -class SSHAgentServer(protocol.Protocol): - """ - The server side of the SSH agent protocol. This is equivalent to - ssh-agent(1) and can be used with either ssh-add(1) or the SSHAgentClient - protocol, also in this package. - """ - - def __init__(self): - self.buf = '' - - - def dataReceived(self, data): - self.buf += data - while 1: - if len(self.buf) <= 4: - return - packLen = struct.unpack('!L', self.buf[:4])[0] - if len(self.buf) < 4 + packLen: - return - packet, self.buf = self.buf[4:4 + packLen], self.buf[4 + packLen:] - reqType = ord(packet[0]) - reqName = messages.get(reqType, None) - if not reqName: - self.sendResponse(AGENT_FAILURE, '') - else: - f = getattr(self, 'agentc_%s' % reqName) - if getattr(self.factory, 'keys', None) is None: - self.sendResponse(AGENT_FAILURE, '') - raise MissingKeyStoreError() - f(packet[1:]) - - - def sendResponse(self, reqType, data): - pack = struct.pack('!LB', len(data) + 1, reqType) + data - self.transport.write(pack) - - - def agentc_REQUEST_IDENTITIES(self, data): - """ - Return all of the identities that have been added to the server - """ - assert data == '' - numKeys = len(self.factory.keys) - resp = [] - - resp.append(struct.pack('!L', numKeys)) - for key, comment in self.factory.keys.itervalues(): - resp.append(NS(key.blob())) # yes, wrapped in an NS - resp.append(NS(comment)) - self.sendResponse(AGENT_IDENTITIES_ANSWER, ''.join(resp)) - - - def agentc_SIGN_REQUEST(self, data): - """ - Data is a structure with a reference to an already added key object and - some data that the clients wants signed with that key. If the key - object wasn't loaded, return AGENT_FAILURE, else return the signature. - """ - blob, data = getNS(data) - if blob not in self.factory.keys: - return self.sendResponse(AGENT_FAILURE, '') - signData, data = getNS(data) - assert data == '\000\000\000\000' - self.sendResponse(AGENT_SIGN_RESPONSE, NS(self.factory.keys[blob][0].sign(signData))) - - - def agentc_ADD_IDENTITY(self, data): - """ - Adds a private key to the agent's collection of identities. On - subsequent interactions, the private key can be accessed using only the - corresponding public key. - """ - - # need to pre-read the key data so we can get past it to the comment string - keyType, rest = getNS(data) - if keyType == 'ssh-rsa': - nmp = 6 - elif keyType == 'ssh-dss': - nmp = 5 - else: - raise keys.BadKeyError('unknown blob type: %s' % keyType) - - rest = getMP(rest, nmp)[-1] # ignore the key data for now, we just want the comment - comment, rest = getNS(rest) # the comment, tacked onto the end of the key blob - - k = keys.Key.fromString(data, type='private_blob') # not wrapped in NS here - self.factory.keys[k.blob()] = (k, comment) - self.sendResponse(AGENT_SUCCESS, '') - - - def agentc_REMOVE_IDENTITY(self, data): - """ - Remove a specific key from the agent's collection of identities. - """ - blob, _ = getNS(data) - k = keys.Key.fromString(blob, type='blob') - del self.factory.keys[k.blob()] - self.sendResponse(AGENT_SUCCESS, '') - - - def agentc_REMOVE_ALL_IDENTITIES(self, data): - """ - Remove all keys from the agent's collection of identities. - """ - assert data == '' - self.factory.keys = {} - self.sendResponse(AGENT_SUCCESS, '') - - # v1 messages that we ignore because we don't keep v1 keys - # open-ssh sends both v1 and v2 commands, so we have to - # do no-ops for v1 commands or we'll get "bad request" errors - - def agentc_REQUEST_RSA_IDENTITIES(self, data): - """ - v1 message for listing RSA1 keys; superseded by - agentc_REQUEST_IDENTITIES, which handles different key types. - """ - self.sendResponse(AGENT_RSA_IDENTITIES_ANSWER, struct.pack('!L', 0)) - - - def agentc_REMOVE_RSA_IDENTITY(self, data): - """ - v1 message for removing RSA1 keys; superseded by - agentc_REMOVE_IDENTITY, which handles different key types. - """ - self.sendResponse(AGENT_SUCCESS, '') - - - def agentc_REMOVE_ALL_RSA_IDENTITIES(self, data): - """ - v1 message for removing all RSA1 keys; superseded by - agentc_REMOVE_ALL_IDENTITIES, which handles different key types. - """ - self.sendResponse(AGENT_SUCCESS, '') - - -AGENTC_REQUEST_RSA_IDENTITIES = 1 -AGENT_RSA_IDENTITIES_ANSWER = 2 -AGENT_FAILURE = 5 -AGENT_SUCCESS = 6 - -AGENTC_REMOVE_RSA_IDENTITY = 8 -AGENTC_REMOVE_ALL_RSA_IDENTITIES = 9 - -AGENTC_REQUEST_IDENTITIES = 11 -AGENT_IDENTITIES_ANSWER = 12 -AGENTC_SIGN_REQUEST = 13 -AGENT_SIGN_RESPONSE = 14 -AGENTC_ADD_IDENTITY = 17 -AGENTC_REMOVE_IDENTITY = 18 -AGENTC_REMOVE_ALL_IDENTITIES = 19 - -messages = {} -for name, value in locals().copy().items(): - if name[:7] == 'AGENTC_': - messages[value] = name[7:] # doesn't handle doubles - diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/channel.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/channel.py deleted file mode 100755 index f498aec0..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/channel.py +++ /dev/null @@ -1,281 +0,0 @@ -# -*- test-case-name: twisted.conch.test.test_channel -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -# -""" -The parent class for all the SSH Channels. Currently implemented channels -are session. direct-tcp, and forwarded-tcp. - -Maintainer: Paul Swartz -""" - -from twisted.python import log -from twisted.internet import interfaces -from zope.interface import implements - - -class SSHChannel(log.Logger): - """ - A class that represents a multiplexed channel over an SSH connection. - The channel has a local window which is the maximum amount of data it will - receive, and a remote which is the maximum amount of data the remote side - will accept. There is also a maximum packet size for any individual data - packet going each way. - - @ivar name: the name of the channel. - @type name: C{str} - @ivar localWindowSize: the maximum size of the local window in bytes. - @type localWindowSize: C{int} - @ivar localWindowLeft: how many bytes are left in the local window. - @type localWindowLeft: C{int} - @ivar localMaxPacket: the maximum size of packet we will accept in bytes. - @type localMaxPacket: C{int} - @ivar remoteWindowLeft: how many bytes are left in the remote window. - @type remoteWindowLeft: C{int} - @ivar remoteMaxPacket: the maximum size of a packet the remote side will - accept in bytes. - @type remoteMaxPacket: C{int} - @ivar conn: the connection this channel is multiplexed through. - @type conn: L{SSHConnection} - @ivar data: any data to send to the other size when the channel is - requested. - @type data: C{str} - @ivar avatar: an avatar for the logged-in user (if a server channel) - @ivar localClosed: True if we aren't accepting more data. - @type localClosed: C{bool} - @ivar remoteClosed: True if the other size isn't accepting more data. - @type remoteClosed: C{bool} - """ - - implements(interfaces.ITransport) - - name = None # only needed for client channels - - def __init__(self, localWindow = 0, localMaxPacket = 0, - remoteWindow = 0, remoteMaxPacket = 0, - conn = None, data=None, avatar = None): - self.localWindowSize = localWindow or 131072 - self.localWindowLeft = self.localWindowSize - self.localMaxPacket = localMaxPacket or 32768 - self.remoteWindowLeft = remoteWindow - self.remoteMaxPacket = remoteMaxPacket - self.areWriting = 1 - self.conn = conn - self.data = data - self.avatar = avatar - self.specificData = '' - self.buf = '' - self.extBuf = [] - self.closing = 0 - self.localClosed = 0 - self.remoteClosed = 0 - self.id = None # gets set later by SSHConnection - - def __str__(self): - return '<SSHChannel %s (lw %i rw %i)>' % (self.name, - self.localWindowLeft, self.remoteWindowLeft) - - def logPrefix(self): - id = (self.id is not None and str(self.id)) or "unknown" - return "SSHChannel %s (%s) on %s" % (self.name, id, - self.conn.logPrefix()) - - def channelOpen(self, specificData): - """ - Called when the channel is opened. specificData is any data that the - other side sent us when opening the channel. - - @type specificData: C{str} - """ - log.msg('channel open') - - def openFailed(self, reason): - """ - Called when the the open failed for some reason. - reason.desc is a string descrption, reason.code the the SSH error code. - - @type reason: L{error.ConchError} - """ - log.msg('other side refused open\nreason: %s'% reason) - - def addWindowBytes(self, bytes): - """ - Called when bytes are added to the remote window. By default it clears - the data buffers. - - @type bytes: C{int} - """ - self.remoteWindowLeft = self.remoteWindowLeft+bytes - if not self.areWriting and not self.closing: - self.areWriting = True - self.startWriting() - if self.buf: - b = self.buf - self.buf = '' - self.write(b) - if self.extBuf: - b = self.extBuf - self.extBuf = [] - for (type, data) in b: - self.writeExtended(type, data) - - def requestReceived(self, requestType, data): - """ - Called when a request is sent to this channel. By default it delegates - to self.request_<requestType>. - If this function returns true, the request succeeded, otherwise it - failed. - - @type requestType: C{str} - @type data: C{str} - @rtype: C{bool} - """ - foo = requestType.replace('-', '_') - f = getattr(self, 'request_%s'%foo, None) - if f: - return f(data) - log.msg('unhandled request for %s'%requestType) - return 0 - - def dataReceived(self, data): - """ - Called when we receive data. - - @type data: C{str} - """ - log.msg('got data %s'%repr(data)) - - def extReceived(self, dataType, data): - """ - Called when we receive extended data (usually standard error). - - @type dataType: C{int} - @type data: C{str} - """ - log.msg('got extended data %s %s'%(dataType, repr(data))) - - def eofReceived(self): - """ - Called when the other side will send no more data. - """ - log.msg('remote eof') - - def closeReceived(self): - """ - Called when the other side has closed the channel. - """ - log.msg('remote close') - self.loseConnection() - - def closed(self): - """ - Called when the channel is closed. This means that both our side and - the remote side have closed the channel. - """ - log.msg('closed') - - # transport stuff - def write(self, data): - """ - Write some data to the channel. If there is not enough remote window - available, buffer until it is. Otherwise, split the data into - packets of length remoteMaxPacket and send them. - - @type data: C{str} - """ - if self.buf: - self.buf += data - return - top = len(data) - if top > self.remoteWindowLeft: - data, self.buf = (data[:self.remoteWindowLeft], - data[self.remoteWindowLeft:]) - self.areWriting = 0 - self.stopWriting() - top = self.remoteWindowLeft - rmp = self.remoteMaxPacket - write = self.conn.sendData - r = range(0, top, rmp) - for offset in r: - write(self, data[offset: offset+rmp]) - self.remoteWindowLeft -= top - if self.closing and not self.buf: - self.loseConnection() # try again - - def writeExtended(self, dataType, data): - """ - Send extended data to this channel. If there is not enough remote - window available, buffer until there is. Otherwise, split the data - into packets of length remoteMaxPacket and send them. - - @type dataType: C{int} - @type data: C{str} - """ - if self.extBuf: - if self.extBuf[-1][0] == dataType: - self.extBuf[-1][1] += data - else: - self.extBuf.append([dataType, data]) - return - if len(data) > self.remoteWindowLeft: - data, self.extBuf = (data[:self.remoteWindowLeft], - [[dataType, data[self.remoteWindowLeft:]]]) - self.areWriting = 0 - self.stopWriting() - while len(data) > self.remoteMaxPacket: - self.conn.sendExtendedData(self, dataType, - data[:self.remoteMaxPacket]) - data = data[self.remoteMaxPacket:] - self.remoteWindowLeft -= self.remoteMaxPacket - if data: - self.conn.sendExtendedData(self, dataType, data) - self.remoteWindowLeft -= len(data) - if self.closing: - self.loseConnection() # try again - - def writeSequence(self, data): - """ - Part of the Transport interface. Write a list of strings to the - channel. - - @type data: C{list} of C{str} - """ - self.write(''.join(data)) - - def loseConnection(self): - """ - Close the channel if there is no buferred data. Otherwise, note the - request and return. - """ - self.closing = 1 - if not self.buf and not self.extBuf: - self.conn.sendClose(self) - - def getPeer(self): - """ - Return a tuple describing the other side of the connection. - - @rtype: C{tuple} - """ - return('SSH', )+self.conn.transport.getPeer() - - def getHost(self): - """ - Return a tuple describing our side of the connection. - - @rtype: C{tuple} - """ - return('SSH', )+self.conn.transport.getHost() - - def stopWriting(self): - """ - Called when the remote buffer is full, as a hint to stop writing. - This can be ignored, but it can be helpful. - """ - - def startWriting(self): - """ - Called when the remote buffer has more room, as a hint to continue - writing. - """ diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/common.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/common.py deleted file mode 100755 index 3afa3413..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/common.py +++ /dev/null @@ -1,117 +0,0 @@ -# -*- test-case-name: twisted.conch.test.test_ssh -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - - -""" -Common functions for the SSH classes. - -Maintainer: Paul Swartz -""" - -import struct, warnings, __builtin__ - -try: - from Crypto import Util -except ImportError: - warnings.warn("PyCrypto not installed, but continuing anyways!", - RuntimeWarning) - -from twisted.python import randbytes - - -def NS(t): - """ - net string - """ - return struct.pack('!L',len(t)) + t - -def getNS(s, count=1): - """ - get net string - """ - ns = [] - c = 0 - for i in range(count): - l, = struct.unpack('!L',s[c:c+4]) - ns.append(s[c+4:4+l+c]) - c += 4 + l - return tuple(ns) + (s[c:],) - -def MP(number): - if number==0: return '\000'*4 - assert number>0 - bn = Util.number.long_to_bytes(number) - if ord(bn[0])&128: - bn = '\000' + bn - return struct.pack('>L',len(bn)) + bn - -def getMP(data, count=1): - """ - Get multiple precision integer out of the string. A multiple precision - integer is stored as a 4-byte length followed by length bytes of the - integer. If count is specified, get count integers out of the string. - The return value is a tuple of count integers followed by the rest of - the data. - """ - mp = [] - c = 0 - for i in range(count): - length, = struct.unpack('>L',data[c:c+4]) - mp.append(Util.number.bytes_to_long(data[c+4:c+4+length])) - c += 4 + length - return tuple(mp) + (data[c:],) - -def _MPpow(x, y, z): - """return the MP version of (x**y)%z - """ - return MP(pow(x,y,z)) - -def ffs(c, s): - """ - first from second - goes through the first list, looking for items in the second, returns the first one - """ - for i in c: - if i in s: return i - -getMP_py = getMP -MP_py = MP -_MPpow_py = _MPpow -pyPow = pow - -def _fastgetMP(data, count=1): - mp = [] - c = 0 - for i in range(count): - length = struct.unpack('!L', data[c:c+4])[0] - mp.append(long(gmpy.mpz(data[c + 4:c + 4 + length][::-1] + '\x00', 256))) - c += length + 4 - return tuple(mp) + (data[c:],) - -def _fastMP(i): - i2 = gmpy.mpz(i).binary()[::-1] - return struct.pack('!L', len(i2)) + i2 - -def _fastMPpow(x, y, z=None): - r = pyPow(gmpy.mpz(x),y,z).binary()[::-1] - return struct.pack('!L', len(r)) + r - -def install(): - global getMP, MP, _MPpow - getMP = _fastgetMP - MP = _fastMP - _MPpow = _fastMPpow - # XXX: We override builtin pow so that PyCrypto can benefit from gmpy too. - def _fastpow(x, y, z=None, mpz=gmpy.mpz): - if type(x) in (long, int): - x = mpz(x) - return pyPow(x, y, z) - __builtin__.pow = _fastpow # evil evil - -try: - import gmpy - install() -except ImportError: - pass - diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/connection.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/connection.py deleted file mode 100755 index 25271995..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/connection.py +++ /dev/null @@ -1,637 +0,0 @@ -# -*- test-case-name: twisted.conch.test.test_connection -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -This module contains the implementation of the ssh-connection service, which -allows access to the shell and port-forwarding. - -Maintainer: Paul Swartz -""" - -import struct - -from twisted.conch.ssh import service, common -from twisted.conch import error -from twisted.internet import defer -from twisted.python import log - -class SSHConnection(service.SSHService): - """ - An implementation of the 'ssh-connection' service. It is used to - multiplex multiple channels over the single SSH connection. - - @ivar localChannelID: the next number to use as a local channel ID. - @type localChannelID: C{int} - @ivar channels: a C{dict} mapping a local channel ID to C{SSHChannel} - subclasses. - @type channels: C{dict} - @ivar localToRemoteChannel: a C{dict} mapping a local channel ID to a - remote channel ID. - @type localToRemoteChannel: C{dict} - @ivar channelsToRemoteChannel: a C{dict} mapping a C{SSHChannel} subclass - to remote channel ID. - @type channelsToRemoteChannel: C{dict} - @ivar deferreds: a C{dict} mapping a local channel ID to a C{list} of - C{Deferreds} for outstanding channel requests. Also, the 'global' - key stores the C{list} of pending global request C{Deferred}s. - """ - name = 'ssh-connection' - - def __init__(self): - self.localChannelID = 0 # this is the current # to use for channel ID - self.localToRemoteChannel = {} # local channel ID -> remote channel ID - self.channels = {} # local channel ID -> subclass of SSHChannel - self.channelsToRemoteChannel = {} # subclass of SSHChannel -> - # remote channel ID - self.deferreds = {"global": []} # local channel -> list of deferreds - # for pending requests or 'global' -> list of - # deferreds for global requests - self.transport = None # gets set later - - - def serviceStarted(self): - if hasattr(self.transport, 'avatar'): - self.transport.avatar.conn = self - - - def serviceStopped(self): - """ - Called when the connection is stopped. - """ - map(self.channelClosed, self.channels.values()) - self._cleanupGlobalDeferreds() - - - def _cleanupGlobalDeferreds(self): - """ - All pending requests that have returned a deferred must be errbacked - when this service is stopped, otherwise they might be left uncalled and - uncallable. - """ - for d in self.deferreds["global"]: - d.errback(error.ConchError("Connection stopped.")) - del self.deferreds["global"][:] - - - # packet methods - def ssh_GLOBAL_REQUEST(self, packet): - """ - The other side has made a global request. Payload:: - string request type - bool want reply - <request specific data> - - This dispatches to self.gotGlobalRequest. - """ - requestType, rest = common.getNS(packet) - wantReply, rest = ord(rest[0]), rest[1:] - ret = self.gotGlobalRequest(requestType, rest) - if wantReply: - reply = MSG_REQUEST_FAILURE - data = '' - if ret: - reply = MSG_REQUEST_SUCCESS - if isinstance(ret, (tuple, list)): - data = ret[1] - self.transport.sendPacket(reply, data) - - def ssh_REQUEST_SUCCESS(self, packet): - """ - Our global request succeeded. Get the appropriate Deferred and call - it back with the packet we received. - """ - log.msg('RS') - self.deferreds['global'].pop(0).callback(packet) - - def ssh_REQUEST_FAILURE(self, packet): - """ - Our global request failed. Get the appropriate Deferred and errback - it with the packet we received. - """ - log.msg('RF') - self.deferreds['global'].pop(0).errback( - error.ConchError('global request failed', packet)) - - def ssh_CHANNEL_OPEN(self, packet): - """ - The other side wants to get a channel. Payload:: - string channel name - uint32 remote channel number - uint32 remote window size - uint32 remote maximum packet size - <channel specific data> - - We get a channel from self.getChannel(), give it a local channel number - and notify the other side. Then notify the channel by calling its - channelOpen method. - """ - channelType, rest = common.getNS(packet) - senderChannel, windowSize, maxPacket = struct.unpack('>3L', rest[:12]) - packet = rest[12:] - try: - channel = self.getChannel(channelType, windowSize, maxPacket, - packet) - localChannel = self.localChannelID - self.localChannelID += 1 - channel.id = localChannel - self.channels[localChannel] = channel - self.channelsToRemoteChannel[channel] = senderChannel - self.localToRemoteChannel[localChannel] = senderChannel - self.transport.sendPacket(MSG_CHANNEL_OPEN_CONFIRMATION, - struct.pack('>4L', senderChannel, localChannel, - channel.localWindowSize, - channel.localMaxPacket)+channel.specificData) - log.callWithLogger(channel, channel.channelOpen, packet) - except Exception, e: - log.msg('channel open failed') - log.err(e) - if isinstance(e, error.ConchError): - textualInfo, reason = e.args - if isinstance(textualInfo, (int, long)): - # See #3657 and #3071 - textualInfo, reason = reason, textualInfo - else: - reason = OPEN_CONNECT_FAILED - textualInfo = "unknown failure" - self.transport.sendPacket( - MSG_CHANNEL_OPEN_FAILURE, - struct.pack('>2L', senderChannel, reason) + - common.NS(textualInfo) + common.NS('')) - - def ssh_CHANNEL_OPEN_CONFIRMATION(self, packet): - """ - The other side accepted our MSG_CHANNEL_OPEN request. Payload:: - uint32 local channel number - uint32 remote channel number - uint32 remote window size - uint32 remote maximum packet size - <channel specific data> - - Find the channel using the local channel number and notify its - channelOpen method. - """ - (localChannel, remoteChannel, windowSize, - maxPacket) = struct.unpack('>4L', packet[: 16]) - specificData = packet[16:] - channel = self.channels[localChannel] - channel.conn = self - self.localToRemoteChannel[localChannel] = remoteChannel - self.channelsToRemoteChannel[channel] = remoteChannel - channel.remoteWindowLeft = windowSize - channel.remoteMaxPacket = maxPacket - log.callWithLogger(channel, channel.channelOpen, specificData) - - def ssh_CHANNEL_OPEN_FAILURE(self, packet): - """ - The other side did not accept our MSG_CHANNEL_OPEN request. Payload:: - uint32 local channel number - uint32 reason code - string reason description - - Find the channel using the local channel number and notify it by - calling its openFailed() method. - """ - localChannel, reasonCode = struct.unpack('>2L', packet[:8]) - reasonDesc = common.getNS(packet[8:])[0] - channel = self.channels[localChannel] - del self.channels[localChannel] - channel.conn = self - reason = error.ConchError(reasonDesc, reasonCode) - log.callWithLogger(channel, channel.openFailed, reason) - - def ssh_CHANNEL_WINDOW_ADJUST(self, packet): - """ - The other side is adding bytes to its window. Payload:: - uint32 local channel number - uint32 bytes to add - - Call the channel's addWindowBytes() method to add new bytes to the - remote window. - """ - localChannel, bytesToAdd = struct.unpack('>2L', packet[:8]) - channel = self.channels[localChannel] - log.callWithLogger(channel, channel.addWindowBytes, bytesToAdd) - - def ssh_CHANNEL_DATA(self, packet): - """ - The other side is sending us data. Payload:: - uint32 local channel number - string data - - Check to make sure the other side hasn't sent too much data (more - than what's in the window, or more than the maximum packet size). If - they have, close the channel. Otherwise, decrease the available - window and pass the data to the channel's dataReceived(). - """ - localChannel, dataLength = struct.unpack('>2L', packet[:8]) - channel = self.channels[localChannel] - # XXX should this move to dataReceived to put client in charge? - if (dataLength > channel.localWindowLeft or - dataLength > channel.localMaxPacket): # more data than we want - log.callWithLogger(channel, log.msg, 'too much data') - self.sendClose(channel) - return - #packet = packet[:channel.localWindowLeft+4] - data = common.getNS(packet[4:])[0] - channel.localWindowLeft -= dataLength - if channel.localWindowLeft < channel.localWindowSize // 2: - self.adjustWindow(channel, channel.localWindowSize - \ - channel.localWindowLeft) - #log.msg('local window left: %s/%s' % (channel.localWindowLeft, - # channel.localWindowSize)) - log.callWithLogger(channel, channel.dataReceived, data) - - def ssh_CHANNEL_EXTENDED_DATA(self, packet): - """ - The other side is sending us exteneded data. Payload:: - uint32 local channel number - uint32 type code - string data - - Check to make sure the other side hasn't sent too much data (more - than what's in the window, or or than the maximum packet size). If - they have, close the channel. Otherwise, decrease the available - window and pass the data and type code to the channel's - extReceived(). - """ - localChannel, typeCode, dataLength = struct.unpack('>3L', packet[:12]) - channel = self.channels[localChannel] - if (dataLength > channel.localWindowLeft or - dataLength > channel.localMaxPacket): - log.callWithLogger(channel, log.msg, 'too much extdata') - self.sendClose(channel) - return - data = common.getNS(packet[8:])[0] - channel.localWindowLeft -= dataLength - if channel.localWindowLeft < channel.localWindowSize // 2: - self.adjustWindow(channel, channel.localWindowSize - - channel.localWindowLeft) - log.callWithLogger(channel, channel.extReceived, typeCode, data) - - def ssh_CHANNEL_EOF(self, packet): - """ - The other side is not sending any more data. Payload:: - uint32 local channel number - - Notify the channel by calling its eofReceived() method. - """ - localChannel = struct.unpack('>L', packet[:4])[0] - channel = self.channels[localChannel] - log.callWithLogger(channel, channel.eofReceived) - - def ssh_CHANNEL_CLOSE(self, packet): - """ - The other side is closing its end; it does not want to receive any - more data. Payload:: - uint32 local channel number - - Notify the channnel by calling its closeReceived() method. If - the channel has also sent a close message, call self.channelClosed(). - """ - localChannel = struct.unpack('>L', packet[:4])[0] - channel = self.channels[localChannel] - log.callWithLogger(channel, channel.closeReceived) - channel.remoteClosed = True - if channel.localClosed and channel.remoteClosed: - self.channelClosed(channel) - - def ssh_CHANNEL_REQUEST(self, packet): - """ - The other side is sending a request to a channel. Payload:: - uint32 local channel number - string request name - bool want reply - <request specific data> - - Pass the message to the channel's requestReceived method. If the - other side wants a reply, add callbacks which will send the - reply. - """ - localChannel = struct.unpack('>L', packet[: 4])[0] - requestType, rest = common.getNS(packet[4:]) - wantReply = ord(rest[0]) - channel = self.channels[localChannel] - d = defer.maybeDeferred(log.callWithLogger, channel, - channel.requestReceived, requestType, rest[1:]) - if wantReply: - d.addCallback(self._cbChannelRequest, localChannel) - d.addErrback(self._ebChannelRequest, localChannel) - return d - - def _cbChannelRequest(self, result, localChannel): - """ - Called back if the other side wanted a reply to a channel request. If - the result is true, send a MSG_CHANNEL_SUCCESS. Otherwise, raise - a C{error.ConchError} - - @param result: the value returned from the channel's requestReceived() - method. If it's False, the request failed. - @type result: C{bool} - @param localChannel: the local channel ID of the channel to which the - request was made. - @type localChannel: C{int} - @raises ConchError: if the result is False. - """ - if not result: - raise error.ConchError('failed request') - self.transport.sendPacket(MSG_CHANNEL_SUCCESS, struct.pack('>L', - self.localToRemoteChannel[localChannel])) - - def _ebChannelRequest(self, result, localChannel): - """ - Called if the other wisde wanted a reply to the channel requeset and - the channel request failed. - - @param result: a Failure, but it's not used. - @param localChannel: the local channel ID of the channel to which the - request was made. - @type localChannel: C{int} - """ - self.transport.sendPacket(MSG_CHANNEL_FAILURE, struct.pack('>L', - self.localToRemoteChannel[localChannel])) - - def ssh_CHANNEL_SUCCESS(self, packet): - """ - Our channel request to the other other side succeeded. Payload:: - uint32 local channel number - - Get the C{Deferred} out of self.deferreds and call it back. - """ - localChannel = struct.unpack('>L', packet[:4])[0] - if self.deferreds.get(localChannel): - d = self.deferreds[localChannel].pop(0) - log.callWithLogger(self.channels[localChannel], - d.callback, '') - - def ssh_CHANNEL_FAILURE(self, packet): - """ - Our channel request to the other side failed. Payload:: - uint32 local channel number - - Get the C{Deferred} out of self.deferreds and errback it with a - C{error.ConchError}. - """ - localChannel = struct.unpack('>L', packet[:4])[0] - if self.deferreds.get(localChannel): - d = self.deferreds[localChannel].pop(0) - log.callWithLogger(self.channels[localChannel], - d.errback, - error.ConchError('channel request failed')) - - # methods for users of the connection to call - - def sendGlobalRequest(self, request, data, wantReply=0): - """ - Send a global request for this connection. Current this is only used - for remote->local TCP forwarding. - - @type request: C{str} - @type data: C{str} - @type wantReply: C{bool} - @rtype C{Deferred}/C{None} - """ - self.transport.sendPacket(MSG_GLOBAL_REQUEST, - common.NS(request) - + (wantReply and '\xff' or '\x00') - + data) - if wantReply: - d = defer.Deferred() - self.deferreds['global'].append(d) - return d - - def openChannel(self, channel, extra=''): - """ - Open a new channel on this connection. - - @type channel: subclass of C{SSHChannel} - @type extra: C{str} - """ - log.msg('opening channel %s with %s %s'%(self.localChannelID, - channel.localWindowSize, channel.localMaxPacket)) - self.transport.sendPacket(MSG_CHANNEL_OPEN, common.NS(channel.name) - + struct.pack('>3L', self.localChannelID, - channel.localWindowSize, channel.localMaxPacket) - + extra) - channel.id = self.localChannelID - self.channels[self.localChannelID] = channel - self.localChannelID += 1 - - def sendRequest(self, channel, requestType, data, wantReply=0): - """ - Send a request to a channel. - - @type channel: subclass of C{SSHChannel} - @type requestType: C{str} - @type data: C{str} - @type wantReply: C{bool} - @rtype C{Deferred}/C{None} - """ - if channel.localClosed: - return - log.msg('sending request %s' % requestType) - self.transport.sendPacket(MSG_CHANNEL_REQUEST, struct.pack('>L', - self.channelsToRemoteChannel[channel]) - + common.NS(requestType)+chr(wantReply) - + data) - if wantReply: - d = defer.Deferred() - self.deferreds.setdefault(channel.id, []).append(d) - return d - - def adjustWindow(self, channel, bytesToAdd): - """ - Tell the other side that we will receive more data. This should not - normally need to be called as it is managed automatically. - - @type channel: subclass of L{SSHChannel} - @type bytesToAdd: C{int} - """ - if channel.localClosed: - return # we're already closed - self.transport.sendPacket(MSG_CHANNEL_WINDOW_ADJUST, struct.pack('>2L', - self.channelsToRemoteChannel[channel], - bytesToAdd)) - log.msg('adding %i to %i in channel %i' % (bytesToAdd, - channel.localWindowLeft, channel.id)) - channel.localWindowLeft += bytesToAdd - - def sendData(self, channel, data): - """ - Send data to a channel. This should not normally be used: instead use - channel.write(data) as it manages the window automatically. - - @type channel: subclass of L{SSHChannel} - @type data: C{str} - """ - if channel.localClosed: - return # we're already closed - self.transport.sendPacket(MSG_CHANNEL_DATA, struct.pack('>L', - self.channelsToRemoteChannel[channel]) + - common.NS(data)) - - def sendExtendedData(self, channel, dataType, data): - """ - Send extended data to a channel. This should not normally be used: - instead use channel.writeExtendedData(data, dataType) as it manages - the window automatically. - - @type channel: subclass of L{SSHChannel} - @type dataType: C{int} - @type data: C{str} - """ - if channel.localClosed: - return # we're already closed - self.transport.sendPacket(MSG_CHANNEL_EXTENDED_DATA, struct.pack('>2L', - self.channelsToRemoteChannel[channel],dataType) \ - + common.NS(data)) - - def sendEOF(self, channel): - """ - Send an EOF (End of File) for a channel. - - @type channel: subclass of L{SSHChannel} - """ - if channel.localClosed: - return # we're already closed - log.msg('sending eof') - self.transport.sendPacket(MSG_CHANNEL_EOF, struct.pack('>L', - self.channelsToRemoteChannel[channel])) - - def sendClose(self, channel): - """ - Close a channel. - - @type channel: subclass of L{SSHChannel} - """ - if channel.localClosed: - return # we're already closed - log.msg('sending close %i' % channel.id) - self.transport.sendPacket(MSG_CHANNEL_CLOSE, struct.pack('>L', - self.channelsToRemoteChannel[channel])) - channel.localClosed = True - if channel.localClosed and channel.remoteClosed: - self.channelClosed(channel) - - # methods to override - def getChannel(self, channelType, windowSize, maxPacket, data): - """ - The other side requested a channel of some sort. - channelType is the type of channel being requested, - windowSize is the initial size of the remote window, - maxPacket is the largest packet we should send, - data is any other packet data (often nothing). - - We return a subclass of L{SSHChannel}. - - By default, this dispatches to a method 'channel_channelType' with any - non-alphanumerics in the channelType replace with _'s. If it cannot - find a suitable method, it returns an OPEN_UNKNOWN_CHANNEL_TYPE error. - The method is called with arguments of windowSize, maxPacket, data. - - @type channelType: C{str} - @type windowSize: C{int} - @type maxPacket: C{int} - @type data: C{str} - @rtype: subclass of L{SSHChannel}/C{tuple} - """ - log.msg('got channel %s request' % channelType) - if hasattr(self.transport, "avatar"): # this is a server! - chan = self.transport.avatar.lookupChannel(channelType, - windowSize, - maxPacket, - data) - else: - channelType = channelType.translate(TRANSLATE_TABLE) - f = getattr(self, 'channel_%s' % channelType, None) - if f is not None: - chan = f(windowSize, maxPacket, data) - else: - chan = None - if chan is None: - raise error.ConchError('unknown channel', - OPEN_UNKNOWN_CHANNEL_TYPE) - else: - chan.conn = self - return chan - - def gotGlobalRequest(self, requestType, data): - """ - We got a global request. pretty much, this is just used by the client - to request that we forward a port from the server to the client. - Returns either: - - 1: request accepted - - 1, <data>: request accepted with request specific data - - 0: request denied - - By default, this dispatches to a method 'global_requestType' with - -'s in requestType replaced with _'s. The found method is passed data. - If this method cannot be found, this method returns 0. Otherwise, it - returns the return value of that method. - - @type requestType: C{str} - @type data: C{str} - @rtype: C{int}/C{tuple} - """ - log.msg('got global %s request' % requestType) - if hasattr(self.transport, 'avatar'): # this is a server! - return self.transport.avatar.gotGlobalRequest(requestType, data) - - requestType = requestType.replace('-','_') - f = getattr(self, 'global_%s' % requestType, None) - if not f: - return 0 - return f(data) - - def channelClosed(self, channel): - """ - Called when a channel is closed. - It clears the local state related to the channel, and calls - channel.closed(). - MAKE SURE YOU CALL THIS METHOD, even if you subclass L{SSHConnection}. - If you don't, things will break mysteriously. - - @type channel: L{SSHChannel} - """ - if channel in self.channelsToRemoteChannel: # actually open - channel.localClosed = channel.remoteClosed = True - del self.localToRemoteChannel[channel.id] - del self.channels[channel.id] - del self.channelsToRemoteChannel[channel] - for d in self.deferreds.setdefault(channel.id, []): - d.errback(error.ConchError("Channel closed.")) - del self.deferreds[channel.id][:] - log.callWithLogger(channel, channel.closed) - -MSG_GLOBAL_REQUEST = 80 -MSG_REQUEST_SUCCESS = 81 -MSG_REQUEST_FAILURE = 82 -MSG_CHANNEL_OPEN = 90 -MSG_CHANNEL_OPEN_CONFIRMATION = 91 -MSG_CHANNEL_OPEN_FAILURE = 92 -MSG_CHANNEL_WINDOW_ADJUST = 93 -MSG_CHANNEL_DATA = 94 -MSG_CHANNEL_EXTENDED_DATA = 95 -MSG_CHANNEL_EOF = 96 -MSG_CHANNEL_CLOSE = 97 -MSG_CHANNEL_REQUEST = 98 -MSG_CHANNEL_SUCCESS = 99 -MSG_CHANNEL_FAILURE = 100 - -OPEN_ADMINISTRATIVELY_PROHIBITED = 1 -OPEN_CONNECT_FAILED = 2 -OPEN_UNKNOWN_CHANNEL_TYPE = 3 -OPEN_RESOURCE_SHORTAGE = 4 - -EXTENDED_DATA_STDERR = 1 - -messages = {} -for name, value in locals().copy().items(): - if name[:4] == 'MSG_': - messages[value] = name # doesn't handle doubles - -import string -alphanums = string.letters + string.digits -TRANSLATE_TABLE = ''.join([chr(i) in alphanums and chr(i) or '_' - for i in range(256)]) -SSHConnection.protocolMessages = messages diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/factory.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/factory.py deleted file mode 100755 index 3c50932f..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/factory.py +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -A Factory for SSH servers, along with an OpenSSHFactory to use the same -data sources as OpenSSH. - -Maintainer: Paul Swartz -""" - -from twisted.internet import protocol -from twisted.python import log -from twisted.python.reflect import qual - -from twisted.conch import error -from twisted.conch.ssh import keys -import transport, userauth, connection - -import random -import warnings - -class SSHFactory(protocol.Factory): - """ - A Factory for SSH servers. - """ - protocol = transport.SSHServerTransport - - services = { - 'ssh-userauth':userauth.SSHUserAuthServer, - 'ssh-connection':connection.SSHConnection - } - def startFactory(self): - """ - Check for public and private keys. - """ - if not hasattr(self,'publicKeys'): - self.publicKeys = self.getPublicKeys() - for keyType, value in self.publicKeys.items(): - if isinstance(value, str): - warnings.warn("Returning a mapping from strings to " - "strings from getPublicKeys()/publicKeys (in %s) " - "is deprecated. Return a mapping from " - "strings to Key objects instead." % - (qual(self.__class__)), - DeprecationWarning, stacklevel=1) - self.publicKeys[keyType] = keys.Key.fromString(value) - if not hasattr(self,'privateKeys'): - self.privateKeys = self.getPrivateKeys() - for keyType, value in self.privateKeys.items(): - if not isinstance(value, keys.Key): - warnings.warn("Returning a mapping from strings to " - "PyCrypto key objects from " - "getPrivateKeys()/privateKeys (in %s) " - "is deprecated. Return a mapping from " - "strings to Key objects instead." % - (qual(self.__class__),), - DeprecationWarning, stacklevel=1) - self.privateKeys[keyType] = keys.Key(value) - if not self.publicKeys or not self.privateKeys: - raise error.ConchError('no host keys, failing') - if not hasattr(self,'primes'): - self.primes = self.getPrimes() - - - def buildProtocol(self, addr): - """ - Create an instance of the server side of the SSH protocol. - - @type addr: L{twisted.internet.interfaces.IAddress} provider - @param addr: The address at which the server will listen. - - @rtype: L{twisted.conch.ssh.SSHServerTransport} - @return: The built transport. - """ - t = protocol.Factory.buildProtocol(self, addr) - t.supportedPublicKeys = self.privateKeys.keys() - if not self.primes: - log.msg('disabling diffie-hellman-group-exchange because we ' - 'cannot find moduli file') - ske = t.supportedKeyExchanges[:] - ske.remove('diffie-hellman-group-exchange-sha1') - t.supportedKeyExchanges = ske - return t - - - def getPublicKeys(self): - """ - Called when the factory is started to get the public portions of the - servers host keys. Returns a dictionary mapping SSH key types to - public key strings. - - @rtype: C{dict} - """ - raise NotImplementedError('getPublicKeys unimplemented') - - - def getPrivateKeys(self): - """ - Called when the factory is started to get the private portions of the - servers host keys. Returns a dictionary mapping SSH key types to - C{Crypto.PublicKey.pubkey.pubkey} objects. - - @rtype: C{dict} - """ - raise NotImplementedError('getPrivateKeys unimplemented') - - - def getPrimes(self): - """ - Called when the factory is started to get Diffie-Hellman generators and - primes to use. Returns a dictionary mapping number of bits to lists - of tuple of (generator, prime). - - @rtype: C{dict} - """ - - - def getDHPrime(self, bits): - """ - Return a tuple of (g, p) for a Diffe-Hellman process, with p being as - close to bits bits as possible. - - @type bits: C{int} - @rtype: C{tuple} - """ - primesKeys = self.primes.keys() - primesKeys.sort(lambda x, y: cmp(abs(x - bits), abs(y - bits))) - realBits = primesKeys[0] - return random.choice(self.primes[realBits]) - - - def getService(self, transport, service): - """ - Return a class to use as a service for the given transport. - - @type transport: L{transport.SSHServerTransport} - @type service: C{str} - @rtype: subclass of L{service.SSHService} - """ - if service == 'ssh-userauth' or hasattr(transport, 'avatar'): - return self.services[service] diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/filetransfer.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/filetransfer.py deleted file mode 100755 index 9b11db0d..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/filetransfer.py +++ /dev/null @@ -1,934 +0,0 @@ -# -*- test-case-name: twisted.conch.test.test_filetransfer -*- -# -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - - -import struct, errno - -from twisted.internet import defer, protocol -from twisted.python import failure, log - -from common import NS, getNS -from twisted.conch.interfaces import ISFTPServer, ISFTPFile - -from zope import interface - - - -class FileTransferBase(protocol.Protocol): - - versions = (3, ) - - packetTypes = {} - - def __init__(self): - self.buf = '' - self.otherVersion = None # this gets set - - def sendPacket(self, kind, data): - self.transport.write(struct.pack('!LB', len(data)+1, kind) + data) - - def dataReceived(self, data): - self.buf += data - while len(self.buf) > 5: - length, kind = struct.unpack('!LB', self.buf[:5]) - if len(self.buf) < 4 + length: - return - data, self.buf = self.buf[5:4+length], self.buf[4+length:] - packetType = self.packetTypes.get(kind, None) - if not packetType: - log.msg('no packet type for', kind) - continue - f = getattr(self, 'packet_%s' % packetType, None) - if not f: - log.msg('not implemented: %s' % packetType) - log.msg(repr(data[4:])) - reqId, = struct.unpack('!L', data[:4]) - self._sendStatus(reqId, FX_OP_UNSUPPORTED, - "don't understand %s" % packetType) - #XXX not implemented - continue - try: - f(data) - except: - log.err() - continue - reqId ,= struct.unpack('!L', data[:4]) - self._ebStatus(failure.Failure(e), reqId) - - def _parseAttributes(self, data): - flags ,= struct.unpack('!L', data[:4]) - attrs = {} - data = data[4:] - if flags & FILEXFER_ATTR_SIZE == FILEXFER_ATTR_SIZE: - size ,= struct.unpack('!Q', data[:8]) - attrs['size'] = size - data = data[8:] - if flags & FILEXFER_ATTR_OWNERGROUP == FILEXFER_ATTR_OWNERGROUP: - uid, gid = struct.unpack('!2L', data[:8]) - attrs['uid'] = uid - attrs['gid'] = gid - data = data[8:] - if flags & FILEXFER_ATTR_PERMISSIONS == FILEXFER_ATTR_PERMISSIONS: - perms ,= struct.unpack('!L', data[:4]) - attrs['permissions'] = perms - data = data[4:] - if flags & FILEXFER_ATTR_ACMODTIME == FILEXFER_ATTR_ACMODTIME: - atime, mtime = struct.unpack('!2L', data[:8]) - attrs['atime'] = atime - attrs['mtime'] = mtime - data = data[8:] - if flags & FILEXFER_ATTR_EXTENDED == FILEXFER_ATTR_EXTENDED: - extended_count ,= struct.unpack('!L', data[:4]) - data = data[4:] - for i in xrange(extended_count): - extended_type, data = getNS(data) - extended_data, data = getNS(data) - attrs['ext_%s' % extended_type] = extended_data - return attrs, data - - def _packAttributes(self, attrs): - flags = 0 - data = '' - if 'size' in attrs: - data += struct.pack('!Q', attrs['size']) - flags |= FILEXFER_ATTR_SIZE - if 'uid' in attrs and 'gid' in attrs: - data += struct.pack('!2L', attrs['uid'], attrs['gid']) - flags |= FILEXFER_ATTR_OWNERGROUP - if 'permissions' in attrs: - data += struct.pack('!L', attrs['permissions']) - flags |= FILEXFER_ATTR_PERMISSIONS - if 'atime' in attrs and 'mtime' in attrs: - data += struct.pack('!2L', attrs['atime'], attrs['mtime']) - flags |= FILEXFER_ATTR_ACMODTIME - extended = [] - for k in attrs: - if k.startswith('ext_'): - ext_type = NS(k[4:]) - ext_data = NS(attrs[k]) - extended.append(ext_type+ext_data) - if extended: - data += struct.pack('!L', len(extended)) - data += ''.join(extended) - flags |= FILEXFER_ATTR_EXTENDED - return struct.pack('!L', flags) + data - -class FileTransferServer(FileTransferBase): - - def __init__(self, data=None, avatar=None): - FileTransferBase.__init__(self) - self.client = ISFTPServer(avatar) # yay interfaces - self.openFiles = {} - self.openDirs = {} - - def packet_INIT(self, data): - version ,= struct.unpack('!L', data[:4]) - self.version = min(list(self.versions) + [version]) - data = data[4:] - ext = {} - while data: - ext_name, data = getNS(data) - ext_data, data = getNS(data) - ext[ext_name] = ext_data - our_ext = self.client.gotVersion(version, ext) - our_ext_data = "" - for (k,v) in our_ext.items(): - our_ext_data += NS(k) + NS(v) - self.sendPacket(FXP_VERSION, struct.pack('!L', self.version) + \ - our_ext_data) - - def packet_OPEN(self, data): - requestId = data[:4] - data = data[4:] - filename, data = getNS(data) - flags ,= struct.unpack('!L', data[:4]) - data = data[4:] - attrs, data = self._parseAttributes(data) - assert data == '', 'still have data in OPEN: %s' % repr(data) - d = defer.maybeDeferred(self.client.openFile, filename, flags, attrs) - d.addCallback(self._cbOpenFile, requestId) - d.addErrback(self._ebStatus, requestId, "open failed") - - def _cbOpenFile(self, fileObj, requestId): - fileId = str(hash(fileObj)) - if fileId in self.openFiles: - raise KeyError, 'id already open' - self.openFiles[fileId] = fileObj - self.sendPacket(FXP_HANDLE, requestId + NS(fileId)) - - def packet_CLOSE(self, data): - requestId = data[:4] - data = data[4:] - handle, data = getNS(data) - assert data == '', 'still have data in CLOSE: %s' % repr(data) - if handle in self.openFiles: - fileObj = self.openFiles[handle] - d = defer.maybeDeferred(fileObj.close) - d.addCallback(self._cbClose, handle, requestId) - d.addErrback(self._ebStatus, requestId, "close failed") - elif handle in self.openDirs: - dirObj = self.openDirs[handle][0] - d = defer.maybeDeferred(dirObj.close) - d.addCallback(self._cbClose, handle, requestId, 1) - d.addErrback(self._ebStatus, requestId, "close failed") - else: - self._ebClose(failure.Failure(KeyError()), requestId) - - def _cbClose(self, result, handle, requestId, isDir = 0): - if isDir: - del self.openDirs[handle] - else: - del self.openFiles[handle] - self._sendStatus(requestId, FX_OK, 'file closed') - - def packet_READ(self, data): - requestId = data[:4] - data = data[4:] - handle, data = getNS(data) - (offset, length), data = struct.unpack('!QL', data[:12]), data[12:] - assert data == '', 'still have data in READ: %s' % repr(data) - if handle not in self.openFiles: - self._ebRead(failure.Failure(KeyError()), requestId) - else: - fileObj = self.openFiles[handle] - d = defer.maybeDeferred(fileObj.readChunk, offset, length) - d.addCallback(self._cbRead, requestId) - d.addErrback(self._ebStatus, requestId, "read failed") - - def _cbRead(self, result, requestId): - if result == '': # python's read will return this for EOF - raise EOFError() - self.sendPacket(FXP_DATA, requestId + NS(result)) - - def packet_WRITE(self, data): - requestId = data[:4] - data = data[4:] - handle, data = getNS(data) - offset, = struct.unpack('!Q', data[:8]) - data = data[8:] - writeData, data = getNS(data) - assert data == '', 'still have data in WRITE: %s' % repr(data) - if handle not in self.openFiles: - self._ebWrite(failure.Failure(KeyError()), requestId) - else: - fileObj = self.openFiles[handle] - d = defer.maybeDeferred(fileObj.writeChunk, offset, writeData) - d.addCallback(self._cbStatus, requestId, "write succeeded") - d.addErrback(self._ebStatus, requestId, "write failed") - - def packet_REMOVE(self, data): - requestId = data[:4] - data = data[4:] - filename, data = getNS(data) - assert data == '', 'still have data in REMOVE: %s' % repr(data) - d = defer.maybeDeferred(self.client.removeFile, filename) - d.addCallback(self._cbStatus, requestId, "remove succeeded") - d.addErrback(self._ebStatus, requestId, "remove failed") - - def packet_RENAME(self, data): - requestId = data[:4] - data = data[4:] - oldPath, data = getNS(data) - newPath, data = getNS(data) - assert data == '', 'still have data in RENAME: %s' % repr(data) - d = defer.maybeDeferred(self.client.renameFile, oldPath, newPath) - d.addCallback(self._cbStatus, requestId, "rename succeeded") - d.addErrback(self._ebStatus, requestId, "rename failed") - - def packet_MKDIR(self, data): - requestId = data[:4] - data = data[4:] - path, data = getNS(data) - attrs, data = self._parseAttributes(data) - assert data == '', 'still have data in MKDIR: %s' % repr(data) - d = defer.maybeDeferred(self.client.makeDirectory, path, attrs) - d.addCallback(self._cbStatus, requestId, "mkdir succeeded") - d.addErrback(self._ebStatus, requestId, "mkdir failed") - - def packet_RMDIR(self, data): - requestId = data[:4] - data = data[4:] - path, data = getNS(data) - assert data == '', 'still have data in RMDIR: %s' % repr(data) - d = defer.maybeDeferred(self.client.removeDirectory, path) - d.addCallback(self._cbStatus, requestId, "rmdir succeeded") - d.addErrback(self._ebStatus, requestId, "rmdir failed") - - def packet_OPENDIR(self, data): - requestId = data[:4] - data = data[4:] - path, data = getNS(data) - assert data == '', 'still have data in OPENDIR: %s' % repr(data) - d = defer.maybeDeferred(self.client.openDirectory, path) - d.addCallback(self._cbOpenDirectory, requestId) - d.addErrback(self._ebStatus, requestId, "opendir failed") - - def _cbOpenDirectory(self, dirObj, requestId): - handle = str(hash(dirObj)) - if handle in self.openDirs: - raise KeyError, "already opened this directory" - self.openDirs[handle] = [dirObj, iter(dirObj)] - self.sendPacket(FXP_HANDLE, requestId + NS(handle)) - - def packet_READDIR(self, data): - requestId = data[:4] - data = data[4:] - handle, data = getNS(data) - assert data == '', 'still have data in READDIR: %s' % repr(data) - if handle not in self.openDirs: - self._ebStatus(failure.Failure(KeyError()), requestId) - else: - dirObj, dirIter = self.openDirs[handle] - d = defer.maybeDeferred(self._scanDirectory, dirIter, []) - d.addCallback(self._cbSendDirectory, requestId) - d.addErrback(self._ebStatus, requestId, "scan directory failed") - - def _scanDirectory(self, dirIter, f): - while len(f) < 250: - try: - info = dirIter.next() - except StopIteration: - if not f: - raise EOFError - return f - if isinstance(info, defer.Deferred): - info.addCallback(self._cbScanDirectory, dirIter, f) - return - else: - f.append(info) - return f - - def _cbScanDirectory(self, result, dirIter, f): - f.append(result) - return self._scanDirectory(dirIter, f) - - def _cbSendDirectory(self, result, requestId): - data = '' - for (filename, longname, attrs) in result: - data += NS(filename) - data += NS(longname) - data += self._packAttributes(attrs) - self.sendPacket(FXP_NAME, requestId + - struct.pack('!L', len(result))+data) - - def packet_STAT(self, data, followLinks = 1): - requestId = data[:4] - data = data[4:] - path, data = getNS(data) - assert data == '', 'still have data in STAT/LSTAT: %s' % repr(data) - d = defer.maybeDeferred(self.client.getAttrs, path, followLinks) - d.addCallback(self._cbStat, requestId) - d.addErrback(self._ebStatus, requestId, 'stat/lstat failed') - - def packet_LSTAT(self, data): - self.packet_STAT(data, 0) - - def packet_FSTAT(self, data): - requestId = data[:4] - data = data[4:] - handle, data = getNS(data) - assert data == '', 'still have data in FSTAT: %s' % repr(data) - if handle not in self.openFiles: - self._ebStatus(failure.Failure(KeyError('%s not in self.openFiles' - % handle)), requestId) - else: - fileObj = self.openFiles[handle] - d = defer.maybeDeferred(fileObj.getAttrs) - d.addCallback(self._cbStat, requestId) - d.addErrback(self._ebStatus, requestId, 'fstat failed') - - def _cbStat(self, result, requestId): - data = requestId + self._packAttributes(result) - self.sendPacket(FXP_ATTRS, data) - - def packet_SETSTAT(self, data): - requestId = data[:4] - data = data[4:] - path, data = getNS(data) - attrs, data = self._parseAttributes(data) - if data != '': - log.msg('WARN: still have data in SETSTAT: %s' % repr(data)) - d = defer.maybeDeferred(self.client.setAttrs, path, attrs) - d.addCallback(self._cbStatus, requestId, 'setstat succeeded') - d.addErrback(self._ebStatus, requestId, 'setstat failed') - - def packet_FSETSTAT(self, data): - requestId = data[:4] - data = data[4:] - handle, data = getNS(data) - attrs, data = self._parseAttributes(data) - assert data == '', 'still have data in FSETSTAT: %s' % repr(data) - if handle not in self.openFiles: - self._ebStatus(failure.Failure(KeyError()), requestId) - else: - fileObj = self.openFiles[handle] - d = defer.maybeDeferred(fileObj.setAttrs, attrs) - d.addCallback(self._cbStatus, requestId, 'fsetstat succeeded') - d.addErrback(self._ebStatus, requestId, 'fsetstat failed') - - def packet_READLINK(self, data): - requestId = data[:4] - data = data[4:] - path, data = getNS(data) - assert data == '', 'still have data in READLINK: %s' % repr(data) - d = defer.maybeDeferred(self.client.readLink, path) - d.addCallback(self._cbReadLink, requestId) - d.addErrback(self._ebStatus, requestId, 'readlink failed') - - def _cbReadLink(self, result, requestId): - self._cbSendDirectory([(result, '', {})], requestId) - - def packet_SYMLINK(self, data): - requestId = data[:4] - data = data[4:] - linkPath, data = getNS(data) - targetPath, data = getNS(data) - d = defer.maybeDeferred(self.client.makeLink, linkPath, targetPath) - d.addCallback(self._cbStatus, requestId, 'symlink succeeded') - d.addErrback(self._ebStatus, requestId, 'symlink failed') - - def packet_REALPATH(self, data): - requestId = data[:4] - data = data[4:] - path, data = getNS(data) - assert data == '', 'still have data in REALPATH: %s' % repr(data) - d = defer.maybeDeferred(self.client.realPath, path) - d.addCallback(self._cbReadLink, requestId) # same return format - d.addErrback(self._ebStatus, requestId, 'realpath failed') - - def packet_EXTENDED(self, data): - requestId = data[:4] - data = data[4:] - extName, extData = getNS(data) - d = defer.maybeDeferred(self.client.extendedRequest, extName, extData) - d.addCallback(self._cbExtended, requestId) - d.addErrback(self._ebStatus, requestId, 'extended %s failed' % extName) - - def _cbExtended(self, data, requestId): - self.sendPacket(FXP_EXTENDED_REPLY, requestId + data) - - def _cbStatus(self, result, requestId, msg = "request succeeded"): - self._sendStatus(requestId, FX_OK, msg) - - def _ebStatus(self, reason, requestId, msg = "request failed"): - code = FX_FAILURE - message = msg - if reason.type in (IOError, OSError): - if reason.value.errno == errno.ENOENT: # no such file - code = FX_NO_SUCH_FILE - message = reason.value.strerror - elif reason.value.errno == errno.EACCES: # permission denied - code = FX_PERMISSION_DENIED - message = reason.value.strerror - elif reason.value.errno == errno.EEXIST: - code = FX_FILE_ALREADY_EXISTS - else: - log.err(reason) - elif reason.type == EOFError: # EOF - code = FX_EOF - if reason.value.args: - message = reason.value.args[0] - elif reason.type == NotImplementedError: - code = FX_OP_UNSUPPORTED - if reason.value.args: - message = reason.value.args[0] - elif reason.type == SFTPError: - code = reason.value.code - message = reason.value.message - else: - log.err(reason) - self._sendStatus(requestId, code, message) - - def _sendStatus(self, requestId, code, message, lang = ''): - """ - Helper method to send a FXP_STATUS message. - """ - data = requestId + struct.pack('!L', code) - data += NS(message) - data += NS(lang) - self.sendPacket(FXP_STATUS, data) - - - def connectionLost(self, reason): - """ - Clean all opened files and directories. - """ - for fileObj in self.openFiles.values(): - fileObj.close() - self.openFiles = {} - for (dirObj, dirIter) in self.openDirs.values(): - dirObj.close() - self.openDirs = {} - - - -class FileTransferClient(FileTransferBase): - - def __init__(self, extData = {}): - """ - @param extData: a dict of extended_name : extended_data items - to be sent to the server. - """ - FileTransferBase.__init__(self) - self.extData = {} - self.counter = 0 - self.openRequests = {} # id -> Deferred - self.wasAFile = {} # Deferred -> 1 TERRIBLE HACK - - def connectionMade(self): - data = struct.pack('!L', max(self.versions)) - for k,v in self.extData.itervalues(): - data += NS(k) + NS(v) - self.sendPacket(FXP_INIT, data) - - def _sendRequest(self, msg, data): - data = struct.pack('!L', self.counter) + data - d = defer.Deferred() - self.openRequests[self.counter] = d - self.counter += 1 - self.sendPacket(msg, data) - return d - - def _parseRequest(self, data): - (id,) = struct.unpack('!L', data[:4]) - d = self.openRequests[id] - del self.openRequests[id] - return d, data[4:] - - def openFile(self, filename, flags, attrs): - """ - Open a file. - - This method returns a L{Deferred} that is called back with an object - that provides the L{ISFTPFile} interface. - - @param filename: a string representing the file to open. - - @param flags: a integer of the flags to open the file with, ORed together. - The flags and their values are listed at the bottom of this file. - - @param attrs: a list of attributes to open the file with. It is a - dictionary, consisting of 0 or more keys. The possible keys are:: - - size: the size of the file in bytes - uid: the user ID of the file as an integer - gid: the group ID of the file as an integer - permissions: the permissions of the file with as an integer. - the bit representation of this field is defined by POSIX. - atime: the access time of the file as seconds since the epoch. - mtime: the modification time of the file as seconds since the epoch. - ext_*: extended attributes. The server is not required to - understand this, but it may. - - NOTE: there is no way to indicate text or binary files. it is up - to the SFTP client to deal with this. - """ - data = NS(filename) + struct.pack('!L', flags) + self._packAttributes(attrs) - d = self._sendRequest(FXP_OPEN, data) - self.wasAFile[d] = (1, filename) # HACK - return d - - def removeFile(self, filename): - """ - Remove the given file. - - This method returns a Deferred that is called back when it succeeds. - - @param filename: the name of the file as a string. - """ - return self._sendRequest(FXP_REMOVE, NS(filename)) - - def renameFile(self, oldpath, newpath): - """ - Rename the given file. - - This method returns a Deferred that is called back when it succeeds. - - @param oldpath: the current location of the file. - @param newpath: the new file name. - """ - return self._sendRequest(FXP_RENAME, NS(oldpath)+NS(newpath)) - - def makeDirectory(self, path, attrs): - """ - Make a directory. - - This method returns a Deferred that is called back when it is - created. - - @param path: the name of the directory to create as a string. - - @param attrs: a dictionary of attributes to create the directory - with. Its meaning is the same as the attrs in the openFile method. - """ - return self._sendRequest(FXP_MKDIR, NS(path)+self._packAttributes(attrs)) - - def removeDirectory(self, path): - """ - Remove a directory (non-recursively) - - It is an error to remove a directory that has files or directories in - it. - - This method returns a Deferred that is called back when it is removed. - - @param path: the directory to remove. - """ - return self._sendRequest(FXP_RMDIR, NS(path)) - - def openDirectory(self, path): - """ - Open a directory for scanning. - - This method returns a Deferred that is called back with an iterable - object that has a close() method. - - The close() method is called when the client is finished reading - from the directory. At this point, the iterable will no longer - be used. - - The iterable returns triples of the form (filename, longname, attrs) - or a Deferred that returns the same. The sequence must support - __getitem__, but otherwise may be any 'sequence-like' object. - - filename is the name of the file relative to the directory. - logname is an expanded format of the filename. The recommended format - is: - -rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer - 1234567890 123 12345678 12345678 12345678 123456789012 - - The first line is sample output, the second is the length of the field. - The fields are: permissions, link count, user owner, group owner, - size in bytes, modification time. - - attrs is a dictionary in the format of the attrs argument to openFile. - - @param path: the directory to open. - """ - d = self._sendRequest(FXP_OPENDIR, NS(path)) - self.wasAFile[d] = (0, path) - return d - - def getAttrs(self, path, followLinks=0): - """ - Return the attributes for the given path. - - This method returns a dictionary in the same format as the attrs - argument to openFile or a Deferred that is called back with same. - - @param path: the path to return attributes for as a string. - @param followLinks: a boolean. if it is True, follow symbolic links - and return attributes for the real path at the base. if it is False, - return attributes for the specified path. - """ - if followLinks: m = FXP_STAT - else: m = FXP_LSTAT - return self._sendRequest(m, NS(path)) - - def setAttrs(self, path, attrs): - """ - Set the attributes for the path. - - This method returns when the attributes are set or a Deferred that is - called back when they are. - - @param path: the path to set attributes for as a string. - @param attrs: a dictionary in the same format as the attrs argument to - openFile. - """ - data = NS(path) + self._packAttributes(attrs) - return self._sendRequest(FXP_SETSTAT, data) - - def readLink(self, path): - """ - Find the root of a set of symbolic links. - - This method returns the target of the link, or a Deferred that - returns the same. - - @param path: the path of the symlink to read. - """ - d = self._sendRequest(FXP_READLINK, NS(path)) - return d.addCallback(self._cbRealPath) - - def makeLink(self, linkPath, targetPath): - """ - Create a symbolic link. - - This method returns when the link is made, or a Deferred that - returns the same. - - @param linkPath: the pathname of the symlink as a string - @param targetPath: the path of the target of the link as a string. - """ - return self._sendRequest(FXP_SYMLINK, NS(linkPath)+NS(targetPath)) - - def realPath(self, path): - """ - Convert any path to an absolute path. - - This method returns the absolute path as a string, or a Deferred - that returns the same. - - @param path: the path to convert as a string. - """ - d = self._sendRequest(FXP_REALPATH, NS(path)) - return d.addCallback(self._cbRealPath) - - def _cbRealPath(self, result): - name, longname, attrs = result[0] - return name - - def extendedRequest(self, request, data): - """ - Make an extended request of the server. - - The method returns a Deferred that is called back with - the result of the extended request. - - @param request: the name of the extended request to make. - @param data: any other data that goes along with the request. - """ - return self._sendRequest(FXP_EXTENDED, NS(request) + data) - - def packet_VERSION(self, data): - version, = struct.unpack('!L', data[:4]) - data = data[4:] - d = {} - while data: - k, data = getNS(data) - v, data = getNS(data) - d[k]=v - self.version = version - self.gotServerVersion(version, d) - - def packet_STATUS(self, data): - d, data = self._parseRequest(data) - code, = struct.unpack('!L', data[:4]) - data = data[4:] - if len(data) >= 4: - msg, data = getNS(data) - if len(data) >= 4: - lang, data = getNS(data) - else: - lang = '' - else: - msg = '' - lang = '' - if code == FX_OK: - d.callback((msg, lang)) - elif code == FX_EOF: - d.errback(EOFError(msg)) - elif code == FX_OP_UNSUPPORTED: - d.errback(NotImplementedError(msg)) - else: - d.errback(SFTPError(code, msg, lang)) - - def packet_HANDLE(self, data): - d, data = self._parseRequest(data) - isFile, name = self.wasAFile.pop(d) - if isFile: - cb = ClientFile(self, getNS(data)[0]) - else: - cb = ClientDirectory(self, getNS(data)[0]) - cb.name = name - d.callback(cb) - - def packet_DATA(self, data): - d, data = self._parseRequest(data) - d.callback(getNS(data)[0]) - - def packet_NAME(self, data): - d, data = self._parseRequest(data) - count, = struct.unpack('!L', data[:4]) - data = data[4:] - files = [] - for i in range(count): - filename, data = getNS(data) - longname, data = getNS(data) - attrs, data = self._parseAttributes(data) - files.append((filename, longname, attrs)) - d.callback(files) - - def packet_ATTRS(self, data): - d, data = self._parseRequest(data) - d.callback(self._parseAttributes(data)[0]) - - def packet_EXTENDED_REPLY(self, data): - d, data = self._parseRequest(data) - d.callback(data) - - def gotServerVersion(self, serverVersion, extData): - """ - Called when the client sends their version info. - - @param otherVersion: an integer representing the version of the SFTP - protocol they are claiming. - @param extData: a dictionary of extended_name : extended_data items. - These items are sent by the client to indicate additional features. - """ - -class ClientFile: - - interface.implements(ISFTPFile) - - def __init__(self, parent, handle): - self.parent = parent - self.handle = NS(handle) - - def close(self): - return self.parent._sendRequest(FXP_CLOSE, self.handle) - - def readChunk(self, offset, length): - data = self.handle + struct.pack("!QL", offset, length) - return self.parent._sendRequest(FXP_READ, data) - - def writeChunk(self, offset, chunk): - data = self.handle + struct.pack("!Q", offset) + NS(chunk) - return self.parent._sendRequest(FXP_WRITE, data) - - def getAttrs(self): - return self.parent._sendRequest(FXP_FSTAT, self.handle) - - def setAttrs(self, attrs): - data = self.handle + self.parent._packAttributes(attrs) - return self.parent._sendRequest(FXP_FSTAT, data) - -class ClientDirectory: - - def __init__(self, parent, handle): - self.parent = parent - self.handle = NS(handle) - self.filesCache = [] - - def read(self): - d = self.parent._sendRequest(FXP_READDIR, self.handle) - return d - - def close(self): - return self.parent._sendRequest(FXP_CLOSE, self.handle) - - def __iter__(self): - return self - - def next(self): - if self.filesCache: - return self.filesCache.pop(0) - d = self.read() - d.addCallback(self._cbReadDir) - d.addErrback(self._ebReadDir) - return d - - def _cbReadDir(self, names): - self.filesCache = names[1:] - return names[0] - - def _ebReadDir(self, reason): - reason.trap(EOFError) - def _(): - raise StopIteration - self.next = _ - return reason - - -class SFTPError(Exception): - - def __init__(self, errorCode, errorMessage, lang = ''): - Exception.__init__(self) - self.code = errorCode - self._message = errorMessage - self.lang = lang - - - def message(self): - """ - A string received over the network that explains the error to a human. - """ - # Python 2.6 deprecates assigning to the 'message' attribute of an - # exception. We define this read-only property here in order to - # prevent the warning about deprecation while maintaining backwards - # compatibility with object clients that rely on the 'message' - # attribute being set correctly. See bug #3897. - return self._message - message = property(message) - - - def __str__(self): - return 'SFTPError %s: %s' % (self.code, self.message) - -FXP_INIT = 1 -FXP_VERSION = 2 -FXP_OPEN = 3 -FXP_CLOSE = 4 -FXP_READ = 5 -FXP_WRITE = 6 -FXP_LSTAT = 7 -FXP_FSTAT = 8 -FXP_SETSTAT = 9 -FXP_FSETSTAT = 10 -FXP_OPENDIR = 11 -FXP_READDIR = 12 -FXP_REMOVE = 13 -FXP_MKDIR = 14 -FXP_RMDIR = 15 -FXP_REALPATH = 16 -FXP_STAT = 17 -FXP_RENAME = 18 -FXP_READLINK = 19 -FXP_SYMLINK = 20 -FXP_STATUS = 101 -FXP_HANDLE = 102 -FXP_DATA = 103 -FXP_NAME = 104 -FXP_ATTRS = 105 -FXP_EXTENDED = 200 -FXP_EXTENDED_REPLY = 201 - -FILEXFER_ATTR_SIZE = 0x00000001 -FILEXFER_ATTR_UIDGID = 0x00000002 -FILEXFER_ATTR_OWNERGROUP = FILEXFER_ATTR_UIDGID -FILEXFER_ATTR_PERMISSIONS = 0x00000004 -FILEXFER_ATTR_ACMODTIME = 0x00000008 -FILEXFER_ATTR_EXTENDED = 0x80000000L - -FILEXFER_TYPE_REGULAR = 1 -FILEXFER_TYPE_DIRECTORY = 2 -FILEXFER_TYPE_SYMLINK = 3 -FILEXFER_TYPE_SPECIAL = 4 -FILEXFER_TYPE_UNKNOWN = 5 - -FXF_READ = 0x00000001 -FXF_WRITE = 0x00000002 -FXF_APPEND = 0x00000004 -FXF_CREAT = 0x00000008 -FXF_TRUNC = 0x00000010 -FXF_EXCL = 0x00000020 -FXF_TEXT = 0x00000040 - -FX_OK = 0 -FX_EOF = 1 -FX_NO_SUCH_FILE = 2 -FX_PERMISSION_DENIED = 3 -FX_FAILURE = 4 -FX_BAD_MESSAGE = 5 -FX_NO_CONNECTION = 6 -FX_CONNECTION_LOST = 7 -FX_OP_UNSUPPORTED = 8 -FX_FILE_ALREADY_EXISTS = 11 -# http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/ defines more -# useful error codes, but so far OpenSSH doesn't implement them. We use them -# internally for clarity, but for now define them all as FX_FAILURE to be -# compatible with existing software. -FX_NOT_A_DIRECTORY = FX_FAILURE -FX_FILE_IS_A_DIRECTORY = FX_FAILURE - - -# initialize FileTransferBase.packetTypes: -g = globals() -for name in g.keys(): - if name.startswith('FXP_'): - value = g[name] - FileTransferBase.packetTypes[value] = name[4:] -del g, name, value diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/forwarding.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/forwarding.py deleted file mode 100755 index 753f9946..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/forwarding.py +++ /dev/null @@ -1,181 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -# - -""" -This module contains the implementation of the TCP forwarding, which allows -clients and servers to forward arbitrary TCP data across the connection. - -Maintainer: Paul Swartz -""" - -import struct - -from twisted.internet import protocol, reactor -from twisted.python import log - -import common, channel - -class SSHListenForwardingFactory(protocol.Factory): - def __init__(self, connection, hostport, klass): - self.conn = connection - self.hostport = hostport # tuple - self.klass = klass - - def buildProtocol(self, addr): - channel = self.klass(conn = self.conn) - client = SSHForwardingClient(channel) - channel.client = client - addrTuple = (addr.host, addr.port) - channelOpenData = packOpen_direct_tcpip(self.hostport, addrTuple) - self.conn.openChannel(channel, channelOpenData) - return client - -class SSHListenForwardingChannel(channel.SSHChannel): - - def channelOpen(self, specificData): - log.msg('opened forwarding channel %s' % self.id) - if len(self.client.buf)>1: - b = self.client.buf[1:] - self.write(b) - self.client.buf = '' - - def openFailed(self, reason): - self.closed() - - def dataReceived(self, data): - self.client.transport.write(data) - - def eofReceived(self): - self.client.transport.loseConnection() - - def closed(self): - if hasattr(self, 'client'): - log.msg('closing local forwarding channel %s' % self.id) - self.client.transport.loseConnection() - del self.client - -class SSHListenClientForwardingChannel(SSHListenForwardingChannel): - - name = 'direct-tcpip' - -class SSHListenServerForwardingChannel(SSHListenForwardingChannel): - - name = 'forwarded-tcpip' - -class SSHConnectForwardingChannel(channel.SSHChannel): - - def __init__(self, hostport, *args, **kw): - channel.SSHChannel.__init__(self, *args, **kw) - self.hostport = hostport - self.client = None - self.clientBuf = '' - - def channelOpen(self, specificData): - cc = protocol.ClientCreator(reactor, SSHForwardingClient, self) - log.msg("connecting to %s:%i" % self.hostport) - cc.connectTCP(*self.hostport).addCallbacks(self._setClient, self._close) - - def _setClient(self, client): - self.client = client - log.msg("connected to %s:%i" % self.hostport) - if self.clientBuf: - self.client.transport.write(self.clientBuf) - self.clientBuf = None - if self.client.buf[1:]: - self.write(self.client.buf[1:]) - self.client.buf = '' - - def _close(self, reason): - log.msg("failed to connect: %s" % reason) - self.loseConnection() - - def dataReceived(self, data): - if self.client: - self.client.transport.write(data) - else: - self.clientBuf += data - - def closed(self): - if self.client: - log.msg('closed remote forwarding channel %s' % self.id) - if self.client.channel: - self.loseConnection() - self.client.transport.loseConnection() - del self.client - -def openConnectForwardingClient(remoteWindow, remoteMaxPacket, data, avatar): - remoteHP, origHP = unpackOpen_direct_tcpip(data) - return SSHConnectForwardingChannel(remoteHP, - remoteWindow=remoteWindow, - remoteMaxPacket=remoteMaxPacket, - avatar=avatar) - -class SSHForwardingClient(protocol.Protocol): - - def __init__(self, channel): - self.channel = channel - self.buf = '\000' - - def dataReceived(self, data): - if self.buf: - self.buf += data - else: - self.channel.write(data) - - def connectionLost(self, reason): - if self.channel: - self.channel.loseConnection() - self.channel = None - - -def packOpen_direct_tcpip((connHost, connPort), (origHost, origPort)): - """Pack the data suitable for sending in a CHANNEL_OPEN packet. - """ - conn = common.NS(connHost) + struct.pack('>L', connPort) - orig = common.NS(origHost) + struct.pack('>L', origPort) - return conn + orig - -packOpen_forwarded_tcpip = packOpen_direct_tcpip - -def unpackOpen_direct_tcpip(data): - """Unpack the data to a usable format. - """ - connHost, rest = common.getNS(data) - connPort = int(struct.unpack('>L', rest[:4])[0]) - origHost, rest = common.getNS(rest[4:]) - origPort = int(struct.unpack('>L', rest[:4])[0]) - return (connHost, connPort), (origHost, origPort) - -unpackOpen_forwarded_tcpip = unpackOpen_direct_tcpip - -def packGlobal_tcpip_forward((host, port)): - return common.NS(host) + struct.pack('>L', port) - -def unpackGlobal_tcpip_forward(data): - host, rest = common.getNS(data) - port = int(struct.unpack('>L', rest[:4])[0]) - return host, port - -"""This is how the data -> eof -> close stuff /should/ work. - -debug3: channel 1: waiting for connection -debug1: channel 1: connected -debug1: channel 1: read<=0 rfd 7 len 0 -debug1: channel 1: read failed -debug1: channel 1: close_read -debug1: channel 1: input open -> drain -debug1: channel 1: ibuf empty -debug1: channel 1: send eof -debug1: channel 1: input drain -> closed -debug1: channel 1: rcvd eof -debug1: channel 1: output open -> drain -debug1: channel 1: obuf empty -debug1: channel 1: close_write -debug1: channel 1: output drain -> closed -debug1: channel 1: rcvd close -debug3: channel 1: will not send data after close -debug1: channel 1: send close -debug1: channel 1: is dead -""" diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/keys.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/keys.py deleted file mode 100755 index 1c223517..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/keys.py +++ /dev/null @@ -1,809 +0,0 @@ -# -*- test-case-name: twisted.conch.test.test_keys -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -Handling of RSA and DSA keys. - -Maintainer: U{Paul Swartz} -""" - -# base library imports -import base64 -import itertools - -# external library imports -from Crypto.Cipher import DES3, AES -from Crypto.PublicKey import RSA, DSA -from Crypto import Util -from pyasn1.type import univ -from pyasn1.codec.ber import decoder as berDecoder -from pyasn1.codec.ber import encoder as berEncoder - -# twisted -from twisted.python import randbytes -from twisted.python.hashlib import md5, sha1 - -# sibling imports -from twisted.conch.ssh import common, sexpy - - -class BadKeyError(Exception): - """ - Raised when a key isn't what we expected from it. - - XXX: we really need to check for bad keys - """ - - -class EncryptedKeyError(Exception): - """ - Raised when an encrypted key is presented to fromString/fromFile without - a password. - """ - - -class Key(object): - """ - An object representing a key. A key can be either a public or - private key. A public key can verify a signature; a private key can - create or verify a signature. To generate a string that can be stored - on disk, use the toString method. If you have a private key, but want - the string representation of the public key, use Key.public().toString(). - - @ivar keyObject: The C{Crypto.PublicKey.pubkey.pubkey} object that - operations are performed with. - """ - - def fromFile(Class, filename, type=None, passphrase=None): - """ - Return a Key object corresponding to the data in filename. type - and passphrase function as they do in fromString. - """ - return Class.fromString(file(filename, 'rb').read(), type, passphrase) - fromFile = classmethod(fromFile) - - def fromString(Class, data, type=None, passphrase=None): - """ - Return a Key object corresponding to the string data. - type is optionally the type of string, matching a _fromString_* - method. Otherwise, the _guessStringType() classmethod will be used - to guess a type. If the key is encrypted, passphrase is used as - the decryption key. - - @type data: C{str} - @type type: C{None}/C{str} - @type passphrase: C{None}/C{str} - @rtype: C{Key} - """ - if type is None: - type = Class._guessStringType(data) - if type is None: - raise BadKeyError('cannot guess the type of %r' % data) - method = getattr(Class, '_fromString_%s' % type.upper(), None) - if method is None: - raise BadKeyError('no _fromString method for %s' % type) - if method.func_code.co_argcount == 2: # no passphrase - if passphrase: - raise BadKeyError('key not encrypted') - return method(data) - else: - return method(data, passphrase) - fromString = classmethod(fromString) - - def _fromString_BLOB(Class, blob): - """ - Return a public key object corresponding to this public key blob. - The format of a RSA public key blob is:: - string 'ssh-rsa' - integer e - integer n - - The format of a DSA public key blob is:: - string 'ssh-dss' - integer p - integer q - integer g - integer y - - @type blob: C{str} - @return: a C{Crypto.PublicKey.pubkey.pubkey} object - @raises BadKeyError: if the key type (the first string) is unknown. - """ - keyType, rest = common.getNS(blob) - if keyType == 'ssh-rsa': - e, n, rest = common.getMP(rest, 2) - return Class(RSA.construct((n, e))) - elif keyType == 'ssh-dss': - p, q, g, y, rest = common.getMP(rest, 4) - return Class(DSA.construct((y, g, p, q))) - else: - raise BadKeyError('unknown blob type: %s' % keyType) - _fromString_BLOB = classmethod(_fromString_BLOB) - - def _fromString_PRIVATE_BLOB(Class, blob): - """ - Return a private key object corresponding to this private key blob. - The blob formats are as follows: - - RSA keys:: - string 'ssh-rsa' - integer n - integer e - integer d - integer u - integer p - integer q - - DSA keys:: - string 'ssh-dss' - integer p - integer q - integer g - integer y - integer x - - @type blob: C{str} - @return: a C{Crypto.PublicKey.pubkey.pubkey} object - @raises BadKeyError: if the key type (the first string) is unknown. - """ - keyType, rest = common.getNS(blob) - - if keyType == 'ssh-rsa': - n, e, d, u, p, q, rest = common.getMP(rest, 6) - rsakey = Class(RSA.construct((n, e, d, p, q, u))) - return rsakey - elif keyType == 'ssh-dss': - p, q, g, y, x, rest = common.getMP(rest, 5) - dsakey = Class(DSA.construct((y, g, p, q, x))) - return dsakey - else: - raise BadKeyError('unknown blob type: %s' % keyType) - _fromString_PRIVATE_BLOB = classmethod(_fromString_PRIVATE_BLOB) - - def _fromString_PUBLIC_OPENSSH(Class, data): - """ - Return a public key object corresponding to this OpenSSH public key - string. The format of an OpenSSH public key string is:: - <key type> <base64-encoded public key blob> - - @type data: C{str} - @return: A {Crypto.PublicKey.pubkey.pubkey} object - @raises BadKeyError: if the blob type is unknown. - """ - blob = base64.decodestring(data.split()[1]) - return Class._fromString_BLOB(blob) - _fromString_PUBLIC_OPENSSH = classmethod(_fromString_PUBLIC_OPENSSH) - - def _fromString_PRIVATE_OPENSSH(Class, data, passphrase): - """ - Return a private key object corresponding to this OpenSSH private key - string. If the key is encrypted, passphrase MUST be provided. - Providing a passphrase for an unencrypted key is an error. - - The format of an OpenSSH private key string is:: - -----BEGIN <key type> PRIVATE KEY----- - [Proc-Type: 4,ENCRYPTED - DEK-Info: DES-EDE3-CBC,<initialization value>] - <base64-encoded ASN.1 structure> - ------END <key type> PRIVATE KEY------ - - The ASN.1 structure of a RSA key is:: - (0, n, e, d, p, q) - - The ASN.1 structure of a DSA key is:: - (0, p, q, g, y, x) - - @type data: C{str} - @type passphrase: C{str} - @return: a C{Crypto.PublicKey.pubkey.pubkey} object - @raises BadKeyError: if - * a passphrase is provided for an unencrypted key - * a passphrase is not provided for an encrypted key - * the ASN.1 encoding is incorrect - """ - lines = data.strip().split('\n') - kind = lines[0][11:14] - if lines[1].startswith('Proc-Type: 4,ENCRYPTED'): # encrypted key - try: - _, cipher_iv_info = lines[2].split(' ', 1) - cipher, ivdata = cipher_iv_info.rstrip().split(',', 1) - except ValueError: - raise BadKeyError('invalid DEK-info %r' % lines[2]) - if cipher == 'AES-128-CBC': - CipherClass = AES - keySize = 16 - if len(ivdata) != 32: - raise BadKeyError('AES encrypted key with a bad IV') - elif cipher == 'DES-EDE3-CBC': - CipherClass = DES3 - keySize = 24 - if len(ivdata) != 16: - raise BadKeyError('DES encrypted key with a bad IV') - else: - raise BadKeyError('unknown encryption type %r' % cipher) - iv = ''.join([chr(int(ivdata[i:i + 2], 16)) - for i in range(0, len(ivdata), 2)]) - if not passphrase: - raise EncryptedKeyError('encrypted key with no passphrase') - ba = md5(passphrase + iv[:8]).digest() - bb = md5(ba + passphrase + iv[:8]).digest() - decKey = (ba + bb)[:keySize] - b64Data = base64.decodestring(''.join(lines[3:-1])) - keyData = CipherClass.new(decKey, - CipherClass.MODE_CBC, - iv).decrypt(b64Data) - removeLen = ord(keyData[-1]) - keyData = keyData[:-removeLen] - else: - b64Data = ''.join(lines[1:-1]) - keyData = base64.decodestring(b64Data) - try: - decodedKey = berDecoder.decode(keyData)[0] - except Exception: - raise BadKeyError('something wrong with decode') - if kind == 'RSA': - if len(decodedKey) == 2: # alternate RSA key - decodedKey = decodedKey[0] - if len(decodedKey) < 6: - raise BadKeyError('RSA key failed to decode properly') - n, e, d, p, q = [long(value) for value in decodedKey[1:6]] - if p > q: # make p smaller than q - p, q = q, p - return Class(RSA.construct((n, e, d, p, q))) - elif kind == 'DSA': - p, q, g, y, x = [long(value) for value in decodedKey[1: 6]] - if len(decodedKey) < 6: - raise BadKeyError('DSA key failed to decode properly') - return Class(DSA.construct((y, g, p, q, x))) - _fromString_PRIVATE_OPENSSH = classmethod(_fromString_PRIVATE_OPENSSH) - - def _fromString_PUBLIC_LSH(Class, data): - """ - Return a public key corresponding to this LSH public key string. - The LSH public key string format is:: - <s-expression: ('public-key', (<key type>, (<name, <value>)+))> - - The names for a RSA (key type 'rsa-pkcs1-sha1') key are: n, e. - The names for a DSA (key type 'dsa') key are: y, g, p, q. - - @type data: C{str} - @return: a C{Crypto.PublicKey.pubkey.pubkey} object - @raises BadKeyError: if the key type is unknown - """ - sexp = sexpy.parse(base64.decodestring(data[1:-1])) - assert sexp[0] == 'public-key' - kd = {} - for name, data in sexp[1][1:]: - kd[name] = common.getMP(common.NS(data))[0] - if sexp[1][0] == 'dsa': - return Class(DSA.construct((kd['y'], kd['g'], kd['p'], kd['q']))) - elif sexp[1][0] == 'rsa-pkcs1-sha1': - return Class(RSA.construct((kd['n'], kd['e']))) - else: - raise BadKeyError('unknown lsh key type %s' % sexp[1][0]) - _fromString_PUBLIC_LSH = classmethod(_fromString_PUBLIC_LSH) - - def _fromString_PRIVATE_LSH(Class, data): - """ - Return a private key corresponding to this LSH private key string. - The LSH private key string format is:: - <s-expression: ('private-key', (<key type>, (<name>, <value>)+))> - - The names for a RSA (key type 'rsa-pkcs1-sha1') key are: n, e, d, p, q. - The names for a DSA (key type 'dsa') key are: y, g, p, q, x. - - @type data: C{str} - @return: a {Crypto.PublicKey.pubkey.pubkey} object - @raises BadKeyError: if the key type is unknown - """ - sexp = sexpy.parse(data) - assert sexp[0] == 'private-key' - kd = {} - for name, data in sexp[1][1:]: - kd[name] = common.getMP(common.NS(data))[0] - if sexp[1][0] == 'dsa': - assert len(kd) == 5, len(kd) - return Class(DSA.construct((kd['y'], kd['g'], kd['p'], - kd['q'], kd['x']))) - elif sexp[1][0] == 'rsa-pkcs1': - assert len(kd) == 8, len(kd) - if kd['p'] > kd['q']: # make p smaller than q - kd['p'], kd['q'] = kd['q'], kd['p'] - return Class(RSA.construct((kd['n'], kd['e'], kd['d'], - kd['p'], kd['q']))) - else: - raise BadKeyError('unknown lsh key type %s' % sexp[1][0]) - _fromString_PRIVATE_LSH = classmethod(_fromString_PRIVATE_LSH) - - def _fromString_AGENTV3(Class, data): - """ - Return a private key object corresponsing to the Secure Shell Key - Agent v3 format. - - The SSH Key Agent v3 format for a RSA key is:: - string 'ssh-rsa' - integer e - integer d - integer n - integer u - integer p - integer q - - The SSH Key Agent v3 format for a DSA key is:: - string 'ssh-dss' - integer p - integer q - integer g - integer y - integer x - - @type data: C{str} - @return: a C{Crypto.PublicKey.pubkey.pubkey} object - @raises BadKeyError: if the key type (the first string) is unknown - """ - keyType, data = common.getNS(data) - if keyType == 'ssh-dss': - p, data = common.getMP(data) - q, data = common.getMP(data) - g, data = common.getMP(data) - y, data = common.getMP(data) - x, data = common.getMP(data) - return Class(DSA.construct((y, g, p, q, x))) - elif keyType == 'ssh-rsa': - e, data = common.getMP(data) - d, data = common.getMP(data) - n, data = common.getMP(data) - u, data = common.getMP(data) - p, data = common.getMP(data) - q, data = common.getMP(data) - return Class(RSA.construct((n, e, d, p, q, u))) - else: - raise BadKeyError("unknown key type %s" % keyType) - _fromString_AGENTV3 = classmethod(_fromString_AGENTV3) - - def _guessStringType(Class, data): - """ - Guess the type of key in data. The types map to _fromString_* - methods. - """ - if data.startswith('ssh-'): - return 'public_openssh' - elif data.startswith('-----BEGIN'): - return 'private_openssh' - elif data.startswith('{'): - return 'public_lsh' - elif data.startswith('('): - return 'private_lsh' - elif data.startswith('\x00\x00\x00\x07ssh-'): - ignored, rest = common.getNS(data) - count = 0 - while rest: - count += 1 - ignored, rest = common.getMP(rest) - if count > 4: - return 'agentv3' - else: - return 'blob' - _guessStringType = classmethod(_guessStringType) - - def __init__(self, keyObject): - """ - Initialize a PublicKey with a C{Crypto.PublicKey.pubkey.pubkey} - object. - - @type keyObject: C{Crypto.PublicKey.pubkey.pubkey} - """ - self.keyObject = keyObject - - def __eq__(self, other): - """ - Return True if other represents an object with the same key. - """ - if type(self) == type(other): - return self.type() == other.type() and self.data() == other.data() - else: - return NotImplemented - - def __ne__(self, other): - """ - Return True if other represents anything other than this key. - """ - result = self.__eq__(other) - if result == NotImplemented: - return result - return not result - - def __repr__(self): - """ - Return a pretty representation of this object. - """ - lines = [ - '<%s %s (%s bits)' % ( - self.type(), - self.isPublic() and 'Public Key' or 'Private Key', - self.keyObject.size())] - for k, v in sorted(self.data().items()): - lines.append('attr %s:' % k) - by = common.MP(v)[4:] - while by: - m = by[:15] - by = by[15:] - o = '' - for c in m: - o = o + '%02x:' % ord(c) - if len(m) < 15: - o = o[:-1] - lines.append('\t' + o) - lines[-1] = lines[-1] + '>' - return '\n'.join(lines) - - def isPublic(self): - """ - Returns True if this Key is a public key. - """ - return not self.keyObject.has_private() - - def public(self): - """ - Returns a version of this key containing only the public key data. - If this is a public key, this may or may not be the same object - as self. - """ - return Key(self.keyObject.publickey()) - - def fingerprint(self): - """ - Get the user presentation of the fingerprint of this L{Key}. As - described by U{RFC 4716 section - 4<http://tools.ietf.org/html/rfc4716#section-4>}:: - - The fingerprint of a public key consists of the output of the MD5 - message-digest algorithm [RFC1321]. The input to the algorithm is - the public key data as specified by [RFC4253]. (...) The output - of the (MD5) algorithm is presented to the user as a sequence of 16 - octets printed as hexadecimal with lowercase letters and separated - by colons. - - @since: 8.2 - - @return: the user presentation of this L{Key}'s fingerprint, as a - string. - - @rtype: L{str} - """ - return ':'.join([x.encode('hex') for x in md5(self.blob()).digest()]) - - def type(self): - """ - Return the type of the object we wrap. Currently this can only be - 'RSA' or 'DSA'. - """ - # the class is Crypto.PublicKey.<type>.<stuff we don't care about> - mod = self.keyObject.__class__.__module__ - if mod.startswith('Crypto.PublicKey'): - type = mod.split('.')[2] - else: - raise RuntimeError('unknown type of object: %r' % self.keyObject) - if type in ('RSA', 'DSA'): - return type - else: - raise RuntimeError('unknown type of key: %s' % type) - - def sshType(self): - """ - Return the type of the object we wrap as defined in the ssh protocol. - Currently this can only be 'ssh-rsa' or 'ssh-dss'. - """ - return {'RSA': 'ssh-rsa', 'DSA': 'ssh-dss'}[self.type()] - - def data(self): - """ - Return the values of the public key as a dictionary. - - @rtype: C{dict} - """ - keyData = {} - for name in self.keyObject.keydata: - value = getattr(self.keyObject, name, None) - if value is not None: - keyData[name] = value - return keyData - - def blob(self): - """ - Return the public key blob for this key. The blob is the - over-the-wire format for public keys: - - RSA keys:: - string 'ssh-rsa' - integer e - integer n - - DSA keys:: - string 'ssh-dss' - integer p - integer q - integer g - integer y - - @rtype: C{str} - """ - type = self.type() - data = self.data() - if type == 'RSA': - return (common.NS('ssh-rsa') + common.MP(data['e']) + - common.MP(data['n'])) - elif type == 'DSA': - return (common.NS('ssh-dss') + common.MP(data['p']) + - common.MP(data['q']) + common.MP(data['g']) + - common.MP(data['y'])) - - def privateBlob(self): - """ - Return the private key blob for this key. The blob is the - over-the-wire format for private keys: - - RSA keys:: - string 'ssh-rsa' - integer n - integer e - integer d - integer u - integer p - integer q - - DSA keys:: - string 'ssh-dss' - integer p - integer q - integer g - integer y - integer x - """ - type = self.type() - data = self.data() - if type == 'RSA': - return (common.NS('ssh-rsa') + common.MP(data['n']) + - common.MP(data['e']) + common.MP(data['d']) + - common.MP(data['u']) + common.MP(data['p']) + - common.MP(data['q'])) - elif type == 'DSA': - return (common.NS('ssh-dss') + common.MP(data['p']) + - common.MP(data['q']) + common.MP(data['g']) + - common.MP(data['y']) + common.MP(data['x'])) - - def toString(self, type, extra=None): - """ - Create a string representation of this key. If the key is a private - key and you want the represenation of its public key, use - C{key.public().toString()}. type maps to a _toString_* method. - - @param type: The type of string to emit. Currently supported values - are C{'OPENSSH'}, C{'LSH'}, and C{'AGENTV3'}. - @type type: L{str} - - @param extra: Any extra data supported by the selected format which - is not part of the key itself. For public OpenSSH keys, this is - a comment. For private OpenSSH keys, this is a passphrase to - encrypt with. - @type extra: L{str} or L{NoneType} - - @rtype: L{str} - """ - method = getattr(self, '_toString_%s' % type.upper(), None) - if method is None: - raise BadKeyError('unknown type: %s' % type) - if method.func_code.co_argcount == 2: - return method(extra) - else: - return method() - - def _toString_OPENSSH(self, extra): - """ - Return a public or private OpenSSH string. See - _fromString_PUBLIC_OPENSSH and _fromString_PRIVATE_OPENSSH for the - string formats. If extra is present, it represents a comment for a - public key, or a passphrase for a private key. - - @type extra: C{str} - @rtype: C{str} - """ - data = self.data() - if self.isPublic(): - b64Data = base64.encodestring(self.blob()).replace('\n', '') - if not extra: - extra = '' - return ('%s %s %s' % (self.sshType(), b64Data, extra)).strip() - else: - lines = ['-----BEGIN %s PRIVATE KEY-----' % self.type()] - if self.type() == 'RSA': - p, q = data['p'], data['q'] - objData = (0, data['n'], data['e'], data['d'], q, p, - data['d'] % (q - 1), data['d'] % (p - 1), - data['u']) - else: - objData = (0, data['p'], data['q'], data['g'], data['y'], - data['x']) - asn1Sequence = univ.Sequence() - for index, value in itertools.izip(itertools.count(), objData): - asn1Sequence.setComponentByPosition(index, univ.Integer(value)) - asn1Data = berEncoder.encode(asn1Sequence) - if extra: - iv = randbytes.secureRandom(8) - hexiv = ''.join(['%02X' % ord(x) for x in iv]) - lines.append('Proc-Type: 4,ENCRYPTED') - lines.append('DEK-Info: DES-EDE3-CBC,%s\n' % hexiv) - ba = md5(extra + iv).digest() - bb = md5(ba + extra + iv).digest() - encKey = (ba + bb)[:24] - padLen = 8 - (len(asn1Data) % 8) - asn1Data += (chr(padLen) * padLen) - asn1Data = DES3.new(encKey, DES3.MODE_CBC, - iv).encrypt(asn1Data) - b64Data = base64.encodestring(asn1Data).replace('\n', '') - lines += [b64Data[i:i + 64] for i in range(0, len(b64Data), 64)] - lines.append('-----END %s PRIVATE KEY-----' % self.type()) - return '\n'.join(lines) - - def _toString_LSH(self): - """ - Return a public or private LSH key. See _fromString_PUBLIC_LSH and - _fromString_PRIVATE_LSH for the key formats. - - @rtype: C{str} - """ - data = self.data() - if self.isPublic(): - if self.type() == 'RSA': - keyData = sexpy.pack([['public-key', - ['rsa-pkcs1-sha1', - ['n', common.MP(data['n'])[4:]], - ['e', common.MP(data['e'])[4:]]]]]) - elif self.type() == 'DSA': - keyData = sexpy.pack([['public-key', - ['dsa', - ['p', common.MP(data['p'])[4:]], - ['q', common.MP(data['q'])[4:]], - ['g', common.MP(data['g'])[4:]], - ['y', common.MP(data['y'])[4:]]]]]) - return '{' + base64.encodestring(keyData).replace('\n', '') + '}' - else: - if self.type() == 'RSA': - p, q = data['p'], data['q'] - return sexpy.pack([['private-key', - ['rsa-pkcs1', - ['n', common.MP(data['n'])[4:]], - ['e', common.MP(data['e'])[4:]], - ['d', common.MP(data['d'])[4:]], - ['p', common.MP(q)[4:]], - ['q', common.MP(p)[4:]], - ['a', common.MP(data['d'] % (q - 1))[4:]], - ['b', common.MP(data['d'] % (p - 1))[4:]], - ['c', common.MP(data['u'])[4:]]]]]) - elif self.type() == 'DSA': - return sexpy.pack([['private-key', - ['dsa', - ['p', common.MP(data['p'])[4:]], - ['q', common.MP(data['q'])[4:]], - ['g', common.MP(data['g'])[4:]], - ['y', common.MP(data['y'])[4:]], - ['x', common.MP(data['x'])[4:]]]]]) - - def _toString_AGENTV3(self): - """ - Return a private Secure Shell Agent v3 key. See - _fromString_AGENTV3 for the key format. - - @rtype: C{str} - """ - data = self.data() - if not self.isPublic(): - if self.type() == 'RSA': - values = (data['e'], data['d'], data['n'], data['u'], - data['p'], data['q']) - elif self.type() == 'DSA': - values = (data['p'], data['q'], data['g'], data['y'], - data['x']) - return common.NS(self.sshType()) + ''.join(map(common.MP, values)) - - def sign(self, data): - """ - Returns a signature with this Key. - - @type data: C{str} - @rtype: C{str} - """ - if self.type() == 'RSA': - digest = pkcs1Digest(data, self.keyObject.size() / 8) - signature = self.keyObject.sign(digest, '')[0] - ret = common.NS(Util.number.long_to_bytes(signature)) - elif self.type() == 'DSA': - digest = sha1(data).digest() - randomBytes = randbytes.secureRandom(19) - sig = self.keyObject.sign(digest, randomBytes) - # SSH insists that the DSS signature blob be two 160-bit integers - # concatenated together. The sig[0], [1] numbers from obj.sign - # are just numbers, and could be any length from 0 to 160 bits. - # Make sure they are padded out to 160 bits (20 bytes each) - ret = common.NS(Util.number.long_to_bytes(sig[0], 20) + - Util.number.long_to_bytes(sig[1], 20)) - return common.NS(self.sshType()) + ret - - def verify(self, signature, data): - """ - Returns true if the signature for data is valid for this Key. - - @type signature: C{str} - @type data: C{str} - @rtype: C{bool} - """ - if len(signature) == 40: - # DSA key with no padding - signatureType, signature = 'ssh-dss', common.NS(signature) - else: - signatureType, signature = common.getNS(signature) - if signatureType != self.sshType(): - return False - if self.type() == 'RSA': - numbers = common.getMP(signature) - digest = pkcs1Digest(data, self.keyObject.size() / 8) - elif self.type() == 'DSA': - signature = common.getNS(signature)[0] - numbers = [Util.number.bytes_to_long(n) for n in signature[:20], - signature[20:]] - digest = sha1(data).digest() - return self.keyObject.verify(digest, numbers) - - -def objectType(obj): - """ - Return the SSH key type corresponding to a - C{Crypto.PublicKey.pubkey.pubkey} object. - - @type obj: C{Crypto.PublicKey.pubkey.pubkey} - @rtype: C{str} - """ - keyDataMapping = { - ('n', 'e', 'd', 'p', 'q'): 'ssh-rsa', - ('n', 'e', 'd', 'p', 'q', 'u'): 'ssh-rsa', - ('y', 'g', 'p', 'q', 'x'): 'ssh-dss' - } - try: - return keyDataMapping[tuple(obj.keydata)] - except (KeyError, AttributeError): - raise BadKeyError("invalid key object", obj) - - -def pkcs1Pad(data, messageLength): - """ - Pad out data to messageLength according to the PKCS#1 standard. - @type data: C{str} - @type messageLength: C{int} - """ - lenPad = messageLength - 2 - len(data) - return '\x01' + ('\xff' * lenPad) + '\x00' + data - - -def pkcs1Digest(data, messageLength): - """ - Create a message digest using the SHA1 hash algorithm according to the - PKCS#1 standard. - @type data: C{str} - @type messageLength: C{str} - """ - digest = sha1(data).digest() - return pkcs1Pad(ID_SHA1 + digest, messageLength) - - -def lenSig(obj): - """ - Return the length of the signature in bytes for a key object. - - @type obj: C{Crypto.PublicKey.pubkey.pubkey} - @rtype: C{long} - """ - return obj.size() / 8 - - -ID_SHA1 = '\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14' diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/service.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/service.py deleted file mode 100755 index b5477c4f..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/service.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -The parent class for all the SSH services. Currently implemented services -are ssh-userauth and ssh-connection. - -Maintainer: Paul Swartz -""" - - -from twisted.python import log - -class SSHService(log.Logger): - name = None # this is the ssh name for the service - protocolMessages = {} # these map #'s -> protocol names - transport = None # gets set later - - def serviceStarted(self): - """ - called when the service is active on the transport. - """ - - def serviceStopped(self): - """ - called when the service is stopped, either by the connection ending - or by another service being started - """ - - def logPrefix(self): - return "SSHService %s on %s" % (self.name, - self.transport.transport.logPrefix()) - - def packetReceived(self, messageNum, packet): - """ - called when we receive a packet on the transport - """ - #print self.protocolMessages - if messageNum in self.protocolMessages: - messageType = self.protocolMessages[messageNum] - f = getattr(self,'ssh_%s' % messageType[4:], - None) - if f is not None: - return f(packet) - log.msg("couldn't handle %r" % messageNum) - log.msg(repr(packet)) - self.transport.sendUnimplemented() - diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/session.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/session.py deleted file mode 100755 index e9eca3eb..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/session.py +++ /dev/null @@ -1,348 +0,0 @@ -# -*- test-case-name: twisted.conch.test.test_session -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -This module contains the implementation of SSHSession, which (by default) -allows access to a shell and a python interpreter over SSH. - -Maintainer: Paul Swartz -""" - -import struct -import signal -import sys -import os -from zope.interface import implements - -from twisted.internet import interfaces, protocol -from twisted.python import log -from twisted.conch.interfaces import ISession -from twisted.conch.ssh import common, channel - -class SSHSession(channel.SSHChannel): - - name = 'session' - def __init__(self, *args, **kw): - channel.SSHChannel.__init__(self, *args, **kw) - self.buf = '' - self.client = None - self.session = None - - def request_subsystem(self, data): - subsystem, ignored= common.getNS(data) - log.msg('asking for subsystem "%s"' % subsystem) - client = self.avatar.lookupSubsystem(subsystem, data) - if client: - pp = SSHSessionProcessProtocol(self) - proto = wrapProcessProtocol(pp) - client.makeConnection(proto) - pp.makeConnection(wrapProtocol(client)) - self.client = pp - return 1 - else: - log.msg('failed to get subsystem') - return 0 - - def request_shell(self, data): - log.msg('getting shell') - if not self.session: - self.session = ISession(self.avatar) - try: - pp = SSHSessionProcessProtocol(self) - self.session.openShell(pp) - except: - log.deferr() - return 0 - else: - self.client = pp - return 1 - - def request_exec(self, data): - if not self.session: - self.session = ISession(self.avatar) - f,data = common.getNS(data) - log.msg('executing command "%s"' % f) - try: - pp = SSHSessionProcessProtocol(self) - self.session.execCommand(pp, f) - except: - log.deferr() - return 0 - else: - self.client = pp - return 1 - - def request_pty_req(self, data): - if not self.session: - self.session = ISession(self.avatar) - term, windowSize, modes = parseRequest_pty_req(data) - log.msg('pty request: %s %s' % (term, windowSize)) - try: - self.session.getPty(term, windowSize, modes) - except: - log.err() - return 0 - else: - return 1 - - def request_window_change(self, data): - if not self.session: - self.session = ISession(self.avatar) - winSize = parseRequest_window_change(data) - try: - self.session.windowChanged(winSize) - except: - log.msg('error changing window size') - log.err() - return 0 - else: - return 1 - - def dataReceived(self, data): - if not self.client: - #self.conn.sendClose(self) - self.buf += data - return - self.client.transport.write(data) - - def extReceived(self, dataType, data): - if dataType == connection.EXTENDED_DATA_STDERR: - if self.client and hasattr(self.client.transport, 'writeErr'): - self.client.transport.writeErr(data) - else: - log.msg('weird extended data: %s'%dataType) - - def eofReceived(self): - if self.session: - self.session.eofReceived() - elif self.client: - self.conn.sendClose(self) - - def closed(self): - if self.session: - self.session.closed() - elif self.client: - self.client.transport.loseConnection() - - #def closeReceived(self): - # self.loseConnection() # don't know what to do with this - - def loseConnection(self): - if self.client: - self.client.transport.loseConnection() - channel.SSHChannel.loseConnection(self) - -class _ProtocolWrapper(protocol.ProcessProtocol): - """ - This class wraps a L{Protocol} instance in a L{ProcessProtocol} instance. - """ - def __init__(self, proto): - self.proto = proto - - def connectionMade(self): self.proto.connectionMade() - - def outReceived(self, data): self.proto.dataReceived(data) - - def processEnded(self, reason): self.proto.connectionLost(reason) - -class _DummyTransport: - - def __init__(self, proto): - self.proto = proto - - def dataReceived(self, data): - self.proto.transport.write(data) - - def write(self, data): - self.proto.dataReceived(data) - - def writeSequence(self, seq): - self.write(''.join(seq)) - - def loseConnection(self): - self.proto.connectionLost(protocol.connectionDone) - -def wrapProcessProtocol(inst): - if isinstance(inst, protocol.Protocol): - return _ProtocolWrapper(inst) - else: - return inst - -def wrapProtocol(proto): - return _DummyTransport(proto) - - - -# SUPPORTED_SIGNALS is a list of signals that every session channel is supposed -# to accept. See RFC 4254 -SUPPORTED_SIGNALS = ["ABRT", "ALRM", "FPE", "HUP", "ILL", "INT", "KILL", - "PIPE", "QUIT", "SEGV", "TERM", "USR1", "USR2"] - - - -class SSHSessionProcessProtocol(protocol.ProcessProtocol): - """I am both an L{IProcessProtocol} and an L{ITransport}. - - I am a transport to the remote endpoint and a process protocol to the - local subsystem. - """ - - implements(interfaces.ITransport) - - # once initialized, a dictionary mapping signal values to strings - # that follow RFC 4254. - _signalValuesToNames = None - - def __init__(self, session): - self.session = session - self.lostOutOrErrFlag = False - - def connectionMade(self): - if self.session.buf: - self.transport.write(self.session.buf) - self.session.buf = None - - def outReceived(self, data): - self.session.write(data) - - def errReceived(self, err): - self.session.writeExtended(connection.EXTENDED_DATA_STDERR, err) - - def outConnectionLost(self): - """ - EOF should only be sent when both STDOUT and STDERR have been closed. - """ - if self.lostOutOrErrFlag: - self.session.conn.sendEOF(self.session) - else: - self.lostOutOrErrFlag = True - - def errConnectionLost(self): - """ - See outConnectionLost(). - """ - self.outConnectionLost() - - def connectionLost(self, reason = None): - self.session.loseConnection() - - - def _getSignalName(self, signum): - """ - Get a signal name given a signal number. - """ - if self._signalValuesToNames is None: - self._signalValuesToNames = {} - # make sure that the POSIX ones are the defaults - for signame in SUPPORTED_SIGNALS: - signame = 'SIG' + signame - sigvalue = getattr(signal, signame, None) - if sigvalue is not None: - self._signalValuesToNames[sigvalue] = signame - for k, v in signal.__dict__.items(): - # Check for platform specific signals, ignoring Python specific - # SIG_DFL and SIG_IGN - if k.startswith('SIG') and not k.startswith('SIG_'): - if v not in self._signalValuesToNames: - self._signalValuesToNames[v] = k + '@' + sys.platform - return self._signalValuesToNames[signum] - - - def processEnded(self, reason=None): - """ - When we are told the process ended, try to notify the other side about - how the process ended using the exit-signal or exit-status requests. - Also, close the channel. - """ - if reason is not None: - err = reason.value - if err.signal is not None: - signame = self._getSignalName(err.signal) - if (getattr(os, 'WCOREDUMP', None) is not None and - os.WCOREDUMP(err.status)): - log.msg('exitSignal: %s (core dumped)' % (signame,)) - coreDumped = 1 - else: - log.msg('exitSignal: %s' % (signame,)) - coreDumped = 0 - self.session.conn.sendRequest(self.session, 'exit-signal', - common.NS(signame[3:]) + chr(coreDumped) + - common.NS('') + common.NS('')) - elif err.exitCode is not None: - log.msg('exitCode: %r' % (err.exitCode,)) - self.session.conn.sendRequest(self.session, 'exit-status', - struct.pack('>L', err.exitCode)) - self.session.loseConnection() - - - def getHost(self): - """ - Return the host from my session's transport. - """ - return self.session.conn.transport.getHost() - - - def getPeer(self): - """ - Return the peer from my session's transport. - """ - return self.session.conn.transport.getPeer() - - - def write(self, data): - self.session.write(data) - - - def writeSequence(self, seq): - self.session.write(''.join(seq)) - - - def loseConnection(self): - self.session.loseConnection() - - - -class SSHSessionClient(protocol.Protocol): - - def dataReceived(self, data): - if self.transport: - self.transport.write(data) - -# methods factored out to make live easier on server writers -def parseRequest_pty_req(data): - """Parse the data from a pty-req request into usable data. - - @returns: a tuple of (terminal type, (rows, cols, xpixel, ypixel), modes) - """ - term, rest = common.getNS(data) - cols, rows, xpixel, ypixel = struct.unpack('>4L', rest[: 16]) - modes, ignored= common.getNS(rest[16:]) - winSize = (rows, cols, xpixel, ypixel) - modes = [(ord(modes[i]), struct.unpack('>L', modes[i+1: i+5])[0]) for i in range(0, len(modes)-1, 5)] - return term, winSize, modes - -def packRequest_pty_req(term, (rows, cols, xpixel, ypixel), modes): - """Pack a pty-req request so that it is suitable for sending. - - NOTE: modes must be packed before being sent here. - """ - termPacked = common.NS(term) - winSizePacked = struct.pack('>4L', cols, rows, xpixel, ypixel) - modesPacked = common.NS(modes) # depend on the client packing modes - return termPacked + winSizePacked + modesPacked - -def parseRequest_window_change(data): - """Parse the data from a window-change request into usuable data. - - @returns: a tuple of (rows, cols, xpixel, ypixel) - """ - cols, rows, xpixel, ypixel = struct.unpack('>4L', data) - return rows, cols, xpixel, ypixel - -def packRequest_window_change((rows, cols, xpixel, ypixel)): - """Pack a window-change request so that it is suitable for sending. - """ - return struct.pack('>4L', cols, rows, xpixel, ypixel) - -import connection diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/sexpy.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/sexpy.py deleted file mode 100755 index 60c43289..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/sexpy.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -# - -def parse(s): - s = s.strip() - expr = [] - while s: - if s[0] == '(': - newSexp = [] - if expr: - expr[-1].append(newSexp) - expr.append(newSexp) - s = s[1:] - continue - if s[0] == ')': - aList = expr.pop() - s=s[1:] - if not expr: - assert not s - return aList - continue - i = 0 - while s[i].isdigit(): i+=1 - assert i - length = int(s[:i]) - data = s[i+1:i+1+length] - expr[-1].append(data) - s=s[i+1+length:] - assert 0, "this should not happen" - -def pack(sexp): - s = "" - for o in sexp: - if type(o) in (type(()), type([])): - s+='(' - s+=pack(o) - s+=')' - else: - s+='%i:%s' % (len(o), o) - return s diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/transport.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/transport.py deleted file mode 100755 index 9e0c753f..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/transport.py +++ /dev/null @@ -1,1617 +0,0 @@ -# -*- test-case-name: twisted.conch.test.test_transport -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -The lowest level SSH protocol. This handles the key negotiation, the -encryption and the compression. The transport layer is described in -RFC 4253. - -Maintainer: Paul Swartz -""" - -# base library imports -import struct -import zlib -import array - -# external library imports -from Crypto import Util -from Crypto.Cipher import XOR - -# twisted imports -from twisted.internet import protocol, defer - -from twisted.conch import error -from twisted.python import log, randbytes -from twisted.python.hashlib import md5, sha1 - - -# sibling imports -from twisted.conch.ssh import address, keys -from twisted.conch.ssh.common import NS, getNS, MP, getMP, _MPpow, ffs - - -def _getRandomNumber(random, bits): - """ - Generate a random number in the range [0, 2 ** bits). - - @param bits: The number of bits in the result. - @type bits: C{int} - - @rtype: C{int} or C{long} - @return: The newly generated random number. - - @raise ValueError: if C{bits} is not a multiple of 8. - """ - if bits % 8: - raise ValueError("bits (%d) must be a multiple of 8" % (bits,)) - bytes = random(bits / 8) - result = Util.number.bytes_to_long(bytes) - return result - - - -def _generateX(random, bits): - """ - Generate a new value for the private key x. - - From RFC 2631, section 2.2:: - - X9.42 requires that the private key x be in the interval - [2, (q - 2)]. x should be randomly generated in this interval. - """ - while True: - x = _getRandomNumber(random, bits) - if 2 <= x <= (2 ** bits) - 2: - return x - -class SSHTransportBase(protocol.Protocol): - """ - Protocol supporting basic SSH functionality: sending/receiving packets - and message dispatch. To connect to or run a server, you must use - SSHClientTransport or SSHServerTransport. - - @ivar protocolVersion: A string representing the version of the SSH - protocol we support. Currently defaults to '2.0'. - - @ivar version: A string representing the version of the server or client. - Currently defaults to 'Twisted'. - - @ivar comment: An optional string giving more information about the - server or client. - - @ivar supportedCiphers: A list of strings representing the encryption - algorithms supported, in order from most-preferred to least. - - @ivar supportedMACs: A list of strings representing the message - authentication codes (hashes) supported, in order from most-preferred - to least. Both this and supportedCiphers can include 'none' to use - no encryption or authentication, but that must be done manually, - - @ivar supportedKeyExchanges: A list of strings representing the - key exchanges supported, in order from most-preferred to least. - - @ivar supportedPublicKeys: A list of strings representing the - public key types supported, in order from most-preferred to least. - - @ivar supportedCompressions: A list of strings representing compression - types supported, from most-preferred to least. - - @ivar supportedLanguages: A list of strings representing languages - supported, from most-preferred to least. - - @ivar supportedVersions: A container of strings representing supported ssh - protocol version numbers. - - @ivar isClient: A boolean indicating whether this is a client or server. - - @ivar gotVersion: A boolean indicating whether we have receieved the - version string from the other side. - - @ivar buf: Data we've received but hasn't been parsed into a packet. - - @ivar outgoingPacketSequence: the sequence number of the next packet we - will send. - - @ivar incomingPacketSequence: the sequence number of the next packet we - are expecting from the other side. - - @ivar outgoingCompression: an object supporting the .compress(str) and - .flush() methods, or None if there is no outgoing compression. Used to - compress outgoing data. - - @ivar outgoingCompressionType: A string representing the outgoing - compression type. - - @ivar incomingCompression: an object supporting the .decompress(str) - method, or None if there is no incoming compression. Used to - decompress incoming data. - - @ivar incomingCompressionType: A string representing the incoming - compression type. - - @ivar ourVersionString: the version string that we sent to the other side. - Used in the key exchange. - - @ivar otherVersionString: the version string sent by the other side. Used - in the key exchange. - - @ivar ourKexInitPayload: the MSG_KEXINIT payload we sent. Used in the key - exchange. - - @ivar otherKexInitPayload: the MSG_KEXINIT payload we received. Used in - the key exchange - - @ivar sessionID: a string that is unique to this SSH session. Created as - part of the key exchange, sessionID is used to generate the various - encryption and authentication keys. - - @ivar service: an SSHService instance, or None. If it's set to an object, - it's the currently running service. - - @ivar kexAlg: the agreed-upon key exchange algorithm. - - @ivar keyAlg: the agreed-upon public key type for the key exchange. - - @ivar currentEncryptions: an SSHCiphers instance. It represents the - current encryption and authentication options for the transport. - - @ivar nextEncryptions: an SSHCiphers instance. Held here until the - MSG_NEWKEYS messages are exchanged, when nextEncryptions is - transitioned to currentEncryptions. - - @ivar first: the first bytes of the next packet. In order to avoid - decrypting data twice, the first bytes are decrypted and stored until - the whole packet is available. - - @ivar _keyExchangeState: The current protocol state with respect to key - exchange. This is either C{_KEY_EXCHANGE_NONE} if no key exchange is - in progress (and returns to this value after any key exchange - completqes), C{_KEY_EXCHANGE_REQUESTED} if this side of the connection - initiated a key exchange, and C{_KEY_EXCHANGE_PROGRESSING} if the other - side of the connection initiated a key exchange. C{_KEY_EXCHANGE_NONE} - is the initial value (however SSH connections begin with key exchange, - so it will quickly change to another state). - - @ivar _blockedByKeyExchange: Whenever C{_keyExchangeState} is not - C{_KEY_EXCHANGE_NONE}, this is a C{list} of pending messages which were - passed to L{sendPacket} but could not be sent because it is not legal - to send them while a key exchange is in progress. When the key - exchange completes, another attempt is made to send these messages. - """ - - - protocolVersion = '2.0' - version = 'Twisted' - comment = '' - ourVersionString = ('SSH-' + protocolVersion + '-' + version + ' ' - + comment).strip() - supportedCiphers = ['aes256-ctr', 'aes256-cbc', 'aes192-ctr', 'aes192-cbc', - 'aes128-ctr', 'aes128-cbc', 'cast128-ctr', - 'cast128-cbc', 'blowfish-ctr', 'blowfish-cbc', - '3des-ctr', '3des-cbc'] # ,'none'] - supportedMACs = ['hmac-sha1', 'hmac-md5'] # , 'none'] - # both of the above support 'none', but for security are disabled by - # default. to enable them, subclass this class and add it, or do: - # SSHTransportBase.supportedCiphers.append('none') - supportedKeyExchanges = ['diffie-hellman-group-exchange-sha1', - 'diffie-hellman-group1-sha1'] - supportedPublicKeys = ['ssh-rsa', 'ssh-dss'] - supportedCompressions = ['none', 'zlib'] - supportedLanguages = () - supportedVersions = ('1.99', '2.0') - isClient = False - gotVersion = False - buf = '' - outgoingPacketSequence = 0 - incomingPacketSequence = 0 - outgoingCompression = None - incomingCompression = None - sessionID = None - service = None - - # There is no key exchange activity in progress. - _KEY_EXCHANGE_NONE = '_KEY_EXCHANGE_NONE' - - # Key exchange is in progress and we started it. - _KEY_EXCHANGE_REQUESTED = '_KEY_EXCHANGE_REQUESTED' - - # Key exchange is in progress and both sides have sent KEXINIT messages. - _KEY_EXCHANGE_PROGRESSING = '_KEY_EXCHANGE_PROGRESSING' - - # There is a fourth conceptual state not represented here: KEXINIT received - # but not sent. Since we always send a KEXINIT as soon as we get it, we - # can't ever be in that state. - - # The current key exchange state. - _keyExchangeState = _KEY_EXCHANGE_NONE - _blockedByKeyExchange = None - - def connectionLost(self, reason): - if self.service: - self.service.serviceStopped() - if hasattr(self, 'avatar'): - self.logoutFunction() - log.msg('connection lost') - - - def connectionMade(self): - """ - Called when the connection is made to the other side. We sent our - version and the MSG_KEXINIT packet. - """ - self.transport.write('%s\r\n' % (self.ourVersionString,)) - self.currentEncryptions = SSHCiphers('none', 'none', 'none', 'none') - self.currentEncryptions.setKeys('', '', '', '', '', '') - self.sendKexInit() - - - def sendKexInit(self): - """ - Send a I{KEXINIT} message to initiate key exchange or to respond to a - key exchange initiated by the peer. - - @raise RuntimeError: If a key exchange has already been started and it - is not appropriate to send a I{KEXINIT} message at this time. - - @return: C{None} - """ - if self._keyExchangeState != self._KEY_EXCHANGE_NONE: - raise RuntimeError( - "Cannot send KEXINIT while key exchange state is %r" % ( - self._keyExchangeState,)) - - self.ourKexInitPayload = (chr(MSG_KEXINIT) + - randbytes.secureRandom(16) + - NS(','.join(self.supportedKeyExchanges)) + - NS(','.join(self.supportedPublicKeys)) + - NS(','.join(self.supportedCiphers)) + - NS(','.join(self.supportedCiphers)) + - NS(','.join(self.supportedMACs)) + - NS(','.join(self.supportedMACs)) + - NS(','.join(self.supportedCompressions)) + - NS(','.join(self.supportedCompressions)) + - NS(','.join(self.supportedLanguages)) + - NS(','.join(self.supportedLanguages)) + - '\000' + '\000\000\000\000') - self.sendPacket(MSG_KEXINIT, self.ourKexInitPayload[1:]) - self._keyExchangeState = self._KEY_EXCHANGE_REQUESTED - self._blockedByKeyExchange = [] - - - def _allowedKeyExchangeMessageType(self, messageType): - """ - Determine if the given message type may be sent while key exchange is - in progress. - - @param messageType: The type of message - @type messageType: C{int} - - @return: C{True} if the given type of message may be sent while key - exchange is in progress, C{False} if it may not. - @rtype: C{bool} - - @see: U{http://tools.ietf.org/html/rfc4253#section-7.1} - """ - # Written somewhat peculularly to reflect the way the specification - # defines the allowed message types. - if 1 <= messageType <= 19: - return messageType not in (MSG_SERVICE_REQUEST, MSG_SERVICE_ACCEPT) - if 20 <= messageType <= 29: - return messageType not in (MSG_KEXINIT,) - return 30 <= messageType <= 49 - - - def sendPacket(self, messageType, payload): - """ - Sends a packet. If it's been set up, compress the data, encrypt it, - and authenticate it before sending. If key exchange is in progress and - the message is not part of key exchange, queue it to be sent later. - - @param messageType: The type of the packet; generally one of the - MSG_* values. - @type messageType: C{int} - @param payload: The payload for the message. - @type payload: C{str} - """ - if self._keyExchangeState != self._KEY_EXCHANGE_NONE: - if not self._allowedKeyExchangeMessageType(messageType): - self._blockedByKeyExchange.append((messageType, payload)) - return - - payload = chr(messageType) + payload - if self.outgoingCompression: - payload = (self.outgoingCompression.compress(payload) - + self.outgoingCompression.flush(2)) - bs = self.currentEncryptions.encBlockSize - # 4 for the packet length and 1 for the padding length - totalSize = 5 + len(payload) - lenPad = bs - (totalSize % bs) - if lenPad < 4: - lenPad = lenPad + bs - packet = (struct.pack('!LB', - totalSize + lenPad - 4, lenPad) + - payload + randbytes.secureRandom(lenPad)) - encPacket = ( - self.currentEncryptions.encrypt(packet) + - self.currentEncryptions.makeMAC( - self.outgoingPacketSequence, packet)) - self.transport.write(encPacket) - self.outgoingPacketSequence += 1 - - - def getPacket(self): - """ - Try to return a decrypted, authenticated, and decompressed packet - out of the buffer. If there is not enough data, return None. - - @rtype: C{str}/C{None} - """ - bs = self.currentEncryptions.decBlockSize - ms = self.currentEncryptions.verifyDigestSize - if len(self.buf) < bs: return # not enough data - if not hasattr(self, 'first'): - first = self.currentEncryptions.decrypt(self.buf[:bs]) - else: - first = self.first - del self.first - packetLen, paddingLen = struct.unpack('!LB', first[:5]) - if packetLen > 1048576: # 1024 ** 2 - self.sendDisconnect(DISCONNECT_PROTOCOL_ERROR, - 'bad packet length %s' % packetLen) - return - if len(self.buf) < packetLen + 4 + ms: - self.first = first - return # not enough packet - if(packetLen + 4) % bs != 0: - self.sendDisconnect( - DISCONNECT_PROTOCOL_ERROR, - 'bad packet mod (%i%%%i == %i)' % (packetLen + 4, bs, - (packetLen + 4) % bs)) - return - encData, self.buf = self.buf[:4 + packetLen], self.buf[4 + packetLen:] - packet = first + self.currentEncryptions.decrypt(encData[bs:]) - if len(packet) != 4 + packetLen: - self.sendDisconnect(DISCONNECT_PROTOCOL_ERROR, - 'bad decryption') - return - if ms: - macData, self.buf = self.buf[:ms], self.buf[ms:] - if not self.currentEncryptions.verify(self.incomingPacketSequence, - packet, macData): - self.sendDisconnect(DISCONNECT_MAC_ERROR, 'bad MAC') - return - payload = packet[5:-paddingLen] - if self.incomingCompression: - try: - payload = self.incomingCompression.decompress(payload) - except: # bare except, because who knows what kind of errors - # decompression can raise - log.err() - self.sendDisconnect(DISCONNECT_COMPRESSION_ERROR, - 'compression error') - return - self.incomingPacketSequence += 1 - return payload - - - def _unsupportedVersionReceived(self, remoteVersion): - """ - Called when an unsupported version of the ssh protocol is received from - the remote endpoint. - - @param remoteVersion: remote ssh protocol version which is unsupported - by us. - @type remoteVersion: C{str} - """ - self.sendDisconnect(DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED, - 'bad version ' + remoteVersion) - - - def dataReceived(self, data): - """ - First, check for the version string (SSH-2.0-*). After that has been - received, this method adds data to the buffer, and pulls out any - packets. - - @type data: C{str} - """ - self.buf = self.buf + data - if not self.gotVersion: - if self.buf.find('\n', self.buf.find('SSH-')) == -1: - return - lines = self.buf.split('\n') - for p in lines: - if p.startswith('SSH-'): - self.gotVersion = True - self.otherVersionString = p.strip() - remoteVersion = p.split('-')[1] - if remoteVersion not in self.supportedVersions: - self._unsupportedVersionReceived(remoteVersion) - return - i = lines.index(p) - self.buf = '\n'.join(lines[i + 1:]) - packet = self.getPacket() - while packet: - messageNum = ord(packet[0]) - self.dispatchMessage(messageNum, packet[1:]) - packet = self.getPacket() - - - def dispatchMessage(self, messageNum, payload): - """ - Send a received message to the appropriate method. - - @type messageNum: C{int} - @type payload: c{str} - """ - if messageNum < 50 and messageNum in messages: - messageType = messages[messageNum][4:] - f = getattr(self, 'ssh_%s' % messageType, None) - if f is not None: - f(payload) - else: - log.msg("couldn't handle %s" % messageType) - log.msg(repr(payload)) - self.sendUnimplemented() - elif self.service: - log.callWithLogger(self.service, self.service.packetReceived, - messageNum, payload) - else: - log.msg("couldn't handle %s" % messageNum) - log.msg(repr(payload)) - self.sendUnimplemented() - - def getPeer(self): - """ - Returns an L{SSHTransportAddress} corresponding to the other (peer) - side of this transport. - - @return: L{SSHTransportAddress} for the peer - @rtype: L{SSHTransportAddress} - @since: 12.1 - """ - return address.SSHTransportAddress(self.transport.getPeer()) - - def getHost(self): - """ - Returns an L{SSHTransportAddress} corresponding to the this side of - transport. - - @return: L{SSHTransportAddress} for the peer - @rtype: L{SSHTransportAddress} - @since: 12.1 - """ - return address.SSHTransportAddress(self.transport.getHost()) - - - # Client-initiated rekeying looks like this: - # - # C> MSG_KEXINIT - # S> MSG_KEXINIT - # C> MSG_KEX_DH_GEX_REQUEST or MSG_KEXDH_INIT - # S> MSG_KEX_DH_GEX_GROUP or MSG_KEXDH_REPLY - # C> MSG_KEX_DH_GEX_INIT or -- - # S> MSG_KEX_DH_GEX_REPLY or -- - # C> MSG_NEWKEYS - # S> MSG_NEWKEYS - # - # Server-initiated rekeying is the same, only the first two messages are - # switched. - - def ssh_KEXINIT(self, packet): - """ - Called when we receive a MSG_KEXINIT message. Payload:: - bytes[16] cookie - string keyExchangeAlgorithms - string keyAlgorithms - string incomingEncryptions - string outgoingEncryptions - string incomingAuthentications - string outgoingAuthentications - string incomingCompressions - string outgoingCompressions - string incomingLanguages - string outgoingLanguages - bool firstPacketFollows - unit32 0 (reserved) - - Starts setting up the key exchange, keys, encryptions, and - authentications. Extended by ssh_KEXINIT in SSHServerTransport and - SSHClientTransport. - """ - self.otherKexInitPayload = chr(MSG_KEXINIT) + packet - #cookie = packet[: 16] # taking this is useless - k = getNS(packet[16:], 10) - strings, rest = k[:-1], k[-1] - (kexAlgs, keyAlgs, encCS, encSC, macCS, macSC, compCS, compSC, langCS, - langSC) = [s.split(',') for s in strings] - # these are the server directions - outs = [encSC, macSC, compSC] - ins = [encCS, macSC, compCS] - if self.isClient: - outs, ins = ins, outs # switch directions - server = (self.supportedKeyExchanges, self.supportedPublicKeys, - self.supportedCiphers, self.supportedCiphers, - self.supportedMACs, self.supportedMACs, - self.supportedCompressions, self.supportedCompressions) - client = (kexAlgs, keyAlgs, outs[0], ins[0], outs[1], ins[1], - outs[2], ins[2]) - if self.isClient: - server, client = client, server - self.kexAlg = ffs(client[0], server[0]) - self.keyAlg = ffs(client[1], server[1]) - self.nextEncryptions = SSHCiphers( - ffs(client[2], server[2]), - ffs(client[3], server[3]), - ffs(client[4], server[4]), - ffs(client[5], server[5])) - self.outgoingCompressionType = ffs(client[6], server[6]) - self.incomingCompressionType = ffs(client[7], server[7]) - if None in (self.kexAlg, self.keyAlg, self.outgoingCompressionType, - self.incomingCompressionType): - self.sendDisconnect(DISCONNECT_KEY_EXCHANGE_FAILED, - "couldn't match all kex parts") - return - if None in self.nextEncryptions.__dict__.values(): - self.sendDisconnect(DISCONNECT_KEY_EXCHANGE_FAILED, - "couldn't match all kex parts") - return - log.msg('kex alg, key alg: %s %s' % (self.kexAlg, self.keyAlg)) - log.msg('outgoing: %s %s %s' % (self.nextEncryptions.outCipType, - self.nextEncryptions.outMACType, - self.outgoingCompressionType)) - log.msg('incoming: %s %s %s' % (self.nextEncryptions.inCipType, - self.nextEncryptions.inMACType, - self.incomingCompressionType)) - - if self._keyExchangeState == self._KEY_EXCHANGE_REQUESTED: - self._keyExchangeState = self._KEY_EXCHANGE_PROGRESSING - else: - self.sendKexInit() - - return kexAlgs, keyAlgs, rest # for SSHServerTransport to use - - - def ssh_DISCONNECT(self, packet): - """ - Called when we receive a MSG_DISCONNECT message. Payload:: - long code - string description - - This means that the other side has disconnected. Pass the message up - and disconnect ourselves. - """ - reasonCode = struct.unpack('>L', packet[: 4])[0] - description, foo = getNS(packet[4:]) - self.receiveError(reasonCode, description) - self.transport.loseConnection() - - - def ssh_IGNORE(self, packet): - """ - Called when we receieve a MSG_IGNORE message. No payload. - This means nothing; we simply return. - """ - - - def ssh_UNIMPLEMENTED(self, packet): - """ - Called when we receieve a MSG_UNIMPLEMENTED message. Payload:: - long packet - - This means that the other side did not implement one of our packets. - """ - seqnum, = struct.unpack('>L', packet) - self.receiveUnimplemented(seqnum) - - - def ssh_DEBUG(self, packet): - """ - Called when we receieve a MSG_DEBUG message. Payload:: - bool alwaysDisplay - string message - string language - - This means the other side has passed along some debugging info. - """ - alwaysDisplay = bool(packet[0]) - message, lang, foo = getNS(packet[1:], 2) - self.receiveDebug(alwaysDisplay, message, lang) - - - def setService(self, service): - """ - Set our service to service and start it running. If we were - running a service previously, stop it first. - - @type service: C{SSHService} - """ - log.msg('starting service %s' % service.name) - if self.service: - self.service.serviceStopped() - self.service = service - service.transport = self - self.service.serviceStarted() - - - def sendDebug(self, message, alwaysDisplay=False, language=''): - """ - Send a debug message to the other side. - - @param message: the message to send. - @type message: C{str} - @param alwaysDisplay: if True, tell the other side to always - display this message. - @type alwaysDisplay: C{bool} - @param language: optionally, the language the message is in. - @type language: C{str} - """ - self.sendPacket(MSG_DEBUG, chr(alwaysDisplay) + NS(message) + - NS(language)) - - - def sendIgnore(self, message): - """ - Send a message that will be ignored by the other side. This is - useful to fool attacks based on guessing packet sizes in the - encrypted stream. - - @param message: data to send with the message - @type message: C{str} - """ - self.sendPacket(MSG_IGNORE, NS(message)) - - - def sendUnimplemented(self): - """ - Send a message to the other side that the last packet was not - understood. - """ - seqnum = self.incomingPacketSequence - self.sendPacket(MSG_UNIMPLEMENTED, struct.pack('!L', seqnum)) - - - def sendDisconnect(self, reason, desc): - """ - Send a disconnect message to the other side and then disconnect. - - @param reason: the reason for the disconnect. Should be one of the - DISCONNECT_* values. - @type reason: C{int} - @param desc: a descrption of the reason for the disconnection. - @type desc: C{str} - """ - self.sendPacket( - MSG_DISCONNECT, struct.pack('>L', reason) + NS(desc) + NS('')) - log.msg('Disconnecting with error, code %s\nreason: %s' % (reason, - desc)) - self.transport.loseConnection() - - - def _getKey(self, c, sharedSecret, exchangeHash): - """ - Get one of the keys for authentication/encryption. - - @type c: C{str} - @type sharedSecret: C{str} - @type exchangeHash: C{str} - """ - k1 = sha1(sharedSecret + exchangeHash + c + self.sessionID) - k1 = k1.digest() - k2 = sha1(sharedSecret + exchangeHash + k1).digest() - return k1 + k2 - - - def _keySetup(self, sharedSecret, exchangeHash): - """ - Set up the keys for the connection and sends MSG_NEWKEYS when - finished, - - @param sharedSecret: a secret string agreed upon using a Diffie- - Hellman exchange, so it is only shared between - the server and the client. - @type sharedSecret: C{str} - @param exchangeHash: A hash of various data known by both sides. - @type exchangeHash: C{str} - """ - if not self.sessionID: - self.sessionID = exchangeHash - initIVCS = self._getKey('A', sharedSecret, exchangeHash) - initIVSC = self._getKey('B', sharedSecret, exchangeHash) - encKeyCS = self._getKey('C', sharedSecret, exchangeHash) - encKeySC = self._getKey('D', sharedSecret, exchangeHash) - integKeyCS = self._getKey('E', sharedSecret, exchangeHash) - integKeySC = self._getKey('F', sharedSecret, exchangeHash) - outs = [initIVSC, encKeySC, integKeySC] - ins = [initIVCS, encKeyCS, integKeyCS] - if self.isClient: # reverse for the client - log.msg('REVERSE') - outs, ins = ins, outs - self.nextEncryptions.setKeys(outs[0], outs[1], ins[0], ins[1], - outs[2], ins[2]) - self.sendPacket(MSG_NEWKEYS, '') - - - def _newKeys(self): - """ - Called back by a subclass once a I{MSG_NEWKEYS} message has been - received. This indicates key exchange has completed and new encryption - and compression parameters should be adopted. Any messages which were - queued during key exchange will also be flushed. - """ - log.msg('NEW KEYS') - self.currentEncryptions = self.nextEncryptions - if self.outgoingCompressionType == 'zlib': - self.outgoingCompression = zlib.compressobj(6) - if self.incomingCompressionType == 'zlib': - self.incomingCompression = zlib.decompressobj() - - self._keyExchangeState = self._KEY_EXCHANGE_NONE - messages = self._blockedByKeyExchange - self._blockedByKeyExchange = None - for (messageType, payload) in messages: - self.sendPacket(messageType, payload) - - - def isEncrypted(self, direction="out"): - """ - Return True if the connection is encrypted in the given direction. - Direction must be one of ["out", "in", "both"]. - """ - if direction == "out": - return self.currentEncryptions.outCipType != 'none' - elif direction == "in": - return self.currentEncryptions.inCipType != 'none' - elif direction == "both": - return self.isEncrypted("in") and self.isEncrypted("out") - else: - raise TypeError('direction must be "out", "in", or "both"') - - - def isVerified(self, direction="out"): - """ - Return True if the connecction is verified/authenticated in the - given direction. Direction must be one of ["out", "in", "both"]. - """ - if direction == "out": - return self.currentEncryptions.outMACType != 'none' - elif direction == "in": - return self.currentEncryptions.inMACType != 'none' - elif direction == "both": - return self.isVerified("in")and self.isVerified("out") - else: - raise TypeError('direction must be "out", "in", or "both"') - - - def loseConnection(self): - """ - Lose the connection to the other side, sending a - DISCONNECT_CONNECTION_LOST message. - """ - self.sendDisconnect(DISCONNECT_CONNECTION_LOST, - "user closed connection") - - - # client methods - def receiveError(self, reasonCode, description): - """ - Called when we receive a disconnect error message from the other - side. - - @param reasonCode: the reason for the disconnect, one of the - DISCONNECT_ values. - @type reasonCode: C{int} - @param description: a human-readable description of the - disconnection. - @type description: C{str} - """ - log.msg('Got remote error, code %s\nreason: %s' % (reasonCode, - description)) - - - def receiveUnimplemented(self, seqnum): - """ - Called when we receive an unimplemented packet message from the other - side. - - @param seqnum: the sequence number that was not understood. - @type seqnum: C{int} - """ - log.msg('other side unimplemented packet #%s' % seqnum) - - - def receiveDebug(self, alwaysDisplay, message, lang): - """ - Called when we receive a debug message from the other side. - - @param alwaysDisplay: if True, this message should always be - displayed. - @type alwaysDisplay: C{bool} - @param message: the debug message - @type message: C{str} - @param lang: optionally the language the message is in. - @type lang: C{str} - """ - if alwaysDisplay: - log.msg('Remote Debug Message: %s' % message) - - - -class SSHServerTransport(SSHTransportBase): - """ - SSHServerTransport implements the server side of the SSH protocol. - - @ivar isClient: since we are never the client, this is always False. - - @ivar ignoreNextPacket: if True, ignore the next key exchange packet. This - is set when the client sends a guessed key exchange packet but with - an incorrect guess. - - @ivar dhGexRequest: the KEX_DH_GEX_REQUEST(_OLD) that the client sent. - The key generation needs this to be stored. - - @ivar g: the Diffie-Hellman group generator. - - @ivar p: the Diffie-Hellman group prime. - """ - isClient = False - ignoreNextPacket = 0 - - - def ssh_KEXINIT(self, packet): - """ - Called when we receive a MSG_KEXINIT message. For a description - of the packet, see SSHTransportBase.ssh_KEXINIT(). Additionally, - this method checks if a guessed key exchange packet was sent. If - it was sent, and it guessed incorrectly, the next key exchange - packet MUST be ignored. - """ - retval = SSHTransportBase.ssh_KEXINIT(self, packet) - if not retval: # disconnected - return - else: - kexAlgs, keyAlgs, rest = retval - if ord(rest[0]): # first_kex_packet_follows - if (kexAlgs[0] != self.supportedKeyExchanges[0] or - keyAlgs[0] != self.supportedPublicKeys[0]): - self.ignoreNextPacket = True # guess was wrong - - - def _ssh_KEXDH_INIT(self, packet): - """ - Called to handle the beginning of a diffie-hellman-group1-sha1 key - exchange. - - Unlike other message types, this is not dispatched automatically. It - is called from C{ssh_KEX_DH_GEX_REQUEST_OLD} because an extra check is - required to determine if this is really a KEXDH_INIT message or if it - is a KEX_DH_GEX_REQUEST_OLD message. - - The KEXDH_INIT (for diffie-hellman-group1-sha1 exchanges) payload:: - - integer e (the client's Diffie-Hellman public key) - - We send the KEXDH_REPLY with our host key and signature. - """ - clientDHpublicKey, foo = getMP(packet) - y = _getRandomNumber(randbytes.secureRandom, 512) - serverDHpublicKey = _MPpow(DH_GENERATOR, y, DH_PRIME) - sharedSecret = _MPpow(clientDHpublicKey, y, DH_PRIME) - h = sha1() - h.update(NS(self.otherVersionString)) - h.update(NS(self.ourVersionString)) - h.update(NS(self.otherKexInitPayload)) - h.update(NS(self.ourKexInitPayload)) - h.update(NS(self.factory.publicKeys[self.keyAlg].blob())) - h.update(MP(clientDHpublicKey)) - h.update(serverDHpublicKey) - h.update(sharedSecret) - exchangeHash = h.digest() - self.sendPacket( - MSG_KEXDH_REPLY, - NS(self.factory.publicKeys[self.keyAlg].blob()) + - serverDHpublicKey + - NS(self.factory.privateKeys[self.keyAlg].sign(exchangeHash))) - self._keySetup(sharedSecret, exchangeHash) - - - def ssh_KEX_DH_GEX_REQUEST_OLD(self, packet): - """ - This represents two different key exchange methods that share the same - integer value. If the message is determined to be a KEXDH_INIT, - C{_ssh_KEXDH_INIT} is called to handle it. Otherwise, for - KEX_DH_GEX_REQUEST_OLD (for diffie-hellman-group-exchange-sha1) - payload:: - - integer ideal (ideal size for the Diffie-Hellman prime) - - We send the KEX_DH_GEX_GROUP message with the group that is - closest in size to ideal. - - If we were told to ignore the next key exchange packet by ssh_KEXINIT, - drop it on the floor and return. - """ - if self.ignoreNextPacket: - self.ignoreNextPacket = 0 - return - - # KEXDH_INIT and KEX_DH_GEX_REQUEST_OLD have the same value, so use - # another cue to decide what kind of message the peer sent us. - if self.kexAlg == 'diffie-hellman-group1-sha1': - return self._ssh_KEXDH_INIT(packet) - elif self.kexAlg == 'diffie-hellman-group-exchange-sha1': - self.dhGexRequest = packet - ideal = struct.unpack('>L', packet)[0] - self.g, self.p = self.factory.getDHPrime(ideal) - self.sendPacket(MSG_KEX_DH_GEX_GROUP, MP(self.p) + MP(self.g)) - else: - raise error.ConchError('bad kexalg: %s' % self.kexAlg) - - - def ssh_KEX_DH_GEX_REQUEST(self, packet): - """ - Called when we receive a MSG_KEX_DH_GEX_REQUEST message. Payload:: - integer minimum - integer ideal - integer maximum - - The client is asking for a Diffie-Hellman group between minimum and - maximum size, and close to ideal if possible. We reply with a - MSG_KEX_DH_GEX_GROUP message. - - If we were told to ignore the next key exchange packet by ssh_KEXINIT, - drop it on the floor and return. - """ - if self.ignoreNextPacket: - self.ignoreNextPacket = 0 - return - self.dhGexRequest = packet - min, ideal, max = struct.unpack('>3L', packet) - self.g, self.p = self.factory.getDHPrime(ideal) - self.sendPacket(MSG_KEX_DH_GEX_GROUP, MP(self.p) + MP(self.g)) - - - def ssh_KEX_DH_GEX_INIT(self, packet): - """ - Called when we get a MSG_KEX_DH_GEX_INIT message. Payload:: - integer e (client DH public key) - - We send the MSG_KEX_DH_GEX_REPLY message with our host key and - signature. - """ - clientDHpublicKey, foo = getMP(packet) - # TODO: we should also look at the value they send to us and reject - # insecure values of f (if g==2 and f has a single '1' bit while the - # rest are '0's, then they must have used a small y also). - - # TODO: This could be computed when self.p is set up - # or do as openssh does and scan f for a single '1' bit instead - - pSize = Util.number.size(self.p) - y = _getRandomNumber(randbytes.secureRandom, pSize) - - serverDHpublicKey = _MPpow(self.g, y, self.p) - sharedSecret = _MPpow(clientDHpublicKey, y, self.p) - h = sha1() - h.update(NS(self.otherVersionString)) - h.update(NS(self.ourVersionString)) - h.update(NS(self.otherKexInitPayload)) - h.update(NS(self.ourKexInitPayload)) - h.update(NS(self.factory.publicKeys[self.keyAlg].blob())) - h.update(self.dhGexRequest) - h.update(MP(self.p)) - h.update(MP(self.g)) - h.update(MP(clientDHpublicKey)) - h.update(serverDHpublicKey) - h.update(sharedSecret) - exchangeHash = h.digest() - self.sendPacket( - MSG_KEX_DH_GEX_REPLY, - NS(self.factory.publicKeys[self.keyAlg].blob()) + - serverDHpublicKey + - NS(self.factory.privateKeys[self.keyAlg].sign(exchangeHash))) - self._keySetup(sharedSecret, exchangeHash) - - - def ssh_NEWKEYS(self, packet): - """ - Called when we get a MSG_NEWKEYS message. No payload. - When we get this, the keys have been set on both sides, and we - start using them to encrypt and authenticate the connection. - """ - if packet != '': - self.sendDisconnect(DISCONNECT_PROTOCOL_ERROR, - "NEWKEYS takes no data") - return - self._newKeys() - - - def ssh_SERVICE_REQUEST(self, packet): - """ - Called when we get a MSG_SERVICE_REQUEST message. Payload:: - string serviceName - - The client has requested a service. If we can start the service, - start it; otherwise, disconnect with - DISCONNECT_SERVICE_NOT_AVAILABLE. - """ - service, rest = getNS(packet) - cls = self.factory.getService(self, service) - if not cls: - self.sendDisconnect(DISCONNECT_SERVICE_NOT_AVAILABLE, - "don't have service %s" % service) - return - else: - self.sendPacket(MSG_SERVICE_ACCEPT, NS(service)) - self.setService(cls()) - - - -class SSHClientTransport(SSHTransportBase): - """ - SSHClientTransport implements the client side of the SSH protocol. - - @ivar isClient: since we are always the client, this is always True. - - @ivar _gotNewKeys: if we receive a MSG_NEWKEYS message before we are - ready to transition to the new keys, this is set to True so we - can transition when the keys are ready locally. - - @ivar x: our Diffie-Hellman private key. - - @ivar e: our Diffie-Hellman public key. - - @ivar g: the Diffie-Hellman group generator. - - @ivar p: the Diffie-Hellman group prime - - @ivar instance: the SSHService object we are requesting. - """ - isClient = True - - def connectionMade(self): - """ - Called when the connection is started with the server. Just sets - up a private instance variable. - """ - SSHTransportBase.connectionMade(self) - self._gotNewKeys = 0 - - - def ssh_KEXINIT(self, packet): - """ - Called when we receive a MSG_KEXINIT message. For a description - of the packet, see SSHTransportBase.ssh_KEXINIT(). Additionally, - this method sends the first key exchange packet. If the agreed-upon - exchange is diffie-hellman-group1-sha1, generate a public key - and send it in a MSG_KEXDH_INIT message. If the exchange is - diffie-hellman-group-exchange-sha1, ask for a 2048 bit group with a - MSG_KEX_DH_GEX_REQUEST_OLD message. - """ - if SSHTransportBase.ssh_KEXINIT(self, packet) is None: - return # we disconnected - if self.kexAlg == 'diffie-hellman-group1-sha1': - self.x = _generateX(randbytes.secureRandom, 512) - self.e = _MPpow(DH_GENERATOR, self.x, DH_PRIME) - self.sendPacket(MSG_KEXDH_INIT, self.e) - elif self.kexAlg == 'diffie-hellman-group-exchange-sha1': - self.sendPacket(MSG_KEX_DH_GEX_REQUEST_OLD, '\x00\x00\x08\x00') - else: - raise error.ConchError("somehow, the kexAlg has been set " - "to something we don't support") - - - def _ssh_KEXDH_REPLY(self, packet): - """ - Called to handle a reply to a diffie-hellman-group1-sha1 key exchange - message (KEXDH_INIT). - - Like the handler for I{KEXDH_INIT}, this message type has an - overlapping value. This method is called from C{ssh_KEX_DH_GEX_GROUP} - if that method detects a diffie-hellman-group1-sha1 key exchange is in - progress. - - Payload:: - - string serverHostKey - integer f (server Diffie-Hellman public key) - string signature - - We verify the host key by calling verifyHostKey, then continue in - _continueKEXDH_REPLY. - """ - pubKey, packet = getNS(packet) - f, packet = getMP(packet) - signature, packet = getNS(packet) - fingerprint = ':'.join([ch.encode('hex') for ch in - md5(pubKey).digest()]) - d = self.verifyHostKey(pubKey, fingerprint) - d.addCallback(self._continueKEXDH_REPLY, pubKey, f, signature) - d.addErrback( - lambda unused: self.sendDisconnect( - DISCONNECT_HOST_KEY_NOT_VERIFIABLE, 'bad host key')) - return d - - - def ssh_KEX_DH_GEX_GROUP(self, packet): - """ - This handles two different message which share an integer value. - - If the key exchange is diffie-hellman-group-exchange-sha1, this is - MSG_KEX_DH_GEX_GROUP. Payload:: - string g (group generator) - string p (group prime) - - We generate a Diffie-Hellman public key and send it in a - MSG_KEX_DH_GEX_INIT message. - """ - if self.kexAlg == 'diffie-hellman-group1-sha1': - return self._ssh_KEXDH_REPLY(packet) - else: - self.p, rest = getMP(packet) - self.g, rest = getMP(rest) - self.x = _generateX(randbytes.secureRandom, 320) - self.e = _MPpow(self.g, self.x, self.p) - self.sendPacket(MSG_KEX_DH_GEX_INIT, self.e) - - - def _continueKEXDH_REPLY(self, ignored, pubKey, f, signature): - """ - The host key has been verified, so we generate the keys. - - @param pubKey: the public key blob for the server's public key. - @type pubKey: C{str} - @param f: the server's Diffie-Hellman public key. - @type f: C{long} - @param signature: the server's signature, verifying that it has the - correct private key. - @type signature: C{str} - """ - serverKey = keys.Key.fromString(pubKey) - sharedSecret = _MPpow(f, self.x, DH_PRIME) - h = sha1() - h.update(NS(self.ourVersionString)) - h.update(NS(self.otherVersionString)) - h.update(NS(self.ourKexInitPayload)) - h.update(NS(self.otherKexInitPayload)) - h.update(NS(pubKey)) - h.update(self.e) - h.update(MP(f)) - h.update(sharedSecret) - exchangeHash = h.digest() - if not serverKey.verify(signature, exchangeHash): - self.sendDisconnect(DISCONNECT_KEY_EXCHANGE_FAILED, - 'bad signature') - return - self._keySetup(sharedSecret, exchangeHash) - - - def ssh_KEX_DH_GEX_REPLY(self, packet): - """ - Called when we receieve a MSG_KEX_DH_GEX_REPLY message. Payload:: - string server host key - integer f (server DH public key) - - We verify the host key by calling verifyHostKey, then continue in - _continueGEX_REPLY. - """ - pubKey, packet = getNS(packet) - f, packet = getMP(packet) - signature, packet = getNS(packet) - fingerprint = ':'.join(map(lambda c: '%02x'%ord(c), - md5(pubKey).digest())) - d = self.verifyHostKey(pubKey, fingerprint) - d.addCallback(self._continueGEX_REPLY, pubKey, f, signature) - d.addErrback( - lambda unused: self.sendDisconnect( - DISCONNECT_HOST_KEY_NOT_VERIFIABLE, 'bad host key')) - return d - - - def _continueGEX_REPLY(self, ignored, pubKey, f, signature): - """ - The host key has been verified, so we generate the keys. - - @param pubKey: the public key blob for the server's public key. - @type pubKey: C{str} - @param f: the server's Diffie-Hellman public key. - @type f: C{long} - @param signature: the server's signature, verifying that it has the - correct private key. - @type signature: C{str} - """ - serverKey = keys.Key.fromString(pubKey) - sharedSecret = _MPpow(f, self.x, self.p) - h = sha1() - h.update(NS(self.ourVersionString)) - h.update(NS(self.otherVersionString)) - h.update(NS(self.ourKexInitPayload)) - h.update(NS(self.otherKexInitPayload)) - h.update(NS(pubKey)) - h.update('\x00\x00\x08\x00') - h.update(MP(self.p)) - h.update(MP(self.g)) - h.update(self.e) - h.update(MP(f)) - h.update(sharedSecret) - exchangeHash = h.digest() - if not serverKey.verify(signature, exchangeHash): - self.sendDisconnect(DISCONNECT_KEY_EXCHANGE_FAILED, - 'bad signature') - return - self._keySetup(sharedSecret, exchangeHash) - - - def _keySetup(self, sharedSecret, exchangeHash): - """ - See SSHTransportBase._keySetup(). - """ - SSHTransportBase._keySetup(self, sharedSecret, exchangeHash) - if self._gotNewKeys: - self.ssh_NEWKEYS('') - - - def ssh_NEWKEYS(self, packet): - """ - Called when we receieve a MSG_NEWKEYS message. No payload. - If we've finished setting up our own keys, start using them. - Otherwise, remeber that we've receieved this message. - """ - if packet != '': - self.sendDisconnect(DISCONNECT_PROTOCOL_ERROR, - "NEWKEYS takes no data") - return - if not self.nextEncryptions.encBlockSize: - self._gotNewKeys = 1 - return - self._newKeys() - self.connectionSecure() - - - def ssh_SERVICE_ACCEPT(self, packet): - """ - Called when we receieve a MSG_SERVICE_ACCEPT message. Payload:: - string service name - - Start the service we requested. - """ - if packet == '': - log.msg('got SERVICE_ACCEPT without payload') - else: - name = getNS(packet)[0] - if name != self.instance.name: - self.sendDisconnect( - DISCONNECT_PROTOCOL_ERROR, - "received accept for service we did not request") - self.setService(self.instance) - - - def requestService(self, instance): - """ - Request that a service be run over this transport. - - @type instance: subclass of L{twisted.conch.ssh.service.SSHService} - """ - self.sendPacket(MSG_SERVICE_REQUEST, NS(instance.name)) - self.instance = instance - - - # client methods - def verifyHostKey(self, hostKey, fingerprint): - """ - Returns a Deferred that gets a callback if it is a valid key, or - an errback if not. - - @type hostKey: C{str} - @type fingerprint: C{str} - @rtype: L{twisted.internet.defer.Deferred} - """ - # return if it's good - return defer.fail(NotImplementedError()) - - - def connectionSecure(self): - """ - Called when the encryption has been set up. Generally, - requestService() is called to run another service over the transport. - """ - raise NotImplementedError() - - - -class _DummyCipher: - """ - A cipher for the none encryption method. - - @ivar block_size: the block size of the encryption. In the case of the - none cipher, this is 8 bytes. - """ - block_size = 8 - - - def encrypt(self, x): - return x - - - decrypt = encrypt - - -class SSHCiphers: - """ - SSHCiphers represents all the encryption operations that need to occur - to encrypt and authenticate the SSH connection. - - @cvar cipherMap: A dictionary mapping SSH encryption names to 3-tuples of - (<Crypto.Cipher.* name>, <block size>, <counter mode>) - @cvar macMap: A dictionary mapping SSH MAC names to hash modules. - - @ivar outCipType: the string type of the outgoing cipher. - @ivar inCipType: the string type of the incoming cipher. - @ivar outMACType: the string type of the incoming MAC. - @ivar inMACType: the string type of the incoming MAC. - @ivar encBlockSize: the block size of the outgoing cipher. - @ivar decBlockSize: the block size of the incoming cipher. - @ivar verifyDigestSize: the size of the incoming MAC. - @ivar outMAC: a tuple of (<hash module>, <inner key>, <outer key>, - <digest size>) representing the outgoing MAC. - @ivar inMAc: see outMAC, but for the incoming MAC. - """ - - - cipherMap = { - '3des-cbc':('DES3', 24, 0), - 'blowfish-cbc':('Blowfish', 16,0 ), - 'aes256-cbc':('AES', 32, 0), - 'aes192-cbc':('AES', 24, 0), - 'aes128-cbc':('AES', 16, 0), - 'cast128-cbc':('CAST', 16, 0), - 'aes128-ctr':('AES', 16, 1), - 'aes192-ctr':('AES', 24, 1), - 'aes256-ctr':('AES', 32, 1), - '3des-ctr':('DES3', 24, 1), - 'blowfish-ctr':('Blowfish', 16, 1), - 'cast128-ctr':('CAST', 16, 1), - 'none':(None, 0, 0), - } - macMap = { - 'hmac-sha1': sha1, - 'hmac-md5': md5, - 'none': None - } - - - def __init__(self, outCip, inCip, outMac, inMac): - self.outCipType = outCip - self.inCipType = inCip - self.outMACType = outMac - self.inMACType = inMac - self.encBlockSize = 0 - self.decBlockSize = 0 - self.verifyDigestSize = 0 - self.outMAC = (None, '', '', 0) - self.inMAC = (None, '', '', 0) - - - def setKeys(self, outIV, outKey, inIV, inKey, outInteg, inInteg): - """ - Set up the ciphers and hashes using the given keys, - - @param outIV: the outgoing initialization vector - @param outKey: the outgoing encryption key - @param inIV: the incoming initialization vector - @param inKey: the incoming encryption key - @param outInteg: the outgoing integrity key - @param inInteg: the incoming integrity key. - """ - o = self._getCipher(self.outCipType, outIV, outKey) - self.encrypt = o.encrypt - self.encBlockSize = o.block_size - o = self._getCipher(self.inCipType, inIV, inKey) - self.decrypt = o.decrypt - self.decBlockSize = o.block_size - self.outMAC = self._getMAC(self.outMACType, outInteg) - self.inMAC = self._getMAC(self.inMACType, inInteg) - if self.inMAC: - self.verifyDigestSize = self.inMAC[3] - - - def _getCipher(self, cip, iv, key): - """ - Creates an initialized cipher object. - - @param cip: the name of the cipher: maps into Crypto.Cipher.* - @param iv: the initialzation vector - @param key: the encryption key - """ - modName, keySize, counterMode = self.cipherMap[cip] - if not modName: # no cipher - return _DummyCipher() - mod = __import__('Crypto.Cipher.%s'%modName, {}, {}, 'x') - if counterMode: - return mod.new(key[:keySize], mod.MODE_CTR, iv[:mod.block_size], - counter=_Counter(iv, mod.block_size)) - else: - return mod.new(key[:keySize], mod.MODE_CBC, iv[:mod.block_size]) - - - def _getMAC(self, mac, key): - """ - Gets a 4-tuple representing the message authentication code. - (<hash module>, <inner hash value>, <outer hash value>, - <digest size>) - - @param mac: a key mapping into macMap - @type mac: C{str} - @param key: the MAC key. - @type key: C{str} - """ - mod = self.macMap[mac] - if not mod: - return (None, '', '', 0) - ds = mod().digest_size - key = key[:ds] + '\x00' * (64 - ds) - i = XOR.new('\x36').encrypt(key) - o = XOR.new('\x5c').encrypt(key) - return mod, i, o, ds - - - def encrypt(self, blocks): - """ - Encrypt blocks. Overridden by the encrypt method of a - Crypto.Cipher.* object in setKeys(). - - @type blocks: C{str} - """ - raise NotImplementedError() - - - def decrypt(self, blocks): - """ - Decrypt blocks. See encrypt(). - - @type blocks: C{str} - """ - raise NotImplementedError() - - - def makeMAC(self, seqid, data): - """ - Create a message authentication code (MAC) for the given packet using - the outgoing MAC values. - - @param seqid: the sequence ID of the outgoing packet - @type seqid: C{int} - @param data: the data to create a MAC for - @type data: C{str} - @rtype: C{str} - """ - if not self.outMAC[0]: - return '' - data = struct.pack('>L', seqid) + data - mod, i, o, ds = self.outMAC - inner = mod(i + data) - outer = mod(o + inner.digest()) - return outer.digest() - - - def verify(self, seqid, data, mac): - """ - Verify an incoming MAC using the incoming MAC values. Return True - if the MAC is valid. - - @param seqid: the sequence ID of the incoming packet - @type seqid: C{int} - @param data: the packet data to verify - @type data: C{str} - @param mac: the MAC sent with the packet - @type mac: C{str} - @rtype: C{bool} - """ - if not self.inMAC[0]: - return mac == '' - data = struct.pack('>L', seqid) + data - mod, i, o, ds = self.inMAC - inner = mod(i + data) - outer = mod(o + inner.digest()) - return mac == outer.digest() - - - -class _Counter: - """ - Stateful counter which returns results packed in a byte string - """ - - - def __init__(self, initialVector, blockSize): - """ - @type initialVector: C{str} - @param initialVector: A byte string representing the initial counter - value. - @type blockSize: C{int} - @param blockSize: The length of the output buffer, as well as the - number of bytes at the beginning of C{initialVector} to consider. - """ - initialVector = initialVector[:blockSize] - self.count = getMP('\xff\xff\xff\xff' + initialVector)[0] - self.blockSize = blockSize - self.count = Util.number.long_to_bytes(self.count - 1) - self.count = '\x00' * (self.blockSize - len(self.count)) + self.count - self.count = array.array('c', self.count) - self.len = len(self.count) - 1 - - - def __call__(self): - """ - Increment the counter and return the new value. - """ - i = self.len - while i > -1: - self.count[i] = n = chr((ord(self.count[i]) + 1) % 256) - if n == '\x00': - i -= 1 - else: - return self.count.tostring() - - self.count = array.array('c', '\x00' * self.blockSize) - return self.count.tostring() - - - -# Diffie-Hellman primes from Oakley Group 2 [RFC 2409] -DH_PRIME = long('17976931348623159077083915679378745319786029604875601170644' -'442368419718021615851936894783379586492554150218056548598050364644054819923' -'910005079287700335581663922955313623907650873575991482257486257500742530207' -'744771258955095793777842444242661733472762929938766870920560605027081084290' -'7692932019128194467627007L') -DH_GENERATOR = 2L - - - -MSG_DISCONNECT = 1 -MSG_IGNORE = 2 -MSG_UNIMPLEMENTED = 3 -MSG_DEBUG = 4 -MSG_SERVICE_REQUEST = 5 -MSG_SERVICE_ACCEPT = 6 -MSG_KEXINIT = 20 -MSG_NEWKEYS = 21 -MSG_KEXDH_INIT = 30 -MSG_KEXDH_REPLY = 31 -MSG_KEX_DH_GEX_REQUEST_OLD = 30 -MSG_KEX_DH_GEX_REQUEST = 34 -MSG_KEX_DH_GEX_GROUP = 31 -MSG_KEX_DH_GEX_INIT = 32 -MSG_KEX_DH_GEX_REPLY = 33 - - - -DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT = 1 -DISCONNECT_PROTOCOL_ERROR = 2 -DISCONNECT_KEY_EXCHANGE_FAILED = 3 -DISCONNECT_RESERVED = 4 -DISCONNECT_MAC_ERROR = 5 -DISCONNECT_COMPRESSION_ERROR = 6 -DISCONNECT_SERVICE_NOT_AVAILABLE = 7 -DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED = 8 -DISCONNECT_HOST_KEY_NOT_VERIFIABLE = 9 -DISCONNECT_CONNECTION_LOST = 10 -DISCONNECT_BY_APPLICATION = 11 -DISCONNECT_TOO_MANY_CONNECTIONS = 12 -DISCONNECT_AUTH_CANCELLED_BY_USER = 13 -DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE = 14 -DISCONNECT_ILLEGAL_USER_NAME = 15 - - - -messages = {} -for name, value in globals().items(): - # Avoid legacy messages which overlap with never ones - if name.startswith('MSG_') and not name.startswith('MSG_KEXDH_'): - messages[value] = name -# Check for regressions (#5352) -if 'MSG_KEXDH_INIT' in messages or 'MSG_KEXDH_REPLY' in messages: - raise RuntimeError( - "legacy SSH mnemonics should not end up in messages dict") diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/userauth.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/userauth.py deleted file mode 100755 index 65c0ef07..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/userauth.py +++ /dev/null @@ -1,848 +0,0 @@ -# -*- test-case-name: twisted.conch.test.test_userauth -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -Implementation of the ssh-userauth service. -Currently implemented authentication types are public-key and password. - -Maintainer: Paul Swartz -""" - -import struct, warnings -from twisted.conch import error, interfaces -from twisted.conch.ssh import keys, transport, service -from twisted.conch.ssh.common import NS, getNS -from twisted.cred import credentials -from twisted.cred.error import UnauthorizedLogin -from twisted.internet import defer, reactor -from twisted.python import failure, log - - - -class SSHUserAuthServer(service.SSHService): - """ - A service implementing the server side of the 'ssh-userauth' service. It - is used to authenticate the user on the other side as being able to access - this server. - - @ivar name: the name of this service: 'ssh-userauth' - @type name: C{str} - @ivar authenticatedWith: a list of authentication methods that have - already been used. - @type authenticatedWith: C{list} - @ivar loginTimeout: the number of seconds we wait before disconnecting - the user for taking too long to authenticate - @type loginTimeout: C{int} - @ivar attemptsBeforeDisconnect: the number of failed login attempts we - allow before disconnecting. - @type attemptsBeforeDisconnect: C{int} - @ivar loginAttempts: the number of login attempts that have been made - @type loginAttempts: C{int} - @ivar passwordDelay: the number of seconds to delay when the user gives - an incorrect password - @type passwordDelay: C{int} - @ivar interfaceToMethod: a C{dict} mapping credential interfaces to - authentication methods. The server checks to see which of the - cred interfaces have checkers and tells the client that those methods - are valid for authentication. - @type interfaceToMethod: C{dict} - @ivar supportedAuthentications: A list of the supported authentication - methods. - @type supportedAuthentications: C{list} of C{str} - @ivar user: the last username the client tried to authenticate with - @type user: C{str} - @ivar method: the current authentication method - @type method: C{str} - @ivar nextService: the service the user wants started after authentication - has been completed. - @type nextService: C{str} - @ivar portal: the L{twisted.cred.portal.Portal} we are using for - authentication - @type portal: L{twisted.cred.portal.Portal} - @ivar clock: an object with a callLater method. Stubbed out for testing. - """ - - - name = 'ssh-userauth' - loginTimeout = 10 * 60 * 60 - # 10 minutes before we disconnect them - attemptsBeforeDisconnect = 20 - # 20 login attempts before a disconnect - passwordDelay = 1 # number of seconds to delay on a failed password - clock = reactor - interfaceToMethod = { - credentials.ISSHPrivateKey : 'publickey', - credentials.IUsernamePassword : 'password', - credentials.IPluggableAuthenticationModules : 'keyboard-interactive', - } - - - def serviceStarted(self): - """ - Called when the userauth service is started. Set up instance - variables, check if we should allow password/keyboard-interactive - authentication (only allow if the outgoing connection is encrypted) and - set up a login timeout. - """ - self.authenticatedWith = [] - self.loginAttempts = 0 - self.user = None - self.nextService = None - self._pamDeferred = None - self.portal = self.transport.factory.portal - - self.supportedAuthentications = [] - for i in self.portal.listCredentialsInterfaces(): - if i in self.interfaceToMethod: - self.supportedAuthentications.append(self.interfaceToMethod[i]) - - if not self.transport.isEncrypted('in'): - # don't let us transport password in plaintext - if 'password' in self.supportedAuthentications: - self.supportedAuthentications.remove('password') - if 'keyboard-interactive' in self.supportedAuthentications: - self.supportedAuthentications.remove('keyboard-interactive') - self._cancelLoginTimeout = self.clock.callLater( - self.loginTimeout, - self.timeoutAuthentication) - - - def serviceStopped(self): - """ - Called when the userauth service is stopped. Cancel the login timeout - if it's still going. - """ - if self._cancelLoginTimeout: - self._cancelLoginTimeout.cancel() - self._cancelLoginTimeout = None - - - def timeoutAuthentication(self): - """ - Called when the user has timed out on authentication. Disconnect - with a DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE message. - """ - self._cancelLoginTimeout = None - self.transport.sendDisconnect( - transport.DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, - 'you took too long') - - - def tryAuth(self, kind, user, data): - """ - Try to authenticate the user with the given method. Dispatches to a - auth_* method. - - @param kind: the authentication method to try. - @type kind: C{str} - @param user: the username the client is authenticating with. - @type user: C{str} - @param data: authentication specific data sent by the client. - @type data: C{str} - @return: A Deferred called back if the method succeeded, or erred back - if it failed. - @rtype: C{defer.Deferred} - """ - log.msg('%s trying auth %s' % (user, kind)) - if kind not in self.supportedAuthentications: - return defer.fail( - error.ConchError('unsupported authentication, failing')) - kind = kind.replace('-', '_') - f = getattr(self,'auth_%s'%kind, None) - if f: - ret = f(data) - if not ret: - return defer.fail( - error.ConchError('%s return None instead of a Deferred' - % kind)) - else: - return ret - return defer.fail(error.ConchError('bad auth type: %s' % kind)) - - - def ssh_USERAUTH_REQUEST(self, packet): - """ - The client has requested authentication. Payload:: - string user - string next service - string method - <authentication specific data> - - @type packet: C{str} - """ - user, nextService, method, rest = getNS(packet, 3) - if user != self.user or nextService != self.nextService: - self.authenticatedWith = [] # clear auth state - self.user = user - self.nextService = nextService - self.method = method - d = self.tryAuth(method, user, rest) - if not d: - self._ebBadAuth( - failure.Failure(error.ConchError('auth returned none'))) - return - d.addCallback(self._cbFinishedAuth) - d.addErrback(self._ebMaybeBadAuth) - d.addErrback(self._ebBadAuth) - return d - - - def _cbFinishedAuth(self, (interface, avatar, logout)): - """ - The callback when user has successfully been authenticated. For a - description of the arguments, see L{twisted.cred.portal.Portal.login}. - We start the service requested by the user. - """ - self.transport.avatar = avatar - self.transport.logoutFunction = logout - service = self.transport.factory.getService(self.transport, - self.nextService) - if not service: - raise error.ConchError('could not get next service: %s' - % self.nextService) - log.msg('%s authenticated with %s' % (self.user, self.method)) - self.transport.sendPacket(MSG_USERAUTH_SUCCESS, '') - self.transport.setService(service()) - - - def _ebMaybeBadAuth(self, reason): - """ - An intermediate errback. If the reason is - error.NotEnoughAuthentication, we send a MSG_USERAUTH_FAILURE, but - with the partial success indicator set. - - @type reason: L{twisted.python.failure.Failure} - """ - reason.trap(error.NotEnoughAuthentication) - self.transport.sendPacket(MSG_USERAUTH_FAILURE, - NS(','.join(self.supportedAuthentications)) + '\xff') - - - def _ebBadAuth(self, reason): - """ - The final errback in the authentication chain. If the reason is - error.IgnoreAuthentication, we simply return; the authentication - method has sent its own response. Otherwise, send a failure message - and (if the method is not 'none') increment the number of login - attempts. - - @type reason: L{twisted.python.failure.Failure} - """ - if reason.check(error.IgnoreAuthentication): - return - if self.method != 'none': - log.msg('%s failed auth %s' % (self.user, self.method)) - if reason.check(UnauthorizedLogin): - log.msg('unauthorized login: %s' % reason.getErrorMessage()) - elif reason.check(error.ConchError): - log.msg('reason: %s' % reason.getErrorMessage()) - else: - log.msg(reason.getTraceback()) - self.loginAttempts += 1 - if self.loginAttempts > self.attemptsBeforeDisconnect: - self.transport.sendDisconnect( - transport.DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, - 'too many bad auths') - return - self.transport.sendPacket( - MSG_USERAUTH_FAILURE, - NS(','.join(self.supportedAuthentications)) + '\x00') - - - def auth_publickey(self, packet): - """ - Public key authentication. Payload:: - byte has signature - string algorithm name - string key blob - [string signature] (if has signature is True) - - Create a SSHPublicKey credential and verify it using our portal. - """ - hasSig = ord(packet[0]) - algName, blob, rest = getNS(packet[1:], 2) - pubKey = keys.Key.fromString(blob) - signature = hasSig and getNS(rest)[0] or None - if hasSig: - b = (NS(self.transport.sessionID) + chr(MSG_USERAUTH_REQUEST) + - NS(self.user) + NS(self.nextService) + NS('publickey') + - chr(hasSig) + NS(pubKey.sshType()) + NS(blob)) - c = credentials.SSHPrivateKey(self.user, algName, blob, b, - signature) - return self.portal.login(c, None, interfaces.IConchUser) - else: - c = credentials.SSHPrivateKey(self.user, algName, blob, None, None) - return self.portal.login(c, None, - interfaces.IConchUser).addErrback(self._ebCheckKey, - packet[1:]) - - - def _ebCheckKey(self, reason, packet): - """ - Called back if the user did not sent a signature. If reason is - error.ValidPublicKey then this key is valid for the user to - authenticate with. Send MSG_USERAUTH_PK_OK. - """ - reason.trap(error.ValidPublicKey) - # if we make it here, it means that the publickey is valid - self.transport.sendPacket(MSG_USERAUTH_PK_OK, packet) - return failure.Failure(error.IgnoreAuthentication()) - - - def auth_password(self, packet): - """ - Password authentication. Payload:: - string password - - Make a UsernamePassword credential and verify it with our portal. - """ - password = getNS(packet[1:])[0] - c = credentials.UsernamePassword(self.user, password) - return self.portal.login(c, None, interfaces.IConchUser).addErrback( - self._ebPassword) - - - def _ebPassword(self, f): - """ - If the password is invalid, wait before sending the failure in order - to delay brute-force password guessing. - """ - d = defer.Deferred() - self.clock.callLater(self.passwordDelay, d.callback, f) - return d - - - def auth_keyboard_interactive(self, packet): - """ - Keyboard interactive authentication. No payload. We create a - PluggableAuthenticationModules credential and authenticate with our - portal. - """ - if self._pamDeferred is not None: - self.transport.sendDisconnect( - transport.DISCONNECT_PROTOCOL_ERROR, - "only one keyboard interactive attempt at a time") - return defer.fail(error.IgnoreAuthentication()) - c = credentials.PluggableAuthenticationModules(self.user, - self._pamConv) - return self.portal.login(c, None, interfaces.IConchUser) - - - def _pamConv(self, items): - """ - Convert a list of PAM authentication questions into a - MSG_USERAUTH_INFO_REQUEST. Returns a Deferred that will be called - back when the user has responses to the questions. - - @param items: a list of 2-tuples (message, kind). We only care about - kinds 1 (password) and 2 (text). - @type items: C{list} - @rtype: L{defer.Deferred} - """ - resp = [] - for message, kind in items: - if kind == 1: # password - resp.append((message, 0)) - elif kind == 2: # text - resp.append((message, 1)) - elif kind in (3, 4): - return defer.fail(error.ConchError( - 'cannot handle PAM 3 or 4 messages')) - else: - return defer.fail(error.ConchError( - 'bad PAM auth kind %i' % kind)) - packet = NS('') + NS('') + NS('') - packet += struct.pack('>L', len(resp)) - for prompt, echo in resp: - packet += NS(prompt) - packet += chr(echo) - self.transport.sendPacket(MSG_USERAUTH_INFO_REQUEST, packet) - self._pamDeferred = defer.Deferred() - return self._pamDeferred - - - def ssh_USERAUTH_INFO_RESPONSE(self, packet): - """ - The user has responded with answers to PAMs authentication questions. - Parse the packet into a PAM response and callback self._pamDeferred. - Payload:: - uint32 numer of responses - string response 1 - ... - string response n - """ - d, self._pamDeferred = self._pamDeferred, None - - try: - resp = [] - numResps = struct.unpack('>L', packet[:4])[0] - packet = packet[4:] - while len(resp) < numResps: - response, packet = getNS(packet) - resp.append((response, 0)) - if packet: - raise error.ConchError("%i bytes of extra data" % len(packet)) - except: - d.errback(failure.Failure()) - else: - d.callback(resp) - - - -class SSHUserAuthClient(service.SSHService): - """ - A service implementing the client side of 'ssh-userauth'. - - @ivar name: the name of this service: 'ssh-userauth' - @type name: C{str} - @ivar preferredOrder: a list of authentication methods we support, in - order of preference. The client will try authentication methods in - this order, making callbacks for information when necessary. - @type preferredOrder: C{list} - @ivar user: the name of the user to authenticate as - @type user: C{str} - @ivar instance: the service to start after authentication has finished - @type instance: L{service.SSHService} - @ivar authenticatedWith: a list of strings of authentication methods we've tried - @type authenticatedWith: C{list} of C{str} - @ivar triedPublicKeys: a list of public key objects that we've tried to - authenticate with - @type triedPublicKeys: C{list} of L{Key} - @ivar lastPublicKey: the last public key object we've tried to authenticate - with - @type lastPublicKey: L{Key} - """ - - - name = 'ssh-userauth' - preferredOrder = ['publickey', 'password', 'keyboard-interactive'] - - - def __init__(self, user, instance): - self.user = user - self.instance = instance - - - def serviceStarted(self): - self.authenticatedWith = [] - self.triedPublicKeys = [] - self.lastPublicKey = None - self.askForAuth('none', '') - - - def askForAuth(self, kind, extraData): - """ - Send a MSG_USERAUTH_REQUEST. - - @param kind: the authentication method to try. - @type kind: C{str} - @param extraData: method-specific data to go in the packet - @type extraData: C{str} - """ - self.lastAuth = kind - self.transport.sendPacket(MSG_USERAUTH_REQUEST, NS(self.user) + - NS(self.instance.name) + NS(kind) + extraData) - - - def tryAuth(self, kind): - """ - Dispatch to an authentication method. - - @param kind: the authentication method - @type kind: C{str} - """ - kind = kind.replace('-', '_') - log.msg('trying to auth with %s' % (kind,)) - f = getattr(self,'auth_%s' % (kind,), None) - if f: - return f() - - - def _ebAuth(self, ignored, *args): - """ - Generic callback for a failed authentication attempt. Respond by - asking for the list of accepted methods (the 'none' method) - """ - self.askForAuth('none', '') - - - def ssh_USERAUTH_SUCCESS(self, packet): - """ - We received a MSG_USERAUTH_SUCCESS. The server has accepted our - authentication, so start the next service. - """ - self.transport.setService(self.instance) - - - def ssh_USERAUTH_FAILURE(self, packet): - """ - We received a MSG_USERAUTH_FAILURE. Payload:: - string methods - byte partial success - - If partial success is C{True}, then the previous method succeeded but is - not sufficent for authentication. C{methods} is a comma-separated list - of accepted authentication methods. - - We sort the list of methods by their position in C{self.preferredOrder}, - removing methods that have already succeeded. We then call - C{self.tryAuth} with the most preferred method. - - @param packet: the L{MSG_USERAUTH_FAILURE} payload. - @type packet: C{str} - - @return: a L{defer.Deferred} that will be callbacked with C{None} as - soon as all authentication methods have been tried, or C{None} if no - more authentication methods are available. - @rtype: C{defer.Deferred} or C{None} - """ - canContinue, partial = getNS(packet) - partial = ord(partial) - if partial: - self.authenticatedWith.append(self.lastAuth) - - def orderByPreference(meth): - """ - Invoked once per authentication method in order to extract a - comparison key which is then used for sorting. - - @param meth: the authentication method. - @type meth: C{str} - - @return: the comparison key for C{meth}. - @rtype: C{int} - """ - if meth in self.preferredOrder: - return self.preferredOrder.index(meth) - else: - # put the element at the end of the list. - return len(self.preferredOrder) - - canContinue = sorted([meth for meth in canContinue.split(',') - if meth not in self.authenticatedWith], - key=orderByPreference) - - log.msg('can continue with: %s' % canContinue) - return self._cbUserauthFailure(None, iter(canContinue)) - - - def _cbUserauthFailure(self, result, iterator): - if result: - return - try: - method = iterator.next() - except StopIteration: - self.transport.sendDisconnect( - transport.DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, - 'no more authentication methods available') - else: - d = defer.maybeDeferred(self.tryAuth, method) - d.addCallback(self._cbUserauthFailure, iterator) - return d - - - def ssh_USERAUTH_PK_OK(self, packet): - """ - This message (number 60) can mean several different messages depending - on the current authentication type. We dispatch to individual methods - in order to handle this request. - """ - func = getattr(self, 'ssh_USERAUTH_PK_OK_%s' % - self.lastAuth.replace('-', '_'), None) - if func is not None: - return func(packet) - else: - self.askForAuth('none', '') - - - def ssh_USERAUTH_PK_OK_publickey(self, packet): - """ - This is MSG_USERAUTH_PK. Our public key is valid, so we create a - signature and try to authenticate with it. - """ - publicKey = self.lastPublicKey - b = (NS(self.transport.sessionID) + chr(MSG_USERAUTH_REQUEST) + - NS(self.user) + NS(self.instance.name) + NS('publickey') + - '\x01' + NS(publicKey.sshType()) + NS(publicKey.blob())) - d = self.signData(publicKey, b) - if not d: - self.askForAuth('none', '') - # this will fail, we'll move on - return - d.addCallback(self._cbSignedData) - d.addErrback(self._ebAuth) - - - def ssh_USERAUTH_PK_OK_password(self, packet): - """ - This is MSG_USERAUTH_PASSWD_CHANGEREQ. The password given has expired. - We ask for an old password and a new password, then send both back to - the server. - """ - prompt, language, rest = getNS(packet, 2) - self._oldPass = self._newPass = None - d = self.getPassword('Old Password: ') - d = d.addCallbacks(self._setOldPass, self._ebAuth) - d.addCallback(lambda ignored: self.getPassword(prompt)) - d.addCallbacks(self._setNewPass, self._ebAuth) - - - def ssh_USERAUTH_PK_OK_keyboard_interactive(self, packet): - """ - This is MSG_USERAUTH_INFO_RESPONSE. The server has sent us the - questions it wants us to answer, so we ask the user and sent the - responses. - """ - name, instruction, lang, data = getNS(packet, 3) - numPrompts = struct.unpack('!L', data[:4])[0] - data = data[4:] - prompts = [] - for i in range(numPrompts): - prompt, data = getNS(data) - echo = bool(ord(data[0])) - data = data[1:] - prompts.append((prompt, echo)) - d = self.getGenericAnswers(name, instruction, prompts) - d.addCallback(self._cbGenericAnswers) - d.addErrback(self._ebAuth) - - - def _cbSignedData(self, signedData): - """ - Called back out of self.signData with the signed data. Send the - authentication request with the signature. - - @param signedData: the data signed by the user's private key. - @type signedData: C{str} - """ - publicKey = self.lastPublicKey - self.askForAuth('publickey', '\x01' + NS(publicKey.sshType()) + - NS(publicKey.blob()) + NS(signedData)) - - - def _setOldPass(self, op): - """ - Called back when we are choosing a new password. Simply store the old - password for now. - - @param op: the old password as entered by the user - @type op: C{str} - """ - self._oldPass = op - - - def _setNewPass(self, np): - """ - Called back when we are choosing a new password. Get the old password - and send the authentication message with both. - - @param np: the new password as entered by the user - @type np: C{str} - """ - op = self._oldPass - self._oldPass = None - self.askForAuth('password', '\xff' + NS(op) + NS(np)) - - - def _cbGenericAnswers(self, responses): - """ - Called back when we are finished answering keyboard-interactive - questions. Send the info back to the server in a - MSG_USERAUTH_INFO_RESPONSE. - - @param responses: a list of C{str} responses - @type responses: C{list} - """ - data = struct.pack('!L', len(responses)) - for r in responses: - data += NS(r.encode('UTF8')) - self.transport.sendPacket(MSG_USERAUTH_INFO_RESPONSE, data) - - - def auth_publickey(self): - """ - Try to authenticate with a public key. Ask the user for a public key; - if the user has one, send the request to the server and return True. - Otherwise, return False. - - @rtype: C{bool} - """ - d = defer.maybeDeferred(self.getPublicKey) - d.addBoth(self._cbGetPublicKey) - return d - - - def _cbGetPublicKey(self, publicKey): - if isinstance(publicKey, str): - warnings.warn("Returning a string from " - "SSHUserAuthClient.getPublicKey() is deprecated " - "since Twisted 9.0. Return a keys.Key() instead.", - DeprecationWarning) - publicKey = keys.Key.fromString(publicKey) - if not isinstance(publicKey, keys.Key): # failure or None - publicKey = None - if publicKey is not None: - self.lastPublicKey = publicKey - self.triedPublicKeys.append(publicKey) - log.msg('using key of type %s' % publicKey.type()) - self.askForAuth('publickey', '\x00' + NS(publicKey.sshType()) + - NS(publicKey.blob())) - return True - else: - return False - - - def auth_password(self): - """ - Try to authenticate with a password. Ask the user for a password. - If the user will return a password, return True. Otherwise, return - False. - - @rtype: C{bool} - """ - d = self.getPassword() - if d: - d.addCallbacks(self._cbPassword, self._ebAuth) - return True - else: # returned None, don't do password auth - return False - - - def auth_keyboard_interactive(self): - """ - Try to authenticate with keyboard-interactive authentication. Send - the request to the server and return True. - - @rtype: C{bool} - """ - log.msg('authing with keyboard-interactive') - self.askForAuth('keyboard-interactive', NS('') + NS('')) - return True - - - def _cbPassword(self, password): - """ - Called back when the user gives a password. Send the request to the - server. - - @param password: the password the user entered - @type password: C{str} - """ - self.askForAuth('password', '\x00' + NS(password)) - - - def signData(self, publicKey, signData): - """ - Sign the given data with the given public key. - - By default, this will call getPrivateKey to get the private key, - then sign the data using Key.sign(). - - This method is factored out so that it can be overridden to use - alternate methods, such as a key agent. - - @param publicKey: The public key object returned from L{getPublicKey} - @type publicKey: L{keys.Key} - - @param signData: the data to be signed by the private key. - @type signData: C{str} - @return: a Deferred that's called back with the signature - @rtype: L{defer.Deferred} - """ - key = self.getPrivateKey() - if not key: - return - return key.addCallback(self._cbSignData, signData) - - - def _cbSignData(self, privateKey, signData): - """ - Called back when the private key is returned. Sign the data and - return the signature. - - @param privateKey: the private key object - @type publicKey: L{keys.Key} - @param signData: the data to be signed by the private key. - @type signData: C{str} - @return: the signature - @rtype: C{str} - """ - if not isinstance(privateKey, keys.Key): - warnings.warn("Returning a PyCrypto key object from " - "SSHUserAuthClient.getPrivateKey() is deprecated " - "since Twisted 9.0. Return a keys.Key() instead.", - DeprecationWarning) - privateKey = keys.Key(privateKey) - return privateKey.sign(signData) - - - def getPublicKey(self): - """ - Return a public key for the user. If no more public keys are - available, return C{None}. - - This implementation always returns C{None}. Override it in a - subclass to actually find and return a public key object. - - @rtype: L{Key} or L{NoneType} - """ - return None - - - def getPrivateKey(self): - """ - Return a L{Deferred} that will be called back with the private key - object corresponding to the last public key from getPublicKey(). - If the private key is not available, errback on the Deferred. - - @rtype: L{Deferred} called back with L{Key} - """ - return defer.fail(NotImplementedError()) - - - def getPassword(self, prompt = None): - """ - Return a L{Deferred} that will be called back with a password. - prompt is a string to display for the password, or None for a generic - 'user@hostname's password: '. - - @type prompt: C{str}/C{None} - @rtype: L{defer.Deferred} - """ - return defer.fail(NotImplementedError()) - - - def getGenericAnswers(self, name, instruction, prompts): - """ - Returns a L{Deferred} with the responses to the promopts. - - @param name: The name of the authentication currently in progress. - @param instruction: Describes what the authentication wants. - @param prompts: A list of (prompt, echo) pairs, where prompt is a - string to display and echo is a boolean indicating whether the - user's response should be echoed as they type it. - """ - return defer.fail(NotImplementedError()) - - -MSG_USERAUTH_REQUEST = 50 -MSG_USERAUTH_FAILURE = 51 -MSG_USERAUTH_SUCCESS = 52 -MSG_USERAUTH_BANNER = 53 -MSG_USERAUTH_INFO_RESPONSE = 61 -MSG_USERAUTH_PK_OK = 60 - -messages = {} -for k, v in locals().items(): - if k[:4]=='MSG_': - messages[v] = k - -SSHUserAuthServer.protocolMessages = messages -SSHUserAuthClient.protocolMessages = messages -del messages -del v - -# Doubles, not included in the protocols' mappings -MSG_USERAUTH_PASSWD_CHANGEREQ = 60 -MSG_USERAUTH_INFO_REQUEST = 60 |