def ssh_USERAUTH_PK_OK(self, packet): if self.lastAuth == 'publickey': # this is ok publicKey = self.lastPublicKey keyType = getNS(publicKey)[0] b = NS(self.transport.sessionID) + chr(MSG_USERAUTH_REQUEST) + \ NS(self.user) + NS(self.instance.name) + NS('publickey') + '\xff' +\ NS(keyType) + NS(publicKey) 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) elif self.lastAuth == 'password': prompt, language, rest = getNS(packet, 2) self._oldPass = self._newPass = None self.getPassword('Old Password: '******'keyboard-interactive': 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 _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 _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 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 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 ssh_KEX_DH_GEX_REPLY(self, packet): pubKey, packet = getNS(packet) f, packet = getMP(packet) signature, packet = getNS(packet) fingerprint = ':'.join(map(lambda c: '%02x'%ord(c), md5.new(pubKey).digest())) d = self.verifyHostKey(pubKey, fingerprint) d.addCallback(self._continueGEX_REPLY, pubKey, f, signature) d.addErrback(lambda unused, self=self: self.sendDisconnect(DISCONNECT_HOST_KEY_NOT_VERIFIABLE, 'bad host key'))
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_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_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_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 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 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_STATUS(self, data): d, data = self._parseRequest(data) code, = struct.unpack('!L', data[:4]) data = data[4:] msg, data = getNS(data) lang = getNS(data) 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_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_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 ssh_KEX_DH_GEX_GROUP(self, packet): if self.kexAlg == 'diffie-hellman-group1-sha1': pubKey, packet = getNS(packet) f, packet = getMP(packet) signature, packet = getNS(packet) fingerprint = ':'.join(map(lambda c: '%02x'%ord(c), md5.new(pubKey).digest())) d = self.verifyHostKey(pubKey, fingerprint) d.addCallback(self._continueGEX_GROUP, pubKey, f, signature) d.addErrback(lambda unused,self=self:self.sendDisconnect(DISCONNECT_HOST_KEY_NOT_VERIFIABLE, 'bad host key')) else: self.p, rest = getMP(packet) self.g, rest = getMP(rest) self.x = getMP('\x00\x00\x00\x40'+entropy.get_bytes(64))[0] self.DHpubKey = pow(self.g, self.x, self.p) self.sendPacket(MSG_KEX_DH_GEX_INIT, MP(self.DHpubKey))
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 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 auth_publickey(self, packet): hasSig = ord(packet[0]) algName, blob, rest = getNS(packet[1:], 2) pubKey = keys.getPublicKeyObject(data = 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(keys.objectType(pubKey)) + 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 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 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 ssh_SERVICE_ACCEPT(self, packet): 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 ssh_USERAUTH_FAILURE(self, packet): canContinue, partial = getNS(packet) canContinue = canContinue.split(',') partial = ord(partial) if partial: self.authenticatedWith.append(self.lastAuth) def _(x, y): try: i1 = self.preferredOrder.index(x) except ValueError: return 1 try: i2 = self.preferredOrder.index(y) except ValueError: return -1 return cmp(i1, i2) canContinue.sort(_) log.msg('can continue with: %s' % canContinue) for method in canContinue: if method not in self.authenticatedWith and self.tryAuth(method): return self.transport.sendDisconnect( transport.DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, 'no more authentication methods available')
def ssh_USERAUTH_FAILURE(self, packet): canContinue, partial = getNS(packet) canContinue = canContinue.split(",") partial = ord(partial) if partial: self.authenticatedWith.append(self.lastAuth) def _(x, y): try: i1 = self.preferredOrder.index(x) except ValueError: return 1 try: i2 = self.preferredOrder.index(y) except ValueError: return -1 return cmp(i1, i2) canContinue.sort(_) log.msg("can continue with: %s" % canContinue) for method in canContinue: if method not in self.authenticatedWith and self.tryAuth(method): return self.transport.sendDisconnect( transport.DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, "no more authentication methods available" )
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 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_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_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_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 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 ssh_CHANNEL_OPEN_FAILURE(self, packet): 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 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 ssh_CHANNEL_OPEN_FAILURE(self, packet): 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 auth_publickey(self, packet): hasSig = ord(packet[0]) algName, blob, rest = getNS(packet[1:], 2) pubKey = keys.getPublicKeyObject(data=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(keys.objectType(pubKey)) + 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 ssh_SERVICE_REQUEST(self, packet): 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())
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_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 getPublicKeys(self): ks = {} for file in os.listdir(self.dataRoot): if file[:9] == 'ssh_host_' and file[-8:]=='_key.pub': try: k = keys.getPublicKeyString(self.dataRoot+'/'+file) t = common.getNS(k)[0] ks[t] = k except: log.msg('bad public key file %s' % file) return ks
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 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")