From 902b0ce29e2c491fb534c3033aab37a3dfbb2272 Mon Sep 17 00:00:00 2001 From: desaster Date: Sat, 21 Nov 2009 11:51:23 +0000 Subject: [PATCH] move filesystem related stuff to core/fs.py git-svn-id: https://kippo.googlecode.com/svn/trunk@40 951d7100-d841-11de-b865-b3884708a8e2 --- commands/base.py | 2 +- commands/ls.py | 2 +- commands/tar.py | 20 ++++++-- commands/wget.py | 2 +- core/fs.py | 126 +++++++++++++++++++++++++++++++++++++++++++++++ core/fstypes.py | 22 --------- core/honeypot.py | 107 +--------------------------------------- 7 files changed, 146 insertions(+), 135 deletions(-) create mode 100644 core/fs.py delete mode 100644 core/fstypes.py diff --git a/commands/base.py b/commands/base.py index 52f19382..e1cf3526 100644 --- a/commands/base.py +++ b/commands/base.py @@ -3,7 +3,7 @@ import os, time from core.honeypot import HoneyPotCommand -from core.fstypes import * +from core.fs import * from twisted.internet import reactor import config diff --git a/commands/ls.py b/commands/ls.py index 6aee53f6..daba4b42 100644 --- a/commands/ls.py +++ b/commands/ls.py @@ -2,7 +2,7 @@ # See the COPYRIGHT file for more information from core.honeypot import HoneyPotCommand -from core.fstypes import * +from core.fs import * import stat, time commands = {} diff --git a/commands/tar.py b/commands/tar.py index 3d5777a2..c6e889d8 100644 --- a/commands/tar.py +++ b/commands/tar.py @@ -2,7 +2,7 @@ # See the COPYRIGHT file for more information from core.honeypot import HoneyPotCommand -from core.fstypes import * +from core.fs import * from commands import dice import time, random, tarfile, os @@ -26,7 +26,8 @@ class command_tar(HoneyPotCommand): path = self.fs.resolve_path(filename, self.honeypot.cwd) if not path or not self.honeypot.fs.exists(path): - self.writeln('tar: rs: Cannot open: No such file or directory') + self.writeln('tar: %s: Cannot open: No such file or directory' % \ + filename) self.writeln('tar: Error is not recoverable: exiting now') self.writeln('tar: Child returned status 2') self.writeln('tar: Error exit delayed from previous errors') @@ -34,9 +35,19 @@ class command_tar(HoneyPotCommand): f = self.fs.getfile(path) if not f[A_REALFILE]: + self.writeln('tar: this does not look like a tar archive') + self.writeln('tar: skipping to next header') + self.writeln('tar: error exit delayed from previous errors') + return + + try: + t = tarfile.open(f[A_REALFILE]) + except: + self.writeln('tar: this does not look like a tar archive') + self.writeln('tar: skipping to next header') + self.writeln('tar: error exit delayed from previous errors') return - t = tarfile.open(f[A_REALFILE]) for f in t: dest = self.fs.resolve_path(f.name.strip('/'), self.honeypot.cwd) if verbose: @@ -47,8 +58,7 @@ class command_tar(HoneyPotCommand): self.fs.mkdir(dest, 0, 0, 4096, f.mode, f.mtime) elif f.isfile(): self.fs.mkfile(dest, 0, 0, f.size, f.mode, f.mtime) - self.honeypot.commands[dest] = \ - random.choice(dice.clist) + self.honeypot.commands[dest] = random.choice(dice.clist) else: print 'tar: skipping [%s]' % f.name commands['/bin/tar'] = command_tar diff --git a/commands/wget.py b/commands/wget.py index 4e9c4349..3d162602 100644 --- a/commands/wget.py +++ b/commands/wget.py @@ -2,7 +2,7 @@ # See the COPYRIGHT file for more information from core.honeypot import HoneyPotCommand -from core.fstypes import * +from core.fs import * from twisted.web import client from twisted.internet import reactor import stat, time, urlparse, random, re diff --git a/core/fs.py b/core/fs.py new file mode 100644 index 00000000..f8234994 --- /dev/null +++ b/core/fs.py @@ -0,0 +1,126 @@ +# Copyright (c) 2009 Upi Tamminen +# See the COPYRIGHT file for more information + +import os, time + +A_NAME, \ + A_TYPE, \ + A_UID, \ + A_GID, \ + A_SIZE, \ + A_MODE, \ + A_CTIME, \ + A_CONTENTS, \ + A_TARGET, \ + A_REALFILE = range(0, 10) +T_LINK, \ + T_DIR, \ + T_FILE, \ + T_BLK, \ + T_CHR, \ + T_SOCK, \ + T_FIFO = range(0, 7) + +class HoneyPotFilesystem(object): + def __init__(self, fs): + self.fs = fs + + def resolve_path(self, path, cwd): + pieces = path.rstrip('/').split('/') + + if path[0] == '/': + cwd = [] + else: + cwd = [x for x in cwd.split('/') if len(x) and x is not None] + + while 1: + if not len(pieces): + break + piece = pieces.pop(0) + if piece == '..': + if len(cwd): cwd.pop() + continue + if piece in ('.', ''): + continue + cwd.append(piece) + + return '/%s' % '/'.join(cwd) + + def get_path(self, path): + p = self.fs + for i in path.split('/'): + if not i: + continue + p = [x for x in p[A_CONTENTS] if x[A_NAME] == i][0] + return p[A_CONTENTS] + + def list_files(self, path): + return self.get_path(path) + + def exists(self, path): + f = self.getfile(path) + 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 \ + f[A_SIZE] < 25000000: + print 'Updating realfile to %s' % realfile + f[A_REALFILE] = realfile + + def realfile(self, f, path): + self.update_realfile(f, path) + if f[A_REALFILE]: + return f[A_REALFILE] + return None + + def getfile(self, path): + pieces = path.strip('/').split('/') + p = self.fs + while 1: + if not len(pieces): + break + piece = pieces.pop(0) + 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] + return p + + def mkfile(self, path, uid, gid, size, mode, ctime = None): + if ctime is None: + ctime = time.time() + dir = self.get_path(os.path.dirname(path)) + outfile = os.path.basename(path) + if outfile in [x[A_NAME] for x in dir]: + dir.remove([x for x in dir if x[A_NAME] == outfile][0]) + dir.append([outfile, T_FILE, uid, gid, size, mode, ctime, [], + None, None]) + return True + + def mkdir(self, path, uid, gid, size, mode, ctime = None): + if ctime is None: + ctime = time.time() + if not len(path.strip('/')): + return False + try: + dir = self.get_path(os.path.dirname(path.strip('/'))) + except IndexError: + return False + dir.append([os.path.basename(path), T_DIR, uid, gid, size, mode, + ctime, [], None, None]) + return True + + def is_dir(self, path): + if path == '/': + return True + dir = self.get_path(os.path.dirname(path)) + l = [x for x in dir + if x[A_NAME] == os.path.basename(path) and + x[A_TYPE] == T_DIR] + if l: + return True + return False + +# vim: set sw=4 et: diff --git a/core/fstypes.py b/core/fstypes.py deleted file mode 100644 index 8038cbaa..00000000 --- a/core/fstypes.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2009 Upi Tamminen -# See the COPYRIGHT file for more information - -A_NAME, \ - A_TYPE, \ - A_UID, \ - A_GID, \ - A_SIZE, \ - A_MODE, \ - A_CTIME, \ - A_CONTENTS, \ - A_TARGET, \ - A_REALFILE = range(0, 10) -T_LINK, \ - T_DIR, \ - T_FILE, \ - T_BLK, \ - T_CHR, \ - T_SOCK, \ - T_FIFO = range(0, 7) - -# vim: set sw=4 et: diff --git a/core/honeypot.py b/core/honeypot.py index 67c6e0c7..445a0c1d 100644 --- a/core/honeypot.py +++ b/core/honeypot.py @@ -13,8 +13,7 @@ from zope.interface import implements from copy import deepcopy, copy import sys, os, random, pickle, time, stat, shlex -from core import ttylog -from core.fstypes import * +from core import ttylog, fs import commands, config class HoneyPotCommand(object): @@ -101,7 +100,7 @@ class HoneyPotProtocol(recvline.HistoricRecvLine): self.env = env self.cwd = '/root' self.hostname = config.fake_hostname - self.fs = HoneyPotFilesystem(deepcopy(self.env.fs)) + self.fs = fs.HoneyPotFilesystem(deepcopy(self.env.fs)) # commands is also a copy so we can add stuff on the fly self.commands = copy(self.env.commands) self.password_input = False @@ -226,108 +225,6 @@ class HoneyPotEnvironment(object): self.commands.update(module.commands) self.fs = pickle.load(file('fs.pickle')) -class HoneyPotFilesystem(object): - def __init__(self, fs): - self.fs = fs - - def resolve_path(self, path, cwd): - pieces = path.rstrip('/').split('/') - - if path[0] == '/': - cwd = [] - else: - cwd = [x for x in cwd.split('/') if len(x) and x is not None] - - while 1: - if not len(pieces): - break - piece = pieces.pop(0) - if piece == '..': - if len(cwd): cwd.pop() - continue - if piece in ('.', ''): - continue - cwd.append(piece) - - return '/%s' % '/'.join(cwd) - - def get_path(self, path): - p = self.fs - for i in path.split('/'): - if not i: - continue - p = [x for x in p[A_CONTENTS] if x[A_NAME] == i][0] - return p[A_CONTENTS] - - def list_files(self, path): - return self.get_path(path) - - def exists(self, path): - f = self.getfile(path) - 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 \ - f[A_SIZE] < 25000000: - print 'Updating realfile to %s' % realfile - f[A_REALFILE] = realfile - - def realfile(self, f, path): - self.update_realfile(f, path) - if f[A_REALFILE]: - return f[A_REALFILE] - return None - - def getfile(self, path): - pieces = path.strip('/').split('/') - p = self.fs - while 1: - if not len(pieces): - break - piece = pieces.pop(0) - 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] - return p - - def mkfile(self, path, uid, gid, size, mode, ctime = None): - if ctime is None: - ctime = time.time() - dir = self.get_path(os.path.dirname(path)) - outfile = os.path.basename(path) - if outfile in [x[A_NAME] for x in dir]: - dir.remove([x for x in dir if x[A_NAME] == outfile][0]) - dir.append([outfile, T_FILE, uid, gid, size, mode, ctime, [], - None, None]) - return True - - def mkdir(self, path, uid, gid, size, mode, ctime = None): - if ctime is None: - ctime = time.time() - if not len(path.strip('/')): - return False - try: - dir = self.get_path(os.path.dirname(path.strip('/'))) - except IndexError: - return False - dir.append([os.path.basename(path), T_DIR, uid, gid, size, mode, - ctime, [], None, None]) - return True - - def is_dir(self, path): - if path == '/': - return True - dir = self.get_path(os.path.dirname(path)) - l = [x for x in dir - if x[A_NAME] == os.path.basename(path) and - x[A_TYPE] == T_DIR] - if l: - return True - return False - class HoneyPotRealm: implements(portal.IRealm)