seems to work. symbolic links

This commit is contained in:
Michel Oosterhof
2015-09-25 19:22:56 +00:00
parent c1a12655b8
commit 856906f0bc
2 changed files with 79 additions and 51 deletions

View File

@ -129,24 +129,16 @@ class command_cd(HoneyPotCommand):
path = self.args[0]
try:
newpath = self.fs.resolve_path(path, self.honeypot.cwd)
newdir = self.fs.get_path(newpath)
inode = self.fs.getfile(newpath)
except:
newdir = None
if path == "-":
self.writeln('bash: cd: OLDPWD not set')
return
if newdir is None:
if inode is None:
self.writeln('bash: cd: %s: No such file or directory' % path)
return
count = 0
while self.fs.islink(newpath):
f = self.fs.getfile(newpath)
newpath = f[A_TARGET]
count += 1
if count > 10:
self.writeln('bash: cd: %s: Too many levels of symbolic links' % path)
return
if not self.fs.isdir(newpath):
if inode[A_TYPE] != T_DIR:
self.writeln('bash: cd: %s: Not a directory' % path)
return
self.honeypot.cwd = newpath

View File

@ -91,7 +91,10 @@ class HoneyPotFilesystem(object):
foo(pieces, cwd)
return found
def get_path(self, path):
def get_path(self, path, follow_symlinks=True):
'''
this returns the Cowrie file system objects for a directory
'''
cwd = self.fs
for part in path.split('/'):
if not len(part):
@ -99,7 +102,10 @@ class HoneyPotFilesystem(object):
ok = False
for c in cwd[A_CONTENTS]:
if c[A_NAME] == part:
cwd = c
if c[A_TYPE] == T_LINK:
cwd = self.getfile(c[A_TARGET], follow_symlinks=follow_symlinks)
else:
cwd = c
ok = True
break
if not ok:
@ -107,10 +113,25 @@ class HoneyPotFilesystem(object):
return cwd[A_CONTENTS]
def exists(self, path):
'''
Return True if path refers to an existing path. Returns False for
broken symbolic links. On some platforms, this function may return
False if permission is not granted to execute os.stat() on the
requested file, even if the path physically exists.
'''
f = self.getfile(path)
if f is not False:
return True
def lexists(self, path):
'''
Return True if path refers to an existing path.
Returns True for broken symbolic links.
'''
f = self.getfile(path, follow_symlinks=False)
if f is not False:
return True
def update_realfile(self, f, realfile):
if not f[A_REALFILE] and os.path.exists(realfile) and \
not os.path.islink(realfile) and os.path.isfile(realfile) and \
@ -124,19 +145,35 @@ class HoneyPotFilesystem(object):
return f[A_REALFILE]
return None
def getfile(self, path):
def getfile(self, path, follow_symlinks=True):
'''
this returns the Cowrie file system object for a path
'''
if path == '/':
return self.fs
pieces = path.strip('/').split('/')
cwd = ''
p = self.fs
while 1:
if not len(pieces):
break
piece = pieces.pop(0)
for piece in pieces:
cwd = '/'.join((cwd, piece))
if piece not in [x[A_NAME] for x in p[A_CONTENTS]]:
return False
p = [x for x in p[A_CONTENTS] \
if x[A_NAME] == piece][0]
for x in p[A_CONTENTS]:
if x[A_NAME] == piece:
if piece == pieces[-1] and follow_symlinks==False:
p = x
elif x[A_TYPE] == T_LINK:
if x[A_TARGET][0] == '/':
# absolute link
p = self.getfile(x[A_TARGET], follow_symlinks=follow_symlinks)
else:
# relative link
p = self.getfile('/'.join((cwd, x[A_TARGET])),follow_symlinks=follow_symlinks)
if p == False:
# broken link
return False
else:
p = x
return p
def file_contents(self, target, count=0):
@ -185,7 +222,23 @@ class HoneyPotFilesystem(object):
self.newcount += 1
return True
def isfile(self, path):
'''
Return True if path is an existing regular file. This follows symbolic
links, so both islink() and isfile() can be true for the same path.
'''
try:
f = self.getfile(path)
except:
return False
return f[A_TYPE] == T_FILE
def islink(self, path):
'''
Return True if path refers to a directory entry that is a symbolic
link. Always False if symbolic links are not supported by the python
runtime.
'''
try:
f = self.getfile(path)
except:
@ -193,20 +246,22 @@ class HoneyPotFilesystem(object):
return f[A_TYPE] == T_LINK
def isdir(self, path):
'''
Return True if path is an existing directory.
This follows symbolic links, so both islink() and isdir() can be true for the same path.
'''
if path == '/':
return True
try:
dir = self.get_path(os.path.dirname(path))
dir = self.getfile(path)
except:
dir = None
if dir is None:
return False
l = [x for x in dir
if x[A_NAME] == os.path.basename(path) and
x[A_TYPE] == T_DIR]
if l:
if dir[A_TYPE] == T_DIR:
return True
return False
else:
return False
# additions for SFTP support, try to keep functions here similar to os.*
@ -351,32 +406,13 @@ class HoneyPotFilesystem(object):
return names
def lstat(self, path):
# need to treat / as exception
return self.stat(path, follow_symlinks=False)
def stat(self, path, follow_symlinks=True):
if (path == "/"):
p = {A_TYPE:T_DIR, A_UID:0, A_GID:0, A_SIZE:4096, A_MODE:16877, A_CTIME:time.time()}
else:
p = self.getfile(path)
if p == False:
raise OSError(errno.ENOENT, os.strerror(errno.ENOENT))
return _statobj(
p[A_MODE],
0,
0,
1,
p[A_UID],
p[A_GID],
p[A_SIZE],
p[A_CTIME],
p[A_CTIME],
p[A_CTIME])
def stat(self, path):
if (path == "/"):
p = {A_TYPE:T_DIR, A_UID:0, A_GID:0, A_SIZE:4096, A_MODE:16877, A_CTIME:time.time()}
else:
p = self.getfile(path)
p = self.getfile(path, follow_symlinks=follow_symlinks)
if (p == False):
raise OSError(errno.ENOENT, os.strerror(errno.ENOENT))
@ -392,9 +428,9 @@ class HoneyPotFilesystem(object):
def update_size(self, filename, size):
f = self.getfile(filename)
if (f == False):
if f == False:
return
if (f[A_TYPE] != T_FILE):
if f[A_TYPE] != T_FILE:
return
f[A_SIZE] = size