diff options
-rw-r--r-- | src/msec/config.py | 46 | ||||
-rwxr-xr-x | src/msec/msec.py | 7 | ||||
-rwxr-xr-x | src/msec/msecperms.py | 81 |
3 files changed, 87 insertions, 47 deletions
diff --git a/src/msec/config.py b/src/msec/config.py index a6a9d12..4e300a4 100644 --- a/src/msec/config.py +++ b/src/msec/config.py @@ -140,6 +140,13 @@ def load_default_perms(log, level, root=''): config.load() return config +def merge_with_baselevel(log, config, base_level, load_func, root=''): + """Merges a config with its base level""" + # reloading levelconf for base level + levelconf = load_func(log, base_level, root=root) + config.merge(levelconf) + + # {{{ MsecConfig class MsecConfig: """Msec configuration parser""" @@ -148,6 +155,7 @@ class MsecConfig: self.options = {} self.comments = [] self.log = log + self.base_level = None def merge(self, newconfig, overwrite=False): """Merges parameters from newconfig to current config""" @@ -164,6 +172,13 @@ class MsecConfig: del self.comments self.comments = [] + def get_base_level(self, base_level=None): + """Configures base level for current level, so the settings could be pulled from it""" + if not base_level: + base_level = self.get('BASE_LEVEL') + self.base_level = base_level + return self.base_level + def load(self): """Loads and parses configuration file""" if not self.config: @@ -200,7 +215,7 @@ class MsecConfig: def remove(self, option): """Removes a configuration option.""" if option in self.options: - del self.options[option] + self.options[option]=None def set(self, option, value): """Sets a configuration option""" @@ -213,8 +228,8 @@ class MsecConfig: sortedparams.sort() return sortedparams - def save(self): - """Saves configuration. Comments go on top""" + def save(self, base_level=None): + """Saves configuration. Comments go on top. If a variable is present in base_level, and it is identical to the one to be saved, it is skipped""" if not self.config: # No associated file return True @@ -228,6 +243,12 @@ class MsecConfig: # sorting keys for option in self.list_options(): value = self.options[option] + # is it already on base level? + if base_level: + if option in base_level.options and option != "BASE_LEVEL": + if value == base_level.get(option): + self.log.debug("Option %s=%s already on base level!" % (option, value)) + continue # prevent saving empty options # TODO: integrate with remove() if value == None or value == OPTION_DISABLED: @@ -395,14 +416,20 @@ class PermConfig(MsecConfig): """Sorts and returns configuration parameters""" return self.options_order + def get(self, option, default=None): + """Gets a configuration option, or defines it if not defined""" + if option not in self.options: + self.set(option, default) + return self.options[option] + def set(self, option, value): """Sets a configuration option""" self.options[option] = value if option not in self.options_order: self.options_order.append(option) - def save(self): - """Saves configuration. Comments go on top""" + def save(self, base_level=None): + """Saves configuration. Comments go on top. If a variable is present in base_level, and it is identical to the one to be saved, it is skipped""" try: fd = open(self.config, "w") except: @@ -412,7 +439,14 @@ class PermConfig(MsecConfig): print >>fd, comment # sorting keys for file in self.options_order: - user, group, perm, force = self.options[file] + value = self.options[file] + if base_level: + if file in base_level.options: + new_value = base_level.get(file) + if value == new_value: + self.log.debug("Option %s=%s already on base level!" % (file, value)) + continue + user, group, perm, force = value if force: force = "\tforce" else: diff --git a/src/msec/msec.py b/src/msec/msec.py index c1cc75b..8a87c64 100755 --- a/src/msec/msec.py +++ b/src/msec/msec.py @@ -143,13 +143,16 @@ if __name__ == "__main__": else: msec_config.load() + # load variables from base level + config.merge_with_baselevel(log, msec_config, msec_config.get_base_level(), config.load_defaults, root='') + # saving current setting as new level if save: newlevel = config.MsecConfig(log, config=config.SECURITY_LEVEL % (root, level)) newlevel.merge(msec_config, overwrite=True) # update new level name newlevel.set("BASE_LEVEL", level) - newlevel.save() + newlevel.save(levelconf) sys.exit(0) # load the msec library @@ -161,6 +164,6 @@ if __name__ == "__main__": msec.commit(commit) # saving updated config if force_level and commit: - if not msec_config.save(): + if not msec_config.save(levelconf): log.error(_("Unable to save config!")) sys.exit(0) diff --git a/src/msec/msecperms.py b/src/msec/msecperms.py index 988be40..ba50181 100755 --- a/src/msec/msecperms.py +++ b/src/msec/msecperms.py @@ -49,7 +49,7 @@ If no paths to check are specified, all permissions stored in Otherwise, only the enties in the list of paths are expanded and checked. For example: - drakperms '/tmp/*' '/etc/*' + msecperms '/tmp/*' '/etc/*' will cover only files which are covered by '/tmp/*' and '/etc/*' rules of %s. @@ -57,31 +57,27 @@ Available parameters: -h, --help displays this helpful message. -l, --level <level> displays configuration for specified security level. - -f, --force <level> force new level, overwriting user settings. - -e, --enforce <level> enforce permissions on all files. + -e, --enforce enforce permissions on all files. -d enable debugging messages. -p, --pretend only pretend to change the level, perform no real actions. Use this to see what operations msec will perform. -r, --root <path> path to use as root -q, --quiet run quietly - -s, --save <level> save current configuration as a new security level """ % (version, config.PERMCONF, config.PERMCONF) # }}} if __name__ == "__main__": # default options log_level = logging.INFO - force_level = False commit = True enforce = False quiet = False root = '' - save = False # parse command line try: - opt, args = getopt.getopt(sys.argv[1:], 'hel:f:dpr:qs:', ['help', 'enforce', 'list=', 'force=', 'debug', 'pretend', 'root=', 'quiet', 'save=']) + opt, args = getopt.getopt(sys.argv[1:], 'hel=dpr:q', ['help', 'enforce', 'list=', 'debug', 'pretend', 'root=', 'quiet']) except getopt.error: usage() sys.exit(1) @@ -105,14 +101,6 @@ if __name__ == "__main__": print "!! forcing permissions on %s" % file print "%s: %s.%s perm %s" % (file, user, group, perm) sys.exit(0) - # force new level - elif o[0] == '-f' or o[0] == '--force': - level = o[1] - force_level = True - # save as new security level - elif o[0] == '-s' or o[0] == '--save': - level = o[1] - save = True # debugging elif o[0] == '-d' or o[0] == '--debug': log_level = logging.DEBUG @@ -144,40 +132,55 @@ if __name__ == "__main__": log_level = logging.WARN log = Log(log_path="%s%s" % (root, config.SECURITYLOG), interactive=True, log_syslog=False, log_level=log_level, quiet=quiet) + # loading msec config + msec_config = config.MsecConfig(log, config="%s%s" % (root, config.SECURITYCONF)) + msec_config.load() + # find out the base level + base_level = msec_config.get_base_level() # loading permissions permconf = config.PermConfig(log, config="%s%s" % (root, config.PERMCONF)) - - # forcing new level - if force_level: - # first load the default configuration for level - standard_permconf = config.load_default_perms(log, level, root=root) - params = standard_permconf.list_options() - if not params: - log.error(_("Level '%s' not found, aborting.") % level) - sys.exit(1) - log.info(_("Switching to '%s' level.") % level) - permconf.reset() - permconf.merge(standard_permconf, overwrite=True) - else: - permconf.load() - - # saving current setting as new level - if save: - newlevel = config.PermConfig(log, config=config.PERMISSIONS_LEVEL % (root, level)) - newlevel.merge(permconf, overwrite=True) - newlevel.save() - sys.exit(0) + permconf.load() + + # TODO: move to main msec + ## forcing new level + #if force_level: + # # first load the default configuration for level + # standard_permconf = config.load_default_perms(log, level, root=root) + # params = standard_permconf.list_options() + # if not params: + # log.error(_("Level '%s' not found, aborting.") % level) + # sys.exit(1) + # log.info(_("Switching to '%s' level.") % level) + # # updating base level + # base_level = msec_config.get_base_level(level) + # permconf.reset() + # permconf.merge(standard_permconf, overwrite=True) + #else: + # permconf.load() + + # load variables from base level + config.merge_with_baselevel(log, permconf, base_level, config.load_default_perms, root='') + + # reloading levelconf for base level + levelconf = config.load_default_perms(log, base_level, root=root) + + # TODO: move to main msec + ## saving current setting as new level + #if save: + # newlevel = config.PermConfig(log, config=config.PERMISSIONS_LEVEL % (root, level)) + # newlevel.merge(permconf, overwrite=True) + # newlevel.save(levelconf) + # sys.exit(0) # load the main permission class perm = PERMS(log, root=root) - # check permissions changed_files = perm.check_perms(permconf, files_to_check=args) # writing back changes perm.commit(really_commit=commit, enforce=enforce) # saving updated config - if force_level and commit: - if not permconf.save(): + if commit: + if not permconf.save(levelconf): log.error(_("Unable to save config!")) sys.exit(0) |