aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh')
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/__init__.py10
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/address.py38
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/agent.py294
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/channel.py281
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/common.py117
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/connection.py637
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/factory.py141
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/filetransfer.py934
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/forwarding.py181
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/keys.py809
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/service.py48
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/session.py348
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/sexpy.py42
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/transport.py1617
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/conch/ssh/userauth.py848
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