Ejemplo n.º 1
0
    def install_packages(packages):
        """ Install a package using system package manager

        This method is currently using os.system instead of
        subprocess.run or subprocess.Popen because subprocess
        doesn't seem to handle some of the TUIs well.
        """
        Avalon.warning(
            'If the installation is unsuccessful, you should consider updating the package manager cache',
            log=False)

        # Convert packages list into a string
        if len(packages) > 1:
            packages_string = ' '.join(packages)
        else:
            packages_string = packages[0]

        if shutil.which('apt-get'):
            return os.system(f'apt-get install {packages_string} -y')
        elif shutil.which('yum'):
            return os.system(f'yum install {packages_string} -y')
        elif shutil.which('pacman'):
            return os.system(f'pacman -S {packages_string} --noconfirm')
        else:
            Avalon.error(
                'Sorry, we can\'t find a package manager that we currently support. Aborting..'
            )
            Avalon.error('Currently Supported: apt, yum, pacman')
            return False
Ejemplo n.º 2
0
    def _setup_ufw(self):
        """ Enable UFW to controll the firewall
        """
        print(Avalon.FM.BD + '\nEnable UFW firewall?' + Avalon.FM.RST)
        print('Do you want SCUTUM to help configuring and enabling UFW firewall?')
        print('This may help preventing a lot of scanning and attacks')
        if Avalon.ask('Enable?', True):

            # If ufw is not installed
            if shutil.which('ufw') is None:
                if Avalon.ask('UFW is not installed. Install?', True):
                    Utilities.install_packages(['ufw'])
                else:
                    Avalon.warning('UFW package not available, disabling UFW')
                    self.config['Ufw']['handled'] = False
                    return

            ufwctrl = Ufw()
            print('SCUTUM can configure UFW Firewall for you')
            print('However this will reset your current UFW configurations')
            print('It is recommended to do so the first time you install SCUTUM')
            if Avalon.ask('Let SCUTUM configure UFW for you?', True):
                ufwctrl.initialize(True)
            else:
                Avalon.info('Okay. Then we will simply enable it for you')
                ufwctrl.enable()

            print('If you let SCUTUM handle UFW, then UFW will be activated and deactivated with SCUTUM')
            if Avalon.ask('Let SCUTUM handle UFW?', True):
                self.config['Ufw']['handled'] = True
            else:
                self.config['Ufw']['handled'] = False
        else:
            self.config['Ufw']['handled'] = False
            Avalon.info('You can turn it on whenever you change your mind')
Ejemplo n.º 3
0
 def install_wicd_scripts(self):
     """ Write scutum scripts for WICD
     """
     print(Avalon.FG.G + '[+] INFO: Installing for WICD' + Avalon.FM.RST + '.....', end='')
     if not os.path.isdir('/etc/wicd/'):
         print(Avalon.FG.R + Avalon.FM.BD + 'ERROR' + Avalon.FM.RST)
         Avalon.warning('WICD folder not found! WICD does not appear to be installed!')
         if Avalon.ask('Continue anyway? (Create Directories)', False):
             Utilities.execute(['mkdir', '-p', '/etc/wicd/scripts/postconnect/'])
             Utilities.execute(['mkdir', '-p', '/etc/wicd/scripts/postdisconnect/'])
         else:
             Avalon.warning('Aborting installation for WICD')
             return False
     with open('/etc/wicd/scripts/postconnect/scutum_connect', 'w') as postconnect:
         postconnect.write('#!/bin/bash\n')
         postconnect.write('scutum')
         postconnect.close()
     with open('/etc/wicd/scripts/postdisconnect/scutum_disconnect', 'w') as postdisconnect:
         postdisconnect.write('#!/bin/bash\n')
         postdisconnect.write('scutum --reset')
         postdisconnect.close()
     Utilities.execute(['chown', 'root:', '/etc/wicd/scripts/postconnect/scutum_connect'])
     Utilities.execute(['chmod', '755', '/etc/wicd/scripts/postconnect/scutum_connect'])
     Utilities.execute(['chown', 'root:', '/etc/wicd/scripts/postdisconnect/scutum_disconnect'])
     Utilities.execute(['chmod', '755', '/etc/wicd/scripts/postdisconnect/scutum_disconnect'])
     print(Avalon.FG.G + Avalon.FM.BD + 'SUCCEED' + Avalon.FM.RST)
     return True
Ejemplo n.º 4
0
 def run(self):
     global successes
     self.running = True
     while self.running and (self.limit is None or successes < self.limit):
         self.send_request()
         time.sleep(self.interval)
     Avalon.warning(f"Thread {self.name} exiting")
Ejemplo n.º 5
0
def read_config():
    """ Parses configuration
    This function parses the configuration file and
    load the configurations into the program

    TODO: Do something about KeyError
    """
    if not os.path.isfile(args.config):  # Configuration not found
        Avalon.error('SCUTUM configuration file not found! Please re-install SCUTUM!')
        Avalon.warning('Please run \"scutum --install\" before using it for the first time')
        raise FileNotFoundError(args.config)

    # Initialize python confparser and read config
    with open(args.config, 'r') as raw_config:
        config = json.load(raw_config)

    # Get controlled interfaces
    interfaces = []
    for interface in config['Interfaces']['interfaces']:
        if os.path.isdir(f'/sys/class/net/{interface}'):
            # Check if interface is connected
            interfaces.append(interface)

    # Get controlled network controllers
    network_controllers = config['NetworkControllers']['controllers']

    # Check if we should handle ufw
    ufw_handled = config['Ufw']['handled']

    # Get ARP Controller driver
    arp_driver = config['ArpController']['driver']

    return interfaces, network_controllers, ufw_handled, arp_driver
Ejemplo n.º 6
0
    def __init__(self, driver='nftables'):

        self.driver = driver

        if self.driver != 'nftables' and self.driver != 'arptables':
            Avalon.warning('Unrecognized ARP controller driver {}'.format(
                self.driver))
            Avalon.warning('Falling back to nftables')
            self.driver = 'nftables'
Ejemplo n.º 7
0
def main():
    """ AnyRadius Manager main function
    This function can only be executed when
    this file is not being imported.
    """
    # Create database controller connection

    try:
        if sys.argv[1].lower() == 'help':
            print_help()
            exit(0)
        elif sys.argv[1].lower() == 'config':
            config_path = sys.argv[2]
        else:
            config_path = '/etc/anyradius.json'
    except IndexError:
        Avalon.error('Error parsing configuration file path')
        exit(1)

    Avalon.debug_info('Reading config from: {}'.format(config_path))
    db_host, db_user, db_pass, db, table = read_config(config_path)

    Avalon.info('Connecting to RADIUS database')
    rdb = UserDatabase(db_host, db_user, db_pass, db, table)
    Avalon.info('Database connection established')

    # Begin command interpreting
    try:
        if sys.argv[1].lower() == 'interactive' or sys.argv[1].lower(
        ) == 'int':
            print_legal_info()
            # Set command completer
            completer = ShellCompleter(COMMANDS)
            readline.set_completer(completer.complete)
            readline.parse_and_bind('tab: complete')
            # Launch interactive trojan shell
            prompt = '{}[AnyRadius]> {}'.format(Avalon.FM.BD, Avalon.FM.RST)
            while True:
                command_interpreter(rdb, [''] + input(prompt).split(' '))
        else:
            # Return to shell with command return value
            exit(command_interpreter(rdb, sys.argv[0:]))
    except IndexError:
        Avalon.warning('No commands specified')
        exit(0)
    except (MySQLdb.Error, MySQLdb.Warning):
        Avalon.error('Database error')
        traceback.print_exc()
        exit(1)
    except (KeyboardInterrupt, EOFError):
        Avalon.warning('Exiting')
        exit(0)
    except Exception:
        Avalon.error('Exception caught')
        traceback.print_exc()
        exit(1)
def command_interpreter(commands):
    """ WGC shell command interpreter

    This function interprets commands from CLI or
    the interactive shell, and passes the parameters
    to the corresponding functions.
    """
    try:
        # Try to guess what the user is saying
        possibilities = [
            s for s in COMMANDS if s.lower().startswith(commands[1])
        ]
        if len(possibilities) == 1:
            commands[1] = possibilities[0]

        if commands[1].replace(' ', '') == '':
            result = 0
        elif commands[1].lower() == 'help':
            print_help()
            result = 0
        elif commands[1].lower() == 'showpeers':
            for peer in pm.peers:
                print_peer_config(peer)
            result = 0
        elif commands[1].lower() == 'jsonloadprofile':
            result = pm.json_load_profile(commands[2])
        elif commands[1].lower() == 'jsonsaveprofile':
            result = pm.json_save_profile(commands[2])
        elif commands[1].lower() == 'pickleloadprofile':
            result = pm.pickle_load_profile(commands[2])
        elif commands[1].lower() == 'picklesaveprofile':
            result = pm.pickle_save_profile(commands[2])
        elif commands[1].lower() == 'newprofile':
            result = pm.new_profile()
        elif commands[1].lower() == 'addpeer':
            result = add_peer()
        elif commands[1].lower() == 'deletepeer':
            result = delete_peer(commands[2])
        elif commands[1].lower() == 'generateconfigs':
            result = generate_configs(commands[2])
        elif commands[1].lower() == 'exit' or commands[1].lower() == 'quit':
            Avalon.warning('Exiting')
            exit(0)
        elif len(possibilities) > 0:
            Avalon.warning(f'Ambiguous command \"{commands[1]}\"')
            print('Use \"Help\" command to list available commands')
            result = 1
        else:
            Avalon.error('Invalid command')
            print('Use \"Help\" command to list available commands')
            result = 1
        return result
    except IndexError:
        Avalon.error('Invalid arguments')
        print('Use \"Help\" command to list available commands')
        result = 0
    def new_profile(self):
        """ Create new profile and flush the peers list
        """

        # Warn the user before flushing configurations
        Avalon.warning('This will flush the currently loaded profile!')
        if len(self.peers) != 0:
            if not Avalon.ask('Continue?', False):
                return

        # Reset self.peers and start enrolling new peer data
        self.peers = []
Ejemplo n.º 10
0
    def upgrade_full(self):
        """ upgrade all packages

        This method checks if there are packages
        available for updating and update the packages
        if updating them won't remove any packages from
        the system. Often times when a bad source is added
        to the system, APT tends to remove a number of packages
        from the system when upgrading which is very risky.
        """
        Avalon.info("Starting automatic upgrade")
        Avalon.info("Updating APT cache")
        with open("/etc/apt/sources.list", "r") as aptlist:
            for line in aptlist:
                if ("ubuntu.com" in line
                        and distro.linux_distribution()[0] != "Ubuntu"
                        and line.replace(" ", "")[0] != "#"):
                    Avalon.warning("Ubuntu source detected in source.list!")
                    Avalon.warning(
                        "Continue upgrading might cause severe consequences!")

                    if Avalon.ask("Are you sure that you want to continue?",
                                  False):
                        break
                    else:
                        Avalon.warning("Aborting system upgrade..")
                        sys.exit(0)
        self.update()
        Avalon.info("APT cache updated")

        if len(self.import_list) != 0:
            Avalon.ask(
                f"Detected un-imported keys: {' '.join(self.import_list)}")

        # if there are no upgrades available
        Avalon.info("Checking package updates")
        if self.no_upgrades():
            Avalon.debug_info("No upgrades available")

        # if upgrades are available
        else:
            Avalon.info("Checking if full upgrade is safe")

            # if upgrade is safe, use -y flag on apt-get full-upgrade
            # otherwise, let user confirm the upgrade
            if self.full_upgrade_safe():
                Avalon.debug_info("Full upgrade is safe")
                Avalon.info("Starting APT full upgrade")
                self.full_upgrade()
            else:
                Avalon.warning("Full upgrade is NOT safe")
                Avalon.warning("Requiring human confirmation")
                self.manual_full_upgrade()
Ejemplo n.º 11
0
    def _wait(self):
        """wait for subprocesses in process pool to complete"""
        Avalon.debug_info(_("Main process waiting for subprocesses to exit"))

        try:
            # while process pool not empty
            while self.process_pool:

                # if stop signal received, terminate all processes
                if self.running is False:
                    raise SystemExit

                for process in self.process_pool:
                    process_status = process.poll()

                    # if process finished
                    if process_status is None:
                        continue

                    # if return code is not 0
                    elif process_status != 0:
                        Avalon.error(
                            _("Subprocess {} exited with code {}").format(
                                process.pid, process_status
                            )
                        )
                        raise subprocess.CalledProcessError(
                            process_status, process.args
                        )

                    else:
                        Avalon.debug_info(
                            _("Subprocess {} exited with code {}").format(
                                process.pid, process_status
                            )
                        )
                        self.process_pool.remove(process)

                time.sleep(0.1)

        except (KeyboardInterrupt, SystemExit) as e:
            Avalon.warning(_("Stop signal received"))
            self._terminate_subprocesses()
            raise e

        except (Exception, subprocess.CalledProcessError) as e:
            Avalon.error(_("Subprocess execution ran into an error"))
            self._terminate_subprocesses()
            raise e
Ejemplo n.º 12
0
    def _install_arp_controller_driver(self):
        """ Install the CLI tool if not installed
        """
        if self.config['ArpController']['driver'] == 'nftables':
            binary = 'nft'
        elif self.config['ArpController']['driver'] == 'arptables':
            binary = 'arptables'

        if shutil.which(binary) is None:
            Avalon.warning('ARP controller driver is not installed')
            if Avalon.ask(f'Install {self.config["ArpController"]["driver"]}?', True):
                Utilities.install_packages([self.config['ArpController']['driver']])
            else:
                Avalon.error('ARP controller driver not installed')
                Avalon.error('SCUTUM relies on the driver to run')
                Avalon.error('Aborting installation')
                exit(1)
Ejemplo n.º 13
0
def command_interpreter(commands):
    """ WGC shell command interpreter

    This function interprets commands from CLI or
    the interactive shell, and passes the parameters
    to the corresponding functions.
    """
    try:
        # Try to guess what the user is saying
        possibilities = [s for s in COMMANDS if s.lower().startswith(commands[1])]
        if len(possibilities) == 1:
            commands[1] = possibilities[0]

        if commands[1].replace(' ', '') == '':
            result = 0
        elif commands[1].lower() == 'help':
            print_help()
            result = 0
        elif commands[1].lower() == 'gencacert':
            cacert = CACert(commands[2])
            cacert.generate()
            result = 0
        elif commands[1].lower() == 'genusercert':
            usercert = UserCert(commands[2], commands[3], commands[4])
            usercert.generate()
            result = 0
        elif commands[1].lower() == 'genservercert':
            servercert = ServerCert(commands[2], commands[3], commands[4], commands[5])
            servercert.generate()
            result = 0
        elif commands[1].lower() == 'exit' or commands[1].lower() == 'quit':
            Avalon.warning('Exiting')
            exit(0)
        elif len(possibilities) > 0:
            Avalon.warning('Ambiguous command \"{}\"'.format(commands[1]))
            print('Use \"Help\" command to list available commands')
            result = 1
        else:
            Avalon.error('Invalid command')
            print('Use \"Help\" command to list available commands')
            result = 1
        return result
    except IndexError:
        Avalon.error('Invalid arguments')
        print('Use \"Help\" command to list available commands')
        result = 0
Ejemplo n.º 14
0
    def xinstall(packages: list):
        """ install only packages that are not installed

        By using the xinstall function to install packages,
        already-installed packages will not get marked as
        manually installed by APT.

        Arguments:
            packages {list} -- list of packages to install
        """
        not_installed = []
        installed = []

        # get a list of all locally installed packages
        apt_list = subprocess.run(
            ['apt', 'list'],
            stderr=subprocess.DEVNULL).stdout.decode().split('\n')
        for line in apt_list:
            for package in packages:
                if package == line.split('/')[0] and 'installed' not in line:
                    not_installed.append(package)
                elif package == line.split('/')[0] and 'installed' in line:
                    installed.append(package)

        Avalon.info('Packages already installed:')
        print(' '.join(installed))

        Avalon.info('Packages to be installed:')
        print(' '.join(not_installed))

        execute = ['apt-get', 'install', '-s']

        execute.extend(not_installed)

        Avalon.info('Launching a dry-run')
        subprocess.call(execute)

        if Avalon.ask('Confirm installation:', False):

            # swap -s flag with -y for actual installation
            execute[execute.index('-s')] = '-y'
            subprocess.call(execute)

        else:
            Avalon.warning('Installation aborted')
Ejemplo n.º 15
0
def create_char_pool(args):
    """Create a pool of characters

    This function creates a pool of characters which the
    random password generator will choose characters from.

    Arguments:
        args {argparse.Namespace} -- parsed arguments

    Returns:
        string -- string of characters
    """
    symbols = ''.join([chr(i) for i in range(33, 48)])
    char_pool = ""

    if args.uppercase:
        if not args.quiet:
            Avalon.debug_info("Including Uppercase characters")
        char_pool += ascii_uppercase
    if args.lowercase:
        if not args.quiet:
            Avalon.debug_info("Including lowercase characters")
        char_pool += ascii_lowercase
    if args.digits:
        if not args.quiet:
            Avalon.debug_info("Including digits")
        char_pool += digits
    if args.symbols:
        if not args.quiet:
            Avalon.debug_info("Including symbols")
        char_pool += symbols
    if args.all or not (args.uppercase or args.lowercase or args.digits
                        or args.symbols):
        if not args.quiet:
            Avalon.debug_info("Including all characters")
        if args.uppercase or args.lowercase or args.digits or args.symbols:
            if not args.quiet:
                Avalon.warning(
                    "Ignoring other switches since including all characters")
        char_pool = ascii_letters + digits + symbols
    return char_pool
Ejemplo n.º 16
0
    def _get_controlled_nm(self):
        """ Ask which network controller to hook to
        """
        while True:
            print(Avalon.FM.BD + '\nWhich network controller do you want to install for?' + Avalon.FM.RST)
            print('1. WICD')
            print('2. Network-Manager')
            print('3. Both')

            selection = Avalon.gets('Please select: (index number): ')

            if selection == '1':
                if self.install_wicd_scripts() is not True:
                    Avalon.error('SCUTUM Script for WICD has failed to install!')
                    Avalon.error('Aborting Installation...')
                    exit(1)
                self.config['NetworkControllers']['controllers'] = 'wicd'
                break
            elif selection == '2':
                if self.install_nm_scripts(self.config['Interfaces']['interfaces']) is not True:
                    Avalon.error('SCUTUM Script for NetworkManager has failed to install!')
                    Avalon.error('Aborting Installation...')
                    exit(1)
                self.config['NetworkControllers']['controllers'] = 'NetworkManager'
                break
            elif selection == '3':
                ifaces = ['wicd', 'NetworkManager']
                if self.install_wicd_scripts() is not True:
                    Avalon.warning('Deselected WICD from installation')
                    ifaces.remove('wicd')
                if self.install_nm_scripts(self.config['Interfaces']['interfaces']) is not True:
                    Avalon.warning('Deselected NetworkManager from installation')
                    ifaces.remove('NetworkManager')
                if len(ifaces) == 0:
                    Avalon.error('All SCUTUM Scripts have failed to install!')
                    Avalon.error('Aborting Installation...')
                    exit(1)
                self.config['NetworkControllers']['controllers'] = ifaces
                break
            else:
                Avalon.error('Invalid Input!')
Ejemplo n.º 17
0
    def no_upgrades() -> bool:
        """ check if no upgrades are available

        Determine if there are no upgrades available

        Returns:
            bool -- True if there are packages available
        """
        output = subprocess.run(
            ['apt-get', 'full-upgrade', '-s'],
            stdout=subprocess.PIPE).stdout.decode().split('\n')
        for line in output:
            parsed_line = line.replace('and', ',').replace(' ', '').split(',')
            if parsed_line[0] == '0upgraded' and parsed_line[
                    1] == '0newlyinstalled':
                if parsed_line[3] != '0notupgraded.':
                    Avalon.warning('Some packages are not upgraded')
                    Avalon.warning('Attempting to print messages from APT:')
                    subprocess.call(['apt', 'upgrade', '-s'])
                return True
        return False
Ejemplo n.º 18
0
    def no_upgrades() -> bool:
        """ check if no upgrades are available

        Determine if there are no upgrades available

        Returns:
            bool -- True if there are packages available
        """
        output = (subprocess.run(
            ["/usr/bin/apt-get", "full-upgrade", "-s"],
            stdout=subprocess.PIPE).stdout.decode().split("\n"))
        for line in output:
            parsed_line = line.replace("and", ",").replace(" ", "").split(",")
            if parsed_line[0] == "0upgraded" and parsed_line[
                    1] == "0newlyinstalled":
                if parsed_line[3] != "0notupgraded.":
                    Avalon.warning("Some packages are not upgraded")
                    Avalon.warning("Attempting to print messages from APT:")
                    subprocess.call(["/usr/bin/apt", "upgrade", "-s"])
                return True
        return False
    def json_save_profile(self, profile_path):
        """ Save current profile to a JSON file
        """

        # If profile already exists (file or link), ask the user if
        # we should overwrite it.
        if os.path.isfile(profile_path) or os.path.islink(profile_path):
            if not Avalon.ask('File already exists. Overwrite?', True):
                Avalon.warning('Aborted saving profile')
                return 1

        # Abort if profile_path points to a directory
        if os.path.isdir(profile_path):
            Avalon.warning('Destination path is a directory')
            Avalon.warning('Aborted saving profile')
            return 1

        # Finally, write the profile into the destination file
        Avalon.debug_info(f'Writing profile to: {profile_path}')

        peers_dict = {}
        peers_dict['peers'] = []

        for peer in pm.peers:
            peers_dict['peers'].append(peer.__dict__)

        with open(profile_path, 'w') as profile:
            json.dump(peers_dict, profile, indent=4)
            profile.close()
    def save_profile(self, profile_path):
        """ Save current profile to a file

        Serializes the current profile with pickle
        and dumps it into a file.
        """

        # If profile already exists (file or link), ask the user if
        # we should overwrite it.
        if os.path.isfile(profile_path) or os.path.islink(profile_path):
            if not Avalon.ask('File already exists. Overwrite?', True):
                Avalon.warning('Aborted saving profile')
                return 1

        # Abort if profile_path points to a directory
        if os.path.isdir(profile_path):
            Avalon.warning('Destination path is a directory')
            Avalon.warning('Aborted saving profile')
            return 1

        # Finally, write the profile into the destination file
        Avalon.debug_info('Writing profile to: {}'.format(profile_path))
        with open(profile_path, 'wb') as profile:
            pickle.dump(pm.peers, profile)
            profile.close()
def main():
    """ WireGuard Mesh Configurator main function

    This function controls the main flow of this program.
    """

    try:
        if sys.argv[1].lower() == 'help':
            print_help()
            exit(0)
    except IndexError:
        pass

    # Begin command interpreting
    try:
        if sys.argv[1].lower() == 'interactive' or sys.argv[1].lower(
        ) == 'int':
            print_welcome()
            # Set command completer
            completer = ShellCompleter(COMMANDS)
            readline.set_completer(completer.complete)
            readline.parse_and_bind('tab: complete')
            # Launch interactive trojan shell
            prompt = '{}[WGC]> {}'.format(Avalon.FM.BD, Avalon.FM.RST)
            while True:
                command_interpreter([''] + input(prompt).split(' '))
        else:
            # Return to shell with command return value
            exit(command_interpreter(sys.argv[0:]))
    except IndexError:
        Avalon.warning('No commands specified')
        print_help()
        exit(0)
    except (KeyboardInterrupt, EOFError):
        Avalon.warning('Exiting')
        exit(0)
    except Exception:
        Avalon.error('Exception caught')
        traceback.print_exc()
        exit(1)
Ejemplo n.º 22
0
def upgrade_kpm():
    """ upgrade KPM

    Upgrades KPM by downloading the latest version from GitHub.
    Replaces the current file being executed.
    """
    try:

        # get python script web page
        kpm_request = requests.get(GITHUB_KPM_FILE)
        if kpm_request.status_code != requests.codes.ok:
            kpm_request.raise_for_status()

        # write web page content to file
        with open(os.path.abspath(__file__), 'wb') as kpm_file:
            kpm_file.write(kpm_request.content)

        Avalon.info('KPM has been updated successfully')
        Avalon.info('Please relaunch KPM')

    except Exception:
        Avalon.error('There was an error updating KPM')
        Avalon.warning('You might have to reinstall KPM manually')
Ejemplo n.º 23
0
    def install_nm_scripts(self, interfaces):
        """ Write scutum scripts for Network Manager
        """
        print(Avalon.FG.G + '[+] INFO: Installing for NetworkManager' + Avalon.FM.RST + '.....', end='')
        if not os.path.isdir('/etc/NetworkManager/dispatcher.d/'):
            print(Avalon.FG.R + Avalon.FM.BD + 'ERROR' + Avalon.FM.RST)
            Avalon.warning('NetworkManager folders not found! NetworkManager does not appear to be installed!')
            if Avalon.ask('Continue anyway? (Create Directories)', False):
                Utilities.execute(['mkdir', '-p', '/etc/NetworkManager/dispatcher.d/'])
            else:
                Avalon.warning('Aborting installation for NetworkManager')
                return False
        with open('/etc/NetworkManager/dispatcher.d/scutum', 'w') as nmScript:
            nmScript.write('#!/usr/bin/env python3\n')
            nmScript.write('\n')
            nmScript.write('import sys\n')
            nmScript.write('import os\n')
            nmScript.write('\n')
            nmScript.write('try:\n')
            nmScript.write('    interface = sys.argv[1]\n')
            nmScript.write('    status = sys.argv[2]\n')
            nmScript.write('except IndexError:\n')
            nmScript.write('    exit(0)\n')
            nmScript.write('\n')
            nmScript.write('if status == \"down\":\n')
            nmScript.write('    os.system(\"scutum --reset\")\n')
            nmScript.write('    exit(0)\n')
            nmScript.write('\n')
            nmScript.write('if status == \"up\":\n')
            nmScript.write('    os.system(\"scutum\")\n')
            nmScript.write('    exit(0)\n')
            nmScript.close()

        Utilities.execute(['chown', 'root:', '/etc/NetworkManager/dispatcher.d/scutum'])
        Utilities.execute(['chmod', '755', '/etc/NetworkManager/dispatcher.d/scutum'])
        print(Avalon.FG.G + Avalon.FM.BD + 'SUCCEED' + Avalon.FM.RST)
        return True
Ejemplo n.º 24
0
    def _install_defense_matrix(self):
        """ Installs defense matrix to system and
        link defense matrix executable to bin path.
        """

        # Get installation destination from user
        user_install_dir = Avalon.gets(
            'Installation destination (\"/usr/share/defense-matrix\")')
        if user_install_dir != '':
            self.install_dir = user_install_dir

        # If files already at the correct directory, pass
        if self.current_dir == self.install_dir:
            pass

        # Check if destination directory occupied
        else:
            if os.path.isdir(self.install_dir) or os.path.islink(
                    self.install_dir):
                if not Avalon.ask('Target directory exists. Overwrite?', True):
                    Avalon.warning(
                        'Aborting installation: target directory not writable')
                if os.path.isdir(self.install_dir):
                    shutil.rmtree(self.install_dir)
                else:
                    os.remove(self.install_dir)

            # Copy defense matrix to destination directory
            shutil.copytree(self.current_dir, self.install_dir)

        # If defense-matrix is already linked to path, remove it
        if os.path.islink(self.executable) or os.path.isfile(self.executable):
            os.remove(self.executable)  # Remove old file or symbolic links

        # Link current defense-matrix.py to path
        os.symlink('{}/bin/defense-matrix.py'.format(self.current_dir),
                   self.executable)
Ejemplo n.º 25
0
 def getPost(self: None,
             pageNumber: int,
             ajax: bool = True,
             useTemp: bool = True):  # 获得html源文件函数
     self.__workPageNumber = pageNumber
     link = self.__postLink + str(pageNumber)
     existTemp = self.__tempSave.getSameTemp()
     if existTemp.get('html') and useTemp:
         for i in existTemp['html']:
             if int(i[1]) == int(pageNumber):
                 Avalon.debug_info('第%d页已经在临时文件中存在,跳过' % pageNumber)
                 return self.__tempSave.readFileByID(i)
     if ajax is False:
         link = link.replace('ajax=1&', '')
     for tryTimes in range(1, 11):
         try:
             postRequest = request.Request(link)
             try:
                 # 设置程序请求头,伪装爬虫(必要性存疑)
                 postRequest.add_header('User-Agent', (random.choice(
                     self.__userAgent)).replace('\n', ''))
                 postRequest.add_header('Referer',
                                        'https://tieba.baidu.com')
             except:
                 continue
             else:
                 postRead: bytes = request.urlopen(postRequest,
                                                   timeout=5).read()
                 if self.debug:
                     Avalon.debug_info('链接:"%s"请求头:%s.' %
                                       (link, postRequest.headers))
         # 错误处理
         except error.URLError as e:
             Avalon.warning("获取帖子正文失败!原因:%s(%s/10)" %
                            (str(e.reason), str(tryTimes)))
         except timeout as e:
             Avalon.warning("获取帖子正文失败!原因:%s(%s/10)" %
                            (str(e), str(tryTimes)))
         except KeyboardInterrupt:
             Avalon.critical("用户强制退出")
             quit(1)
         except:
             Avalon.warning("获取帖子正文失败!原因:未知错误(%s/10)" % tryTimes)
         # 没有错误,结束循环
         else:
             if self.debug:
                 Avalon.debug_info('Link %s Get Successed.' % link)
             break
     else:
         Avalon.error('获取失败!')
         if self.debug:
             Avalon.debug('Link:%s' % link)
         quit(1)
     if useTemp is True:
         self.__tempSave.savePostRaw(postRead.decode(errors='ignore'),
                                     pageNumber=pageNumber)
     return (postRead.decode(errors='ignore'))
Ejemplo n.º 26
0
def upgrade_kpm():
    """ upgrade KPM

    Upgrades KPM by downloading the latest version from GitHub.
    Replaces the current file being executed.
    """
    try:

        latest_json = requests.get(
            "https://api.github.com/repos/k4yt3x/kpm/releases/latest").json()

        for asset in latest_json["assets"]:
            if asset["name"] == "kpm.py":
                latest_version_url = asset["browser_download_url"]
                break
        else:
            Avalon.warning("Unable to find the latest version's download URL")
            return

        # get python script web page
        kpm_request = requests.get(latest_version_url)
        if kpm_request.status_code != requests.codes.ok:
            kpm_request.raise_for_status()

        # write web page content to file
        with pathlib.Path(__file__).open(mode="wb") as kpm_file:
            kpm_file.write(kpm_request.content)

        Avalon.info("KPM has been updated successfully")
        Avalon.info("Please relaunch KPM")
        sys.exit(0)

    except Exception as e:
        Avalon.error("There was an error updating KPM")
        Avalon.warning("You might have to reinstall KPM manually")
        raise e
Ejemplo n.º 27
0
def check_version():
    """ check if KPM is up-to-date

    Check if KPM is up to date with the the newest
    version on GitHub. Prompt the user to upgrade if
    the local version is not the newest.
    """
    # get version number of KPM on GitHub
    Avalon.debug_info('Checking KPM Version')
    for line in requests.get(GITHUB_KPM_FILE).text.split('\n'):
        if 'VERSION = ' in line:
            server_version = line.split(' ')[-1].replace('\'', '')
            break
    Avalon.debug_info(f'Server version: {server_version}')

    # if the server version is newer than local version
    if server_version > VERSION:
        Avalon.info('Here\'s a newer version of KPM!')
        if Avalon.ask('Update to the newest version?', True):
            upgrade_kpm()
        else:
            Avalon.warning('Ignoring update')
    else:
        Avalon.debug_info('KPM is already on the newest version')
Ejemplo n.º 28
0
def command_interpreter(db_connection, commands):
    """ AnyRadius shell command interpreter
    """
    try:
        # Try to guess what the user is saying
        possibilities = [
            s for s in COMMANDS if s.lower().startswith(commands[1])
        ]
        if len(possibilities) == 1:
            commands[1] = possibilities[0]

        if commands[1].replace(' ', '') == '':
            result = 0
        elif commands[1].lower() == 'help':
            print_help()
            result = 0
        elif commands[1].lower() == 'truncateusertable':
            Avalon.warning('By truncating you will LOSE ALL USER DATA')
            if Avalon.ask('Are you sure you want to truncate?'):
                result = db_connection.truncate_user_table()
            else:
                Avalon.warning('Operation canceled')
                result = 0
        elif commands[1].lower() == 'adduser':
            result = db_connection.add_user(commands[2], commands[3])
        elif commands[1].lower() == 'deluser':
            result = db_connection.del_user(commands[2])
        elif commands[1].lower() == 'showusers':
            result = db_connection.show_users()
        elif commands[1].lower() == 'exit' or commands[1].lower() == 'quit':
            Avalon.warning('Exiting')
            exit(0)
        elif len(possibilities) > 0:
            Avalon.warning('Ambiguous command \"{}\"'.format(commands[1]))
            print('Use \"Help\" command to list available commands')
            result = 1
        else:
            Avalon.error('Invalid command')
            print('Use \"Help\" command to list available commands')
            result = 1
        return result
    except IndexError:
        Avalon.error('Invalid arguments')
        print('Use \"Help\" command to list available commands')
        result = 0
Ejemplo n.º 29
0
 def uploadSingleImage(self: None, imageFilePath: str):
     form = MultiPartForm()
     with open(imageFilePath, 'rb') as f:
         form.add_file('image', f.name, f)  # 文件提交
         form.add_field('token', '')  # 文件上传密钥,默认为空
         # 默认选择新浪图床(推荐),还可以选择 SouGou:搜狗图床,Smms:https://sm.ms 图床
         form.add_field('apiSelect', 'Sina')
     r = request.Request('https://image.mnixry.cn/api/v1/upload',
                         data=bytes(form))  # 用生成好的表单参数制造请求
     r.add_header('User-Agent', self.__getUserAgent())  # 随机UA(必要性存疑)
     # 提交表单类型(主要是Boundary)
     r.add_header('Content-type', form.get_content_type())
     r.add_header('Content-length', len(bytes(form)))  # 提交表单大小(单位:bytes)
     if self.__debugMode:
         Avalon.debug_info(
             '文件名:%s,请求头:%s' %
             (os.path.split(imageFilePath)[1], str(r.headers)))
     for i in range(1, 11):
         try:
             uploadRes = request.urlopen(r, timeout=10).read().decode()
         except error.URLError as e:
             if not (self.__ignoreTimeOut and
                     ('timed out' in str(e.reason))):
                 Avalon.warning('图片上传失败!原因:%s[%d/10]' % (e.reason, i))
         except timeout as e:
             if not self.__ignoreTimeOut:
                 Avalon.warning('图片上传失败!原因:%s[%d/10]' % (e, i))
         except:
             Avalon.warning('图片上传失败!原因:未知错误[%d/10]' % i)
         else:
             uploadRes = json.loads(uploadRes)
             if int(uploadRes['code']) != 200:
                 Avalon.warning('图片上传失败!原因:%s[%d/10]' %
                                (uploadRes['msg'], i))
                 continue
             else:
                 del form
                 break
     else:
         return (False)
     if self.__debugMode:
         Avalon.debug_info('图片上传成功!图床链接:%s,本地地址:%s' %
                           (uploadRes['data']['url'], imageFilePath))
     return (uploadRes['data']['url'])
Ejemplo n.º 30
0
def check_version():
    """ check if KPM is up-to-date

    Check if KPM is up to date with the the newest
    version on GitHub. Prompt the user to upgrade if
    the local version is not the newest.
    """
    # get version number of KPM on GitHub
    Avalon.info("Checking KPM's Version")
    latest = requests.get(
        "https://api.github.com/repos/k4yt3x/kpm/releases/latest")
    latest_json = latest.json()

    # if rate limit is exceeded, 403 will be returned
    if (latest.status_code == requests.codes.forbidden
            and "API rate limit exceeded" in latest_json["message"]):
        Avalon.warning("GitHub API rate limit exceeded")
        return

    # if the status code isn't 200, warn the user and skip the rest of the checks
    elif latest.status_code != requests.codes.ok:
        Avalon.warning("GitHub API request encountered an error")
        return

    latest_version = latest_json["tag_name"]
    Avalon.debug_info(f"Server version: {latest_version}")

    # if the server version is newer than local version
    if version.parse(latest_version) > version.parse(VERSION):
        Avalon.info(
            f"There is a newer version of KPM available ({latest_version})")
        if Avalon.ask("Update to the newest version?", True):
            upgrade_kpm()
        else:
            Avalon.warning("Skipping the upgrade for now")
    else:
        Avalon.debug_info(f"KPM is already on the newest version ({VERSION})")