Source code for sslscan.config

"""
A collection of classes to handle the configuration of a scanner or a module.
"""

import logging

from sslscan.exception import ConfigOptionNotFound, OptionValueError


logger = logging.getLogger(__name__)


[docs]class BaseConfig(object): """ The base config. All other configuration classes use it as base class. """ def __init__(self, options=None, parent=None): self._option_map = {} self._options = [] self._option_groups = [] self._parent = parent if options is not None: for name, args in options: if name is None: group = OptionGroup(options=args) self.add_option_group(group) else: self.add_option(name, **args)
[docs] def add_option(self, name, **kwargs): """ Add an option. :param String name: Name of the config option :param kwargs: Additional params are used for a new :class:`sslscan.config.Option` instance """ if name in self._option_map: return False kwargs["parent"] = self option = Option(name, **kwargs) self._option_map[name] = option if option.type == "bool" and option.negation is not None: self._option_map[option.negation] = name self._options.append(option)
[docs] def add_option_group(self, group): """ Add grouped options. :param group: Instance of :class:`sslscan.config.OptionGroup` :type group: :class:`sslscan.config.OptionGroup` """ option_map = group.get_option_map() for name in option_map.keys(): if name in self._option_map: return False self._option_map.update(option_map) group.set_parent(self) self._option_groups.append(group)
[docs] def get_option(self, name): """ Return an option. :param String name: The name of the option :return: The option or None if not found """ return self._option_map.get(name, None)
[docs] def get_option_map(self): """Return the option map""" return self._option_map
[docs] def get_option_names(self): """Return list of option names""" names = [option.name for option in self._options] return names
[docs] def get_parent(self): """ Return the parent config object or None if no parent is set. :return: Object or None """ return self._parent
[docs] def get_value(self, name, default=None): """ Get the value of an option. :param String name: Name of the option :param Mixed default: Default value :return: If found the value of the option or the default value """ option = self.get_option(name) if option is None: return None return option.get_value(default=default)
[docs] def set_parent(self, parent): """ Set the current parent config object. :param Object|None parent: Set or reset parent config object """ self._parent = parent
[docs] def set_value(self, name, value): """ Set the value of an option. :param String name: Name of the option :param Mixed value: The value of the option to set :return: False or True :rtype: Boolean """ logger.debug("Set value '%s' to '%r'", name, value) option = self._option_map.get(name, None) if option is None: raise ConfigOptionNotFound( name=name, value=value, ) negate = False if type(option) == str: option = self._option_map.get(option, None) negate = True if option is None: raise ConfigOptionNotFound( name=name, value=value, ) value = option.convert_value_type(value) if option.type == "bool" and negate is True: value = not value return option.set_value(value)
[docs] def set_values(self, data): """ Set the value of multiple options at once. :param date: The values to set :todo: Improve docs """ if isinstance(data, str): # ToDo: support escape characters data_parts = data.split(":") for option_data in data_parts: name, sep, value = option_data.partition("=") if name is None or name == "": return False negation = False option = self._option_map.get(name, None) if type(option) is str: negation = True option = self._option_map.get(option, None) if option is None: raise ConfigOptionNotFound( name=name, value=value, ) if option.type == "bool" and sep == "": value = not negation option.set_value(value) elif isinstance(data, dict): for name, value in data.items(): self.set_value(name, value)
[docs]class ModuleConfig(BaseConfig): """ Holds the config of a module :param module: The module this config is for """ def __init__(self, module=None, **kwargs): self._module = module BaseConfig.__init__(self, **kwargs)
[docs] def get_module(self): return self._module
[docs]class ScanConfig(BaseConfig): """Holds the config of a scanner instance""" def __init__(self, **kwargs): BaseConfig.__init__(self, **kwargs)
[docs]class Option(object): """ """ def __init__(self, name, action="store", default=None, help="", metavar="", type="string", values=None, negation=None, parent=None): self.name = name self.action = action self.default = default self.help = help self.metavar = metavar self.negation = negation self._parent = parent self.value = None if type == "choice" and values is None: values = {} self.values = values self.type = type
[docs] def convert_value_type(self, value): """ Tries to convert the value into the right type :param Mixed value: Value to convert :return: The value :rtype: Mixed """ if self.type == "bool": if type(value) == int: return bool(value) if type(value) != str: value = str(value) value = value.strip().lower() return value in ["1", "true", "yes", ""] if self.type == "int": return int(value) if self.type == "float": return float(value) return value
[docs] def get_parent(self): """ Return the parent config object or None if no parent is set. :return: Object or None """ return self._parent
[docs] def get_value(self, default=None): """ Get the value. :param Mixed default: Default value if value of option not set :return: The value or the default value :rtype: Mixed """ if self.value is not None: return self.value if default is not None: return default return self.default
[docs] def set_value(self, value): """ Set the value and returns True if it was successful or False if not. :param Mixed value: The value :raises sslscan.exception.OptionValueError: if types do not match """ logger.debug("Set value of option '%s' to '%r'", self.name, value) value = self.convert_value_type(value) if self.type == "choice": values = self.values if callable(values): values = values(self) if value not in values: raise OptionValueError(option=self, value=value) self.value = value return if self.action == "store": self.value = value return if self.action == "append": if type(self.value) is not list: self.value = [] self.value.append(value) return raise OptionValueError(option=self, value=value)
[docs]class OptionGroup(BaseConfig): """Used to group multiple options""" def __init__(self, label, help=None): BaseConfig.__init__(self) self.label = label self.help = help