burp-ui/burpui/misc/acl/basic.py
2023-03-19 15:13:01 +01:00

378 lines
14 KiB
Python

# -*- coding: utf8 -*-
from ...utils import NOTIF_ERROR, NOTIF_OK, NOTIF_WARN, __
from .interface import BUIaclLoader
from .meta import BUIaclGrant, meta_grants
class ACLloader(BUIaclLoader):
__doc__ = __("Uses the Burp-UI configuration file to load its rules.")
section = name = "BASIC:ACL"
priority = 100
def __init__(self, app=None):
"""See :func:`burpui.misc.acl.interface.BUIaclLoader.__init__`
:param app: Application context
:type app: :class:`burpui.engines.server.BUIServer`
"""
self.app = app
self.conf = self.app.conf
self.admins = ["admin"]
self.moderators = []
self._groups = {}
self._grants = {}
self.first_setup = True
self.moderator = {}
self._acl = meta_grants
self.conf_id = None
self.meta_id = meta_grants.id
meta_grants.register_backend(self.name, self)
self.load_acl(True)
def reload(self):
self.load_acl(True)
def load_acl(self, force=False):
if not force and self.conf_id:
if not self.conf.changed(self.conf_id):
return False
# our config changed or we were forced to reload our rules.
# if the meta_grants didn't change, we reset them
# if they changed, it means something else triggered a reset
if not meta_grants.changed(self.meta_id) and not self.first_setup:
meta_grants.reset(self.name)
self.first_setup = False
self.admins = ["admin"]
self.moderators = []
self._grants = {}
self.groups_def = {}
adms = []
mods = []
def is_empty(data):
return not data or data == [None]
if self.section in self.conf.options:
self.priority = self.conf.safe_get(
"priority", "integer", section=self.section, defaults=self.priority
)
adms = self.conf.safe_get("admin", "force_list", section=self.section)
mods = self.conf.safe_get("+moderator", "force_list", section=self.section)
default_moderator = None
if self.conf.get("STANDALONE"):
default_moderator = '{"agents": {"rw": "local"}}'
self.moderator = (
self.conf.safe_get(
"@moderator",
"force_string",
section=self.section,
defaults=default_moderator,
)
or {}
)
meta_grants.set_moderator_grants(self.moderator)
for opt in self.conf.options.get(self.section).keys():
if opt in ["admin", "+moderator", "priority", "@moderator"]:
continue
record = self.conf.safe_get(opt, "force_string", section=self.section)
self.logger.debug("record: {} -> {}".format(opt, record))
def _record(key):
if gname not in self.groups_def:
self.groups_def[gname] = {}
self.groups_def[gname][key] = parsed
return parsed
if opt[0] == "+":
short = opt.lstrip("+")
gname = "@{}".format(short)
parsed = meta_grants.set_group(gname, record)
self._groups[short] = parsed
_record("members")
elif opt[0] == "@":
short = opt.lstrip("@")
if short not in self._groups:
self._groups[short] = []
gname = opt
parsed = record
_record("grants")
meta_grants.set_grant(gname, parsed)
else:
self._grants[opt] = BUIaclGrant(opt, record).grants
meta_grants.set_grant(opt, record)
if not is_empty(adms):
self.admins = adms
if not is_empty(mods):
self.moderators = mods
meta_grants.set_admin(self.admins)
meta_grants.set_moderator(self.moderators)
self.logger.debug("admins: {}".format(self.admins))
self.logger.debug("moderators: {}".format(self.moderators))
self.logger.debug("moderator grants: {}".format(self.moderator))
self.logger.debug("groups: {}".format(self.groups_def))
self.conf_id = self.conf.id
self.meta_id = meta_grants.id
return True
def _setup_acl(self):
"""Setup ACL management"""
if not self.conf.lookup_section(self.section):
self.conf._refresh()
def add_grant(self, name, content):
"""Add a grant"""
if name[0] in ["+", "@"]:
message = "'{}' is not a valid grant name".format(name)
self.logger.error(message)
return False, message, NOTIF_ERROR
self._setup_acl()
if name in self.conf.options[self.section]:
message = "grant '{}' already exists".format(name)
self.logger.warning(message)
return False, message, NOTIF_WARN
self.conf.options[self.section][name] = content
self.conf.options.write()
self.load_acl(True)
message = "grant '{}' successfully added".format(name)
return True, message, NOTIF_OK
def del_grant(self, name):
"""Delete a grant"""
if name[0] in ["+", "@"]:
message = "'{}' is not a valid grant name".format(name)
self.logger.error(message)
return False, message, NOTIF_ERROR
self._setup_acl()
self.load_acl(True)
if name not in self.conf.options[self.section]:
message = "grant '{}' does not exist".format(name)
self.logger.error(message)
return False, message, NOTIF_ERROR
del self.conf.options[self.section][name]
self.conf.options.write()
self.load_acl(True)
if name in self.admins:
self.del_admin(name)
if name in self.moderators:
self.del_moderator(name)
for group, members in self._groups.items():
if name in members:
self.del_group_member(group, name)
message = "grant '{}' successfully removed".format(name)
return True, message, NOTIF_OK
def mod_grant(self, name, content):
"""Update a grant"""
if name[0] in ["+", "@"]:
message = "'{}' is not a valid grant name".format(name)
self.logger.error(message)
return False, message, NOTIF_ERROR
self._setup_acl()
self.load_acl(True)
if name not in self.conf.options[self.section]:
message = "grant '{}' does not exist".format(name)
self.logger.error(message)
return False, message, NOTIF_WARN
self.conf.options[self.section][name] = content
self.conf.options.write()
self.load_acl(True)
message = "grant '{}' successfully modified".format(name)
return True, message, NOTIF_OK
def add_group(self, name, content):
"""Create a group"""
self._setup_acl()
name = "@{}".format(name)
if name == "moderator":
message = "'moderator' is a reserved name"
self.logger.error(message)
return False, message, NOTIF_ERROR
if name in self.conf.options[self.section]:
message = "group '{}' already exists".format(name)
self.logger.warning(message)
return False, message, NOTIF_WARN
self.conf.options[self.section][name] = content
self.conf.options.write()
self.load_acl(True)
message = "group '{}' successfully added".format(name)
return True, message, NOTIF_OK
def del_group(self, name):
"""Delete a group"""
self._setup_acl()
self.load_acl(True)
gname = "@{}".format(name)
if name == "moderator":
message = "'moderator' is a reserved name"
self.logger.error(message)
return False, message, NOTIF_ERROR
if gname not in self.conf.options[self.section]:
message = "group '{}' does not exist".format(name)
self.logger.error(message)
return False, message, NOTIF_ERROR
del self.conf.options[self.section][gname]
gmembers = "+{}".format(name)
if gmembers in self.conf.options[self.section]:
del self.conf.options[self.section][gmembers]
self.conf.options.write()
self.load_acl(True)
if gname in self.admins:
self.del_admin(gname)
if gname in self.moderators:
self.del_moderator(gname)
for group, members in self._groups.items():
if gname in members:
self.del_group_member(group, gname)
message = "grant '{}' successfully removed".format(name)
return True, message, NOTIF_OK
def mod_group(self, name, content):
"""Update a group"""
self._setup_acl()
name = "@{}".format(name)
if name == "moderator":
message = "'moderator' is a reserved name"
self.logger.error(message)
return False, message, NOTIF_ERROR
if name not in self.conf.options[self.section]:
message = "group '{}' does not exist".format(name)
self.logger.warning(message)
return False, message, NOTIF_WARN
self.conf.options[self.section][name] = content
self.conf.options.write()
self.load_acl(True)
message = "group '{}' successfully modified".format(name)
return True, message, NOTIF_OK
def add_group_member(self, group, member):
"""Add a user to a group"""
if group not in self._groups:
message = "group '{}' does not exist".format(group)
self.logger.warning(message)
return False, message, NOTIF_WARN
if member in self._groups[group]:
message = "'{}' already in group '{}'".format(member, group)
self.logger.warning(message)
return False, message, NOTIF_WARN
self._setup_acl()
self._groups[group].append(member)
gmembers = "+{}".format(group)
self.conf.options[self.section][gmembers] = self._groups[group]
self.conf.options.write()
self.load_acl(True)
message = "'{}' added to group '{}'".format(member, group)
return True, message, NOTIF_OK
def del_group_member(self, group, member):
"""Remove a user from a group"""
if group not in self._groups:
message = "group '{}' does not exist".format(group)
self.logger.warning(message)
return False, message, NOTIF_WARN
if member not in self._groups[group]:
message = "'{}' not in group '{}'".format(member, group)
self.logger.warning(message)
return False, message, NOTIF_WARN
self._setup_acl()
self._groups[group].remove(member)
gmembers = "+{}".format(group)
self.conf.options[self.section][gmembers] = self._groups[group] or ""
self.conf.options.write()
self.load_acl(True)
message = "'{}' removed from group '{}'".format(member, group)
return True, message, NOTIF_OK
def add_moderator(self, member):
"""Add a moderator"""
if member in self.moderators:
message = "'{}' is already a moderator".format(member)
self.logger.warning(message)
return False, message, NOTIF_WARN
self._setup_acl()
self.moderators.append(member)
self.conf.options[self.section]["+moderator"] = self.moderators
self.conf.options.write()
self.load_acl(True)
message = "'{}' successfully added as moderator".format(member)
return True, message, NOTIF_OK
def del_moderator(self, member):
"""Delete a moderator"""
if member not in self.moderators:
message = "'{}' is not a moderator".format(member)
self.logger.warning(message)
return False, message, NOTIF_WARN
self._setup_acl()
self.moderators.remove(member)
self.conf.options[self.section]["+moderator"] = self.moderators or ""
self.conf.options.write()
self.load_acl(True)
message = "'{}' successfully removed from moderators".format(member)
return True, message, NOTIF_OK
def mod_moderator(self, grants):
"""Update moderator grants"""
self._setup_acl()
self.moderator = grants
self.conf.options[self.section]["@moderator"] = grants
self.conf.options.write()
self.load_acl(True)
message = "moderator grants updated"
return True, message, NOTIF_OK
def add_admin(self, member):
"""Add an admin"""
if member in self.admins:
message = "'{}' is already an admin".format(member)
self.logger.warning(message)
return False, message, NOTIF_WARN
self._setup_acl()
self.admins.append(member)
self.conf.options[self.section]["admin"] = self.admins
self.conf.options.write()
self.load_acl(True)
message = "'{}' successfully added as admin".format(member)
return True, message, NOTIF_OK
def del_admin(self, member):
"""Delete an admin"""
if member not in self.admins:
message = "'{}' is not an admin".format(member)
self.logger.warning(message)
return False, message, NOTIF_WARN
self._setup_acl()
self.admins.remove(member)
self.conf.options[self.section]["admin"] = self.admins or ""
self.conf.options.write()
self.load_acl(True)
message = "'{}' successfully removed from admins".format(member)
return True, message, NOTIF_OK
@property
def acl(self):
"""Property to retrieve the backend"""
if self._acl:
self.load_acl()
return self._acl
return None # pragma: no cover
@property
def grants(self):
"""Property to retrieve the list of grants"""
return self._grants
@property
def groups(self):
"""Property to retrieve the list of groups with their members"""
return self.groups_def