mirror of
https://github.com/aljazceru/cowrie.git
synced 2026-01-05 07:14:24 +01:00
sftp protocol support
This commit is contained in:
@@ -215,6 +215,11 @@ class HoneyPotAvatar(avatar.ConchUser):
|
||||
userdb = core.auth.UserDB()
|
||||
self.uid = self.gid = userdb.getUID(self.username)
|
||||
|
||||
# sftp support enabled only when option is explicitly set
|
||||
if self.env.cfg.has_option('honeypot', 'sftp_enabled'):
|
||||
if ( self.env.cfg.get('honeypot', 'sftp_enabled') == "true" ):
|
||||
self.subsystemLookup['sftp'] = filetransfer.FileTransferServer
|
||||
|
||||
if not self.uid:
|
||||
self.home = '/root'
|
||||
else:
|
||||
@@ -304,4 +309,181 @@ def getDSAKeys():
|
||||
privateKeyString = f.read()
|
||||
return publicKeyString, privateKeyString
|
||||
|
||||
|
||||
class KippoSFTPFile:
|
||||
implements(conchinterfaces.ISFTPFile)
|
||||
|
||||
def __init__(self, server, filename, flags, attrs):
|
||||
self.server = server
|
||||
self.filename = filename
|
||||
self.transfer_completed = 0
|
||||
self.bytes_written = 0
|
||||
openFlags = 0
|
||||
if flags & FXF_READ == FXF_READ and flags & FXF_WRITE == 0:
|
||||
openFlags = os.O_RDONLY
|
||||
if flags & FXF_WRITE == FXF_WRITE and flags & FXF_READ == 0:
|
||||
openFlags = os.O_WRONLY
|
||||
if flags & FXF_WRITE == FXF_WRITE and flags & FXF_READ == FXF_READ:
|
||||
openFlags = os.O_RDWR
|
||||
if flags & FXF_APPEND == FXF_APPEND:
|
||||
openFlags |= os.O_APPEND
|
||||
if flags & FXF_CREAT == FXF_CREAT:
|
||||
openFlags |= os.O_CREAT
|
||||
if flags & FXF_TRUNC == FXF_TRUNC:
|
||||
openFlags |= os.O_TRUNC
|
||||
if flags & FXF_EXCL == FXF_EXCL:
|
||||
openFlags |= os.O_EXCL
|
||||
if attrs.has_key("permissions"):
|
||||
mode = attrs["permissions"]
|
||||
del attrs["permissions"]
|
||||
else:
|
||||
mode = 0777
|
||||
fd = server.fs.open(filename, openFlags, mode)
|
||||
if attrs:
|
||||
self.server.setAttrs(filename, attrs)
|
||||
self.fd = fd
|
||||
|
||||
# cache a copy of file in memory to read from in readChunk
|
||||
if flags & FXF_READ == FXF_READ:
|
||||
self.contents = self.server.fs.file_contents(self.filename)
|
||||
|
||||
def close(self):
|
||||
if ( self.bytes_written > 0 ):
|
||||
self.server.fs.update_size(self.filename, self.bytes_written)
|
||||
return self.server.fs.close(self.fd)
|
||||
|
||||
def readChunk(self, offset, length):
|
||||
return self.contents[offset:offset+length]
|
||||
|
||||
def writeChunk(self, offset, data):
|
||||
self.server.fs.lseek(self.fd, offset, os.SEEK_SET)
|
||||
self.server.fs.write(self.fd, data)
|
||||
self.bytes_written += len(data)
|
||||
|
||||
def getAttrs(self):
|
||||
s = self.server.fs.fstat(self.fd)
|
||||
return self.server._getAttrs(s)
|
||||
|
||||
def setAttrs(self, attrs):
|
||||
raise NotImplementedError
|
||||
|
||||
class KippoSFTPDirectory:
|
||||
|
||||
def __init__(self, server, directory):
|
||||
self.server = server
|
||||
self.files = server.fs.listdir(directory)
|
||||
self.dir = directory
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def next(self):
|
||||
try:
|
||||
f = self.files.pop(0)
|
||||
except IndexError:
|
||||
raise StopIteration
|
||||
else:
|
||||
s = self.server.fs.lstat(os.path.join(self.dir, f))
|
||||
longname = twisted.conch.ls.lsLine(f, s)
|
||||
attrs = self.server._getAttrs(s)
|
||||
return (f, longname, attrs)
|
||||
|
||||
def close(self):
|
||||
self.files = []
|
||||
|
||||
class KippoSFTPServer:
|
||||
implements(conchinterfaces.ISFTPServer)
|
||||
|
||||
def __init__(self, avatar):
|
||||
self.avatar = avatar
|
||||
# FIXME we should not copy fs here, but do this at avatar instantiation
|
||||
self.fs = fs.HoneyPotFilesystem(copy.deepcopy(self.avatar.env.fs))
|
||||
|
||||
def _absPath(self, path):
|
||||
home = self.avatar.home
|
||||
return os.path.abspath(os.path.join(home, path))
|
||||
|
||||
def _setAttrs(self, path, attrs):
|
||||
if attrs.has_key("uid") and attrs.has_key("gid"):
|
||||
self.fs.chown(path, attrs["uid"], attrs["gid"])
|
||||
if attrs.has_key("permissions"):
|
||||
self.fs.chmod(path, attrs["permissions"])
|
||||
if attrs.has_key("atime") and attrs.has_key("mtime"):
|
||||
self.fs.utime(path, attrs["atime"], attrs["mtime"])
|
||||
|
||||
def _getAttrs(self, s):
|
||||
return {
|
||||
"size" : s.st_size,
|
||||
"uid" : s.st_uid,
|
||||
"gid" : s.st_gid,
|
||||
"permissions" : s.st_mode,
|
||||
"atime" : int(s.st_atime),
|
||||
"mtime" : int(s.st_mtime)
|
||||
}
|
||||
|
||||
def gotVersion(self, otherVersion, extData):
|
||||
return {}
|
||||
|
||||
def openFile(self, filename, flags, attrs):
|
||||
print "SFTP openFile: %s" % filename
|
||||
return KippoSFTPFile(self, self._absPath(filename), flags, attrs)
|
||||
|
||||
def removeFile(self, filename):
|
||||
print "SFTP removeFile: %s" % filename
|
||||
return self.fs.remove(self._absPath(filename))
|
||||
|
||||
def renameFile(self, oldpath, newpath):
|
||||
print "SFTP renameFile: %s %s" % (oldpath, newpath)
|
||||
return self.fs.rename(self._absPath(oldpath), self._absPath(newpath))
|
||||
|
||||
def makeDirectory(self, path, attrs):
|
||||
print "SFTP makeDirectory: %s" % path
|
||||
path = self._absPath(path)
|
||||
self.fs.mkdir2(path)
|
||||
self._setAttrs(path, attrs)
|
||||
return
|
||||
|
||||
def removeDirectory(self, path):
|
||||
print "SFTP removeDirectory: %s" % path
|
||||
return self.fs.rmdir(self._absPath(path))
|
||||
|
||||
def openDirectory(self, path):
|
||||
print "SFTP OpenDirectory: %s" % path
|
||||
return KippoSFTPDirectory(self, self._absPath(path))
|
||||
|
||||
def getAttrs(self, path, followLinks):
|
||||
print "SFTP getAttrs: %s" % path
|
||||
path = self._absPath(path)
|
||||
if followLinks:
|
||||
s = self.fs.stat(path)
|
||||
else:
|
||||
s = self.fs.lstat(path)
|
||||
return self._getAttrs(s)
|
||||
|
||||
def setAttrs(self, path, attrs):
|
||||
print "SFTP setAttrs: %s" % path
|
||||
path = self._absPath(path)
|
||||
return self._setAttrs(path, attrs)
|
||||
|
||||
def readLink(self, path):
|
||||
print "SFTP readLink: %s" % path
|
||||
path = self._absPath(path)
|
||||
return self.fs.readlink(path)
|
||||
|
||||
def makeLink(self, linkPath, targetPath):
|
||||
print "SFTP makeLink: %s" % path
|
||||
linkPath = self._absPath(linkPath)
|
||||
targetPath = self._absPath(targetPath)
|
||||
return self.fs.symlink(targetPath, linkPath)
|
||||
|
||||
def realPath(self, path):
|
||||
print "SFTP realPath: %s" % path
|
||||
return self.fs.realpath(self._absPath(path))
|
||||
|
||||
def extendedRequest(self, extName, extData):
|
||||
raise NotImplementedError
|
||||
|
||||
components.registerAdapter( KippoSFTPServer, HoneyPotAvatar, conchinterfaces.ISFTPServer)
|
||||
|
||||
|
||||
# vim: set et sw=4 et:
|
||||
|
||||
Reference in New Issue
Block a user