def ssh_CHANNEL_OPEN(self, packet): 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, '') except Exception, e: log.msg('channel open failed') log.err(e) if isinstance(e, error.ConchError): reason, textualInfo = e.args[0], e.data 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 makePrivateKeyBlob(obj): keyType = objectType(obj) if keyType == 'ssh-rsa': return common.NS(keyType) + common.MP(obj.n) + common.MP(obj.e) + \ common.MP(obj.d) + common.MP(obj.u) + common.MP(obj.q) + \ common.MP(obj.p) elif keyType == 'ssh-dss': return common.NS(keyType) + common.MP(obj.p) + common.MP(obj.q) + \ common.MP(obj.g) + common.MP(obj.y) + common.MP(obj.x) else: raise ValueError('trying to get blob for invalid key type: %s' % keyType)
def packOpen_direct_tcpip(destination, source): """ Pack the data suitable for sending in a CHANNEL_OPEN packet. @type destination: C{tuple} @param destination: A tuple of the (host, port) of the destination host. @type source: C{tuple} @param source: A tuple of the (host, port) of the source host. """ (connHost, connPort) = destination (origHost, origPort) = source conn = common.NS(connHost) + struct.pack('>L', connPort) orig = common.NS(origHost) + struct.pack('>L', origPort) return conn + orig
def packGlobal_tcpip_forward(peer): """ Pack the data for tcpip forwarding. @param peer: A tuple of the (host, port) . @type peer: C{tuple} """ (host, port) = peer return common.NS(host) + struct.pack('>L', port)
def makePrivateKeyString_agentv3(obj, passphrase): if passphrase: raise BadKeyError("cannot encrypt to agent v3 format") keyType = objectType(obj) if keyType == 'ssh-rsa': values = (obj.e, obj.d, obj.n, obj.u, obj.p, obj.q) elif keyType == 'ssh-dss': values = (obj.p, obj.q, obj.g, obj.y, obj.x) return common.NS(keytype) + ''.join(map(common.MP, values))
def makePublicKeyBlob(obj): keyType = objectType(obj) if keyType == 'ssh-rsa': keyData = common.MP(obj.e) + common.MP(obj.n) elif keyType == 'ssh-dss': keyData = common.MP(obj.p) keyData += common.MP(obj.q) keyData += common.MP(obj.g) keyData += common.MP(obj.y) return common.NS(keyType) + keyData
def signData(obj, data): """ Sign the data with the given C{Crypto.PublicKey.pubkey.pubkey} object. @type obj: C{Crypto.PublicKey.pubkey.pubkey} @type data: C{str} @rtype: C{str} """ mapping = {'ssh-rsa': signData_rsa, 'ssh-dss': signData_dsa} objType = objectType(obj) return common.NS(objType) + mapping[objType](obj, data)
def signData_dsa(obj, data): sigData = sha.new(data).digest() randData = common.entropy.get_bytes(19) sig = obj.sign(sigData, randData) # 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) return common.NS( Util.number.long_to_bytes(sig[0], 20) + Util.number.long_to_bytes(sig[1], 20))
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 C{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 getPublicKeyString_lsh(data): sexp = sexpy.parse(base64.decodestring(data[1:-1])) assert sexp[0] == 'public-key' kd = {} for name, data in sexp[1][1:]: kd[name] = common.NS(data) if sexp[1][0] == 'dsa': assert len(kd) == 4, len(kd) return '\x00\x00\x00\x07ssh-dss' + kd['p'] + kd['q'] + kd['g'] + kd['y'] elif sexp[1][0] == 'rsa-pkcs1-sha1': assert len(kd) == 2, len(kd) return '\x00\x00\x00\x07ssh-rsa' + kd['e'] + kd['n'] else: raise BadKeyError('unknown lsh key type %s' % sexp[1][0])
def makePublicKeyString_openssh(obj, comment): keyType = objectType(obj) if keyType == 'ssh-rsa': keyData = common.MP(obj.e) + common.MP(obj.n) elif keyType == 'ssh-dss': keyData = common.MP(obj.p) keyData += common.MP(obj.q) keyData += common.MP(obj.g) keyData += common.MP(obj.y) else: raise BadKeyError('unknown key type %s' % keyType) b64Data = base64.encodestring(common.NS(keyType) + keyData).replace( '\n', '') return '%s %s %s' % (keyType, b64Data, comment)
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 getPrivateKeyObject_lsh(data, passphrase): #assert passphrase == '' data = ''.join(data) 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 DSA.construct((kd['y'], kd['g'], kd['p'], kd['q'], kd['x'])) elif sexp[1][0] == 'rsa-pkcs1': assert len(kd) == 8, len(kd) return RSA.construct((kd['n'], kd['e'], kd['d'], kd['p'], kd['q'])) else: raise BadKeyError('unknown lsh key type %s' % sexp[1][0])
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.setdefault('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
@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. """
def signData_rsa(obj, data): sigData = pkcs1Digest(data, lenSig(obj)) sig = obj.sign(sigData, '')[0] return common.NS( Util.number.long_to_bytes(sig)) # get around adding the \x00 byte
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)
def packGlobal_tcpip_forward((host, port)): return common.NS(host) + struct.pack('>L', port)