Example #1
0
    def setUp(self, nick='test', forceSetup=False):
        if not forceSetup and \
                self.__class__ in (PluginTestCase, ChannelPluginTestCase):
            # Necessary because there's a test in here that shouldn\'t run.
            return
        SupyTestCase.setUp(self)
        # Just in case, let's do this.  Too many people forget to call their
        # super methods.
        for irc in world.ircs[:]:
            irc._reallyDie()
        # Set conf variables appropriately.
        conf.supybot.reply.whenAddressedBy.chars.setValue('@')
        conf.supybot.reply.error.detailed.setValue(True)
        conf.supybot.reply.whenNotCommand.setValue(True)
        self.myVerbose = world.myVerbose

        def rmFiles(dir):
            for filename in os.listdir(dir):
                file = os.path.join(dir, filename)
                if os.path.isfile(file):
                    os.remove(file)
                else:
                    shutil.rmtree(file)

        if self.cleanConfDir:
            rmFiles(conf.supybot.directories.conf())
        if self.cleanDataDir:
            rmFiles(conf.supybot.directories.data())
        ircdb.users.reload()
        ircdb.ignores.reload()
        ircdb.channels.reload()
        if self.plugins is None:
            raise ValueError, 'PluginTestCase must have a "plugins" attribute.'
        self.nick = nick
        self.prefix = ircutils.joinHostmask(nick, 'user', 'host.domain.tld')
        self.irc = getTestIrc()
        MiscModule = plugin.loadPluginModule('Misc')
        OwnerModule = plugin.loadPluginModule('Owner')
        ConfigModule = plugin.loadPluginModule('Config')
        _ = plugin.loadPluginClass(self.irc, MiscModule)
        _ = plugin.loadPluginClass(self.irc, OwnerModule)
        _ = plugin.loadPluginClass(self.irc, ConfigModule)
        if isinstance(self.plugins, str):
            self.plugins = [self.plugins]
        else:
            for name in self.plugins:
                if name not in ('Owner', 'Misc', 'Config'):
                    module = plugin.loadPluginModule(name,
                                                     ignoreDeprecation=True)
                    cb = plugin.loadPluginClass(self.irc, module)
        self.irc.addCallback(TestInstance)
        for (name, value) in self.config.iteritems():
            group = conf.supybot
            parts = registry.split(name)
            if parts[0] == 'supybot':
                parts.pop(0)
            for part in parts:
                group = group.get(part)
            self.originals[group] = group()
            group.setValue(value)
Example #2
0
 def __init__(self, irc=None):
     if irc is not None:
         assert not irc.getCallback(self.name())
     self.__parent = super(Owner, self)
     self.__parent.__init__(irc)
     # Setup command flood detection.
     self.commands = ircutils.FloodQueue(
         conf.supybot.abuse.flood.interval())
     conf.supybot.abuse.flood.interval.addCallback(
         self.setFloodQueueTimeout)
     # Setup plugins and default plugins for commands.
     #
     # This needs to be done before we connect to any networks so that the
     # children of supybot.plugins (the actual plugins) exist and can be
     # loaded.
     for (name, s) in registry._cache.items():
         if 'alwaysLoadDefault' in name or 'alwaysLoadImportant' in name:
             continue
         if name.startswith('supybot.plugins'):
             try:
                 (_, _, name) = registry.split(name)
             except ValueError:  # unpack list of wrong size.
                 continue
             # This is just for the prettiness of the configuration file.
             # There are no plugins that are all-lowercase, so we'll at
             # least attempt to capitalize them.
             if name == name.lower():
                 name = name.capitalize()
             conf.registerPlugin(name)
         if name.startswith('supybot.commands.defaultPlugins'):
             try:
                 (_, _, _, name) = registry.split(name)
             except ValueError:  # unpack list of wrong size.
                 continue
             registerDefaultPlugin(name, s)
     # Setup Irc objects, connected to networks.  If world.ircs is already
     # populated, chances are that we're being reloaded, so don't do this.
     if not world.ircs:
         for network in conf.supybot.networks():
             try:
                 self._connect(network)
             except socket.error as e:
                 self.log.error('Could not connect to %s: %s.', network, e)
             except Exception as e:
                 self.log.exception('Exception connecting to %s:', network)
                 self.log.error('Could not connect to %s: %s.', network, e)
Example #3
0
 def setUp(self, nick='test', forceSetup=False):
     if not forceSetup and \
             self.__class__ in (PluginTestCase, ChannelPluginTestCase):
         # Necessary because there's a test in here that shouldn\'t run.
         return
     SupyTestCase.setUp(self)
     # Just in case, let's do this.  Too many people forget to call their
     # super methods.
     for irc in world.ircs[:]:
         irc._reallyDie()
     # Set conf variables appropriately.
     conf.supybot.reply.whenAddressedBy.chars.setValue('@')
     conf.supybot.reply.error.detailed.setValue(True)
     conf.supybot.reply.whenNotCommand.setValue(True)
     self.myVerbose = world.myVerbose
     def rmFiles(dir):
         for filename in os.listdir(dir):
             file = os.path.join(dir, filename)
             if os.path.isfile(file):
                 os.remove(file)
             else:
                 shutil.rmtree(file)
     if self.cleanConfDir:
         rmFiles(conf.supybot.directories.conf())
     if self.cleanDataDir:
         rmFiles(conf.supybot.directories.data())
     ircdb.users.reload()
     ircdb.ignores.reload()
     ircdb.channels.reload()
     if self.plugins is None:
         raise ValueError, 'PluginTestCase must have a "plugins" attribute.'
     self.nick = nick
     self.prefix = ircutils.joinHostmask(nick, 'user', 'host.domain.tld')
     self.irc = getTestIrc()
     MiscModule = plugin.loadPluginModule('Misc')
     OwnerModule = plugin.loadPluginModule('Owner')
     ConfigModule = plugin.loadPluginModule('Config')
     _ = plugin.loadPluginClass(self.irc, MiscModule)
     _ = plugin.loadPluginClass(self.irc, OwnerModule)
     _ = plugin.loadPluginClass(self.irc, ConfigModule)
     if isinstance(self.plugins, str):
         self.plugins = [self.plugins]
     else:
         for name in self.plugins:
             if name not in ('Owner', 'Misc', 'Config'):
                 module = plugin.loadPluginModule(name,
                                                  ignoreDeprecation=True)
                 cb = plugin.loadPluginClass(self.irc, module)
     self.irc.addCallback(TestInstance)
     for (name, value) in self.config.iteritems():
         group = conf.supybot
         parts = registry.split(name)
         if parts[0] == 'supybot':
             parts.pop(0)
         for part in parts:
             group = group.get(part)
         self.originals[group] = group()
         group.setValue(value)
Example #4
0
 def __init__(self, irc=None):
     if irc is not None:
         assert not irc.getCallback(self.name())
     self.__parent = super(Owner, self)
     self.__parent.__init__(irc)
     # Setup log object/command.
     self.log = LogProxy(self.log)
     # Setup command flood detection.
     self.commands = ircutils.FloodQueue(60)
     # Setup plugins and default plugins for commands.
     #
     # This needs to be done before we connect to any networks so that the
     # children of supybot.plugins (the actual plugins) exist and can be
     # loaded.
     for (name, s) in registry._cache.iteritems():
         if 'alwaysLoadDefault' in name or 'alwaysLoadImportant' in name:
             continue
         if name.startswith('supybot.plugins'):
             try:
                 (_, _, name) = registry.split(name)
             except ValueError: # unpack list of wrong size.
                 continue
             # This is just for the prettiness of the configuration file.
             # There are no plugins that are all-lowercase, so we'll at
             # least attempt to capitalize them.
             if name == name.lower():
                 name = name.capitalize()
             conf.registerPlugin(name)
         if name.startswith('supybot.commands.defaultPlugins'):
             try:
                 (_, _, _, name) = registry.split(name)
             except ValueError: # unpack list of wrong size.
                 continue
             registerDefaultPlugin(name, s)
     # Setup Irc objects, connected to networks.  If world.ircs is already
     # populated, chances are that we're being reloaded, so don't do this.
     if not world.ircs:
         for network in conf.supybot.networks():
             try:
                 self._connect(network)
             except socket.error, e:
                 self.log.error('Could not connect to %s: %s.', network, e)
             except Exception, e:
                 self.log.exception('Exception connecting to %s:', network)
                 self.log.error('Could not connect to %s: %s.', network, e)
Example #5
0
 def __init__(self, irc):
     self.__parent = super(Alias, self)
     self.__parent.__init__(irc)
     # Schema: {alias: [command, locked, commandMethod]}
     self.aliases = {}
     # XXX This should go.  aliases should be a space separate list, etc.
     group = conf.supybot.plugins.Alias.aliases
     group2 = conf.supybot.plugins.Alias.escapedaliases
     prefixLen = len(registry.split('supybot.plugins.alias.aliases'))
     for (name, alias) in registry._cache.items():
         name = name.lower()
         nameSplit = registry.split(name)
         if len(nameSplit) > prefixLen + 1:
             continue
         if name.startswith('supybot.plugins.alias.aliases.'):
             name = nameSplit[-1]
             conf.registerGlobalValue(group, name, registry.String('', ''))
             conf.registerGlobalValue(group.get(name), 'locked',
                                      registry.Boolean(False, ''))
         elif name.startswith('supybot.plugins.alias.escapedaliases.'):
             name = nameSplit[-1]
             conf.registerGlobalValue(group2, name, registry.String('', ''))
             conf.registerGlobalValue(group2.get(name), 'locked',
                                      registry.Boolean(False, ''))
     for (name, value) in group.getValues(fullNames=False):
         name = name.lower()  # Just in case.
         command = value()
         locked = value.locked()
         self.aliases[name] = [command, locked, None]
     for (name, value) in group2.getValues(fullNames=False):
         name = name.lower()  # Just in case.
         command = value()
         locked = value.locked()
         self.aliases[unescapeAlias(name)] = [command, locked, None]
     for (alias, (command, locked, _)) in self.aliases.copy().items():
         try:
             self.addAlias(irc, alias, command, locked)
         except Exception as e:
             self.log.exception(
                 'Exception when trying to add alias %s.  '
                 'Removing from the Alias database.', alias)
             del self.aliases[alias]
Example #6
0
 def __init__(self, irc):
     self.__parent = super(Alias, self)
     self.__parent.__init__(irc)
     # Schema: {alias: [command, locked, commandMethod]}
     self.aliases = {}
     # XXX This should go.  aliases should be a space separate list, etc.
     group = conf.supybot.plugins.Alias.aliases
     group2 = conf.supybot.plugins.Alias.escapedaliases
     prefixLen = len(registry.split('supybot.plugins.alias.aliases'))
     for (name, alias) in registry._cache.items():
         name = name.lower()
         nameSplit = registry.split(name)
         if len(nameSplit) > prefixLen+1:
             continue
         if name.startswith('supybot.plugins.alias.aliases.'):
             name = nameSplit[-1]
             conf.registerGlobalValue(group, name, registry.String('', ''))
             conf.registerGlobalValue(group.get(name), 'locked',
                                      registry.Boolean(False, ''))
         elif name.startswith('supybot.plugins.alias.escapedaliases.'):
             name = nameSplit[-1]
             conf.registerGlobalValue(group2, name,
                     registry.String('', ''))
             conf.registerGlobalValue(group2.get(name),
                 'locked', registry.Boolean(False, ''))
     for (name, value) in group.getValues(fullNames=False):
         name = name.lower() # Just in case.
         command = value()
         locked = value.locked()
         self.aliases[name] = [command, locked, None]
     for (name, value) in group2.getValues(fullNames=False):
         name = name.lower() # Just in case.
         command = value()
         locked = value.locked()
         self.aliases[unescapeAlias(name)] = [command, locked, None]
     for (alias, (command, locked, _)) in self.aliases.copy().items():
         try:
             self.addAlias(irc, alias, command, locked)
         except Exception as e:
             self.log.exception('Exception when trying to add alias %s.  '
                                'Removing from the Alias database.', alias)
             del self.aliases[alias]
Example #7
0
def getCapability(name):
    capability = 'owner'  # Default to requiring the owner capability.
    parts = registry.split(name)
    while parts:
        part = parts.pop()
        if ircutils.isChannel(part):
            # If a registry value has a channel in it, it requires a channel.op
            # capability, or so we assume.  We'll see if we're proven wrong.
            capability = ircdb.makeChannelCapability(part, 'op')
        ### Do more later, for specific capabilities/sections.
    return capability
Example #8
0
def getCapability(name):
    capability = 'owner' # Default to requiring the owner capability.
    parts = registry.split(name)
    while parts:
        part = parts.pop()
        if ircutils.isChannel(part):
            # If a registry value has a channel in it, it requires a channel.op
            # capability, or so we assume.  We'll see if we're proven wrong.
            capability = ircdb.makeChannelCapability(part, 'op')
        ### Do more later, for specific capabilities/sections.
    return capability
Example #9
0
def registerChannelValue(group, name, value):
    value._supplyDefault = True
    value.channelValue = True
    g = group.register(name, value)
    gname = g._name.lower()
    for name in registry._cache.iterkeys():
        if name.lower().startswith(gname) and len(gname) < len(name):
            name = name[len(gname) + 1:]  # +1 for .
            parts = registry.split(name)
            if len(parts) == 1 and parts[0] and ircutils.isChannel(parts[0]):
                # This gets the channel values so they always persist.
                g.get(parts[0])()
Example #10
0
def registerChannelValue(group, name, value):
    value._supplyDefault = True
    value.channelValue = True
    g = group.register(name, value)
    gname = g._name.lower()
    for name in registry._cache.iterkeys():
        if name.lower().startswith(gname) and len(gname) < len(name):
            name = name[len(gname)+1:] # +1 for .
            parts = registry.split(name)
            if len(parts) == 1 and parts[0] and ircutils.isChannel(parts[0]):
                # This gets the channel values so they always persist.
                g.get(parts[0])()
Example #11
0
def getWrapper(name):
    parts = registry.split(name)
    if not parts or parts[0] not in ('supybot', 'users'):
        raise registry.InvalidRegistryName(name)
    group = getattr(conf, parts.pop(0))
    while parts:
        try:
            group = group.get(parts.pop(0))
        # We'll catch registry.InvalidRegistryName and re-raise it here so
        # that we have a useful error message for the user.
        except (registry.NonExistentRegistryEntry,
                registry.InvalidRegistryName):
            raise registry.InvalidRegistryName(name)
    return group
Example #12
0
def getWrapper(name):
    parts = registry.split(name)
    if not parts or parts[0] not in ('supybot', 'users'):
        raise InvalidRegistryName, name
    group = getattr(conf, parts.pop(0))
    while parts:
        try:
            group = group.get(parts.pop(0))
        # We'll catch registry.InvalidRegistryName and re-raise it here so
        # that we have a useful error message for the user.
        except (registry.NonExistentRegistryEntry,
                registry.InvalidRegistryName):
            raise registry.InvalidRegistryName, name
    return group
Example #13
0
def getWrapper(name):
    parts = registry.split(name)
    if not parts or parts[0] not in ('supybot', 'users'):
        raise registry.InvalidRegistryName(name)
    group = getattr(conf, parts.pop(0))
    while parts:
        part = parts.pop(0)
        if group.__hasattr__(part):
            group = group.get(part)
        else:
            # We'll raise registry.InvalidRegistryName here so
            # that we have a useful error message for the user.
            raise registry.InvalidRegistryName(name)
    return group
Example #14
0
    def search(self, irc, msg, args, word):
        """<word>

        Searches for <word> in the current configuration variables.
        """
        L = []
        for (name, x) in conf.supybot.getValues(getChildren=True):
            if word in name.lower():
                possibleChannel = registry.split(name)[-1]
                if not ircutils.isChannel(possibleChannel):
                    L.append(name)
        if L:
            irc.reply(format('%L', L))
        else:
            irc.reply(_('There were no matching configuration variables.'))
Example #15
0
    def search(self, irc, msg, args, word):
        """<word>

        Searches for <word> in the current configuration variables.
        """
        L = []
        for (name, x) in conf.supybot.getValues(getChildren=True):
            if word in name.lower():
                possibleChannel = registry.split(name)[-1]
                if not ircutils.isChannel(possibleChannel):
                    L.append(name)
        if L:
            irc.reply(format('%L', L))
        else:
            irc.reply(_('There were no matching configuration variables.'))
Example #16
0
    def searchvalues(self, irc, msg, args, word):
        """<word>

        Searches for <word> in the values of current configuration variables.
        """
        L = []
        for (name, x) in conf.supybot.getValues(getChildren=True):
            if (hasattr(x, 'value')  # not a group
                    and word in str(x()).lower()):
                last_name_part = registry.split(name)[-1]
                L.append(name)
        if L:
            irc.reply(format('%L', L))
        else:
            irc.reply(_('There were no matching configuration variables.'))
Example #17
0
    def searchhelp(self, irc, msg, args, phrase):
        """<phrase>

        Searches for <phrase> in the help of current configuration variables.
        """
        L = []
        for (name, x) in conf.supybot.getValues(getChildren=True):
            if phrase in x.help().lower():
                last_name_part = registry.split(name)[-1]
                if not irc.isChannel(last_name_part) \
                        and not last_name_part.startswith(':'): # network
                    L.append(name)
        if L:
            irc.reply(format('%L', L))
        else:
            irc.reply(_('There were no matching configuration variables.'))
Example #18
0
def registryValue(plugin, name, channel=None, value=True):
    group = conf.supybot.plugins.get(plugin)
    names = registry.split(name)
    for name in names:
        group = group.get(name)
    if channel is not None:
        try:
            if ircutils.isChannel(channel):
                group = group.get(channel)
            else:
                log.debug('registryValue got channel=%r', channel)
        except registry.NonExistentRegistryEntry:
            log.debug('non existent registry entry %r for channel %r', name, channel)
            pass
    if value:
        return group()
    else:
        return group
Example #19
0
def getCapability(name):
    capability = 'owner' # Default to requiring the owner capability.
    if not name.startswith('supybot') and not name.startswith('users'):
        name = 'supybot.' + name
    parts = registry.split(name)
    group = getattr(conf, parts.pop(0))
    while parts:
        part = parts.pop(0)
        group = group.get(part)
        if not getattr(group, '_opSettable', True):
            return 'owner'
        if ircutils.isChannel(part):
            # If a registry value has a channel in it, it requires a
            # 'channel,op' capability, or so we assume.  We'll see if we're
            # proven wrong.
            capability = ircdb.makeChannelCapability(part, 'op')
        ### Do more later, for specific capabilities/sections.
    return capability
Example #20
0
def registryValue(plugin, name, channel=None, value=True):
    group = conf.supybot.plugins.get(plugin)
    names = registry.split(name)
    for name in names:
        group = group.get(name)
    if channel is not None:
        try:
            if ircutils.isChannel(channel):
                group = group.get(channel)
            else:
                log.debug('registryValue got channel=%r', channel)
        except registry.NonExistentRegistryEntry:
            log.debug('non existent registry entry %r for channel %r', name, channel)
            pass
    if value:
        return group()
    else:
        return group
Example #21
0
def isReadOnly(name):
    """Prevents changing certain config variables to gain shell access via
    a vulnerable IRC network."""
    parts = registry.split(name.lower())
    if parts[0] != 'supybot':
        parts.insert(0, 'supybot')
    if parts == ['supybot', 'commands', 'allowshell'] and \
            not conf.supybot.commands.allowShell():
        # allow setting supybot.commands.allowShell from True to False,
        # but not from False to True.
        # Otherwise an IRC network could overwrite it.
        return True
    elif parts[0:2] == ['supybot', 'directories'] and \
            not conf.supybot.commands.allowShell():
        # Setting plugins directory allows for arbitrary code execution if
        # an attacker can both use the IRC network to MITM and upload files
        # on the server (eg. with a web CMS).
        # Setting other directories allows writing data at arbitrary
        # locations.
        return True
    else:
        return False