Exemple #1
0
 def make(self, log):
     output_dir = settings.get('install_path') + 'etc/modsec/'
     output_file = output_dir + 'rules.conf'
     # if os.path.exists(output_dir):
     #     shutil.rmtree(output_dir)
     filelist = glob.glob(os.path.join(output_dir, "*.data"))
     filelist.extend(glob.glob(os.path.join(output_dir, "*.mapping")))
     filelist.extend(glob.glob(os.path.join(output_dir, "*.conf")))
     for f in filelist:
         os.remove(f)
     if not os.path.exists(output_dir):
         os.makedirs(output_dir)
     with open(output_file, 'w+') as output:
         with open(self.build_dir + 'ModSecurity/modsecurity.conf-recommended') as base_config:
             for line in base_config:
                 if line.startswith('SecRuleEngine '):
                     output.write('SecRuleEngine On\n')
                 elif line.startswith('SecAuditLog '):
                     output.write('SecAuditLog ' + settings.get('install_path') + 'var/log/modsec_audit.log\n')
                 else:
                     output.write(line)
         for builder in get_enabled_ruleset_builders():
             input_file = builder.rule_output_file()
             input_dir = builder.rule_output_dir()
             with open(input_file) as input:
                 for line in input:
                     output.write(line)
             for data_file in glob.glob(input_dir + '*.data'):
                 shutil.copy(data_file, output_dir)
     source_map = self.build_dir + 'ModSecurity/unicode.mapping'
     target_map = output_dir + 'unicode.mapping'
     shutil.copy(source_map, target_map)
     return 0 # 0 = successful bash command
Exemple #2
0
 def get_config_arg_file(self):
     """
     Returns the name of the file that lists arguments that are passed to
     the configure command. When overridden, this method can return an array
     of filenames instead.
     """
     return settings.get('install_path') + 'etc/build-config/' + self.slug
Exemple #3
0
def write_primary_logrotate():
    """
    Write out a configuration file for logrotated to rotate the global php log
    files. Also add an include directive that will include all website
    logrotated files.

    Args:
        domain - The domain name
    """
    install_path = settings.get('install_path')
    filename = primary_logrotate_file()
    version_list = get_versions()
    if len(version_list) == 0:
        if os.path.exists(filename):
            os.remove(filename)
    else:
        with open(filename, 'w+') as output:
            output.write('include ' + install_path +
                         'etc/logrotate.d/php-sites/*\n\n')
            for version in version_list:
                output.write(
                    '/opt/php-' + version + '/var/log/*.log {\n\
  weekly\n\
  rotate 52\n\
  dateext\n\
  compress\n\
  copytruncate\n\
  missingok\n\
  postrotate\n\
    /bin/kill -USR1 `cat /opt/php-' + version +
                    '/var/run/php-fpm.pid 2>/dev/null` 2>/dev/null || true\n\
  endscript\n\
}\n\n')
Exemple #4
0
def list_frozen():
    frozen_list = []
    freeze_file = settings.get('install_path') + 'etc/build-freeze'
    with open(freeze_file) as frozen:
        for line in frozen:
            frozen_list.append(line.strip())
    return frozen_list
Exemple #5
0
def unfreeze(slug):
    """
    Allow a builder to update it's source code to a newer version. This
    will not start a build.
    """
    freeze_file = settings.get('install_path') + 'etc/build-freeze'
    return file_filter.RemoveExact(freeze_file, slug).run()
Exemple #6
0
def freeze(slug):
    """
    Prevent a builder from updating it's source code to a newer version.
    The software will still be re-built if it's dependants are upated.
    """
    freeze_file = settings.get('install_path') + 'etc/build-freeze'
    return file_filter.AppendUnique(freeze_file, slug).run()
Exemple #7
0
def create_one_time_login(domain):
    """
    Create a PHP file to give a one-time login into a WordPress site without a
    password. There is no safty measure to remove this link if it is not used.

    Args:
        domain - The domain that needs a one-time login
    """
    sys_user = nginx.user_from_domain(domain)
    passcode = input_util.random_string(40, False)
    passname = input_util.random_string(40, False)
    docroot = nginx.docroot_from_domain(domain)
    target_file = docroot + 'wp-admin/wp-autologin-' + passname + '.php'
    site_url = get_site_url(sys_user, docroot)

    # Set environment
    whoami = os.geteuid()
    os.seteuid(getpwnam(sys_user).pw_uid)

    with open(settings.get('install_path') + 'etc/wp-autologin.php',
              'r') as template:
        with open(target_file, 'w') as php_file:
            for line in template:
                line = line.replace('PASSWORDD', passcode, 10000)
                php_file.write(line)

    # Reset environment
    os.seteuid(whoami)
    print('Go to: ' + site_url + 'wp-admin/wp-autologin-' + passname +
          '.php?pass=' + passcode)
Exemple #8
0
def create_and_install_dkim(domain):
    """
    Create a new DKIM key pair and apply them to the DNS and mail system
    configuration for a domain.

    Args:
        domain - The domain to update with a new DKIM key pair
    """
    if domain and not os.path.exists(bind.zone_folder + domain + '.db'):
        print('No zone file for ' + domain + ' found.')
        domain = False
    if not domain:
        domain = bind.select_main_domain('Select site to add DKIM to: ')[:-3]
    dkim_folder = settings.get('dkim_folder')
    if not os.path.exists(dkim_folder + domain + '.pub'):
        if not os.path.exists(dkim_folder):
            os.makedirs(dkim_folder)
        make_dkim_pair(domain)
    dkim = make_dkim_dns_value(domain)
    print('TXT Encoded DKIM: ' + dkim)

    DkimZoneUpdater(domain, dkim).run()
    bind.increment_soa(domain)

    print('Reloading nameserver to apply changes...')
    bind.reload()
    print('Done.')
Exemple #9
0
def logrotate_file(domain):
    """
    Get the logrotate configuration filename associated with a domain.

    Args:
        domain - The domain name
    """
    return settings.get('install_path') + 'etc/logrotate.d/php-sites/' + domain
Exemple #10
0
def template_path(name):
    """
    Get the full path for a given nginx vhost template name.

    Args:
        name - The name (slug) of the template
    """
    return settings.get('install_path') + 'etc/nginx-templates/' + name
Exemple #11
0
 def populate_config_args(self, log, command=False):
     if command == False:
         command = ['./configure']
     command.append('--prefix=/opt/php-' + self.versions['sub'])
     command.append('--with-mysql-sock=' + settings.get('mysql_socket'))
     for pecl_builder in get_registered_pecl_builders():
         command.append(pecl_builder.get_php_build_arg())
     return super().populate_config_args(log, command)
Exemple #12
0
 def log_name(self):
     if not self.source_version:
         self.source_version = self.get_updated_version()
     name = settings.get('install_path') + 'var/log/build/' + self.slug
     if self.source_version and len(self.source_version) > 0:
         name += '-' + self.source_version
     name += '.log'
     return name
Exemple #13
0
def get_updated_versions(force_refresh=False):
    """
    Get the full version numbers of versions avaliable at php.net.

    Args:
        force_refresh - (optional) When set to True, do not use cached values
    """
    vers = []
    cache_dir = settings.get('install_path') + 'var/cache/'
    cache_file = cache_dir + 'php-versions'
    use_cache = force_refresh == False

    if os.path.exists(cache_file):
        max_age = settings.get_num('build_cache_age')
        mod_time = os.stat(cache_file).st_mtime
        age = time.time() - mod_time
        if age > max_age:
            use_cache = False
    else:
        if not os.path.exists(cache_dir):
            os.makedirs(cache_dir)
        use_cache = False

    if use_cache:
        return file_filter.get_trimmed_file_as_array(cache_file)
    else:
        request = requests.get('https://www.php.net/downloads.php')
        regex = re.compile(r'.*/distributions/php-([0-9\.]*)\.tar\.bz2.*')
        for line in request.text.splitlines():
            match = regex.match(line)
            if match == None:
                continue
            match = match.group(1)
            if len(match) > 0:
                vers.append(match)
        if settings.get_bool('enable_php_legacy_versions'):
            vers.append(php71version)
            vers.append(php70version)
            vers.append(php56version)
        if settings.get_bool('enable_php_super_legacy_versions'):
            vers.append(php55version)
            vers.append(php54version)
            vers.append(php53version)
            vers.append(php52version)
            vers.append(php51version)
            vers.append(php50version)
            vers.append(php44version)
            vers.append(php43version)
            vers.append(php42version)
            vers.append(php41version)
            vers.append(php40version)
            vers.append(php30version)
        if settings.get_bool('enable_php_prerelease_version'):
            vers.extend(get_prerelease_version(vers))
        with open(cache_file, 'w+') as cache_write:
            for v in vers:
                cache_write.write(v + "\n")
        return vers
Exemple #14
0
def make_vhost(username, domain, template_name='php', template_fields=False):
    """
    Create a new vhost file for a given domain.

    Args:
        username - The system username that stores the sitesfiles
        domain - The domain associated with the new vhost file
        template_name - The name of the nginx vhost template to use
    """
    modsec = get_modsec_path(domain)
    home = user.home_dir(username)
    dash_domain = domain.replace('.', '-', 100)
    under_domain = domain.replace('.', '_', 100)
    vhost_path = get_vhost_path(domain)
    local_ip = settings.get('local_ip')
    public_ip = settings.get('public_ip')
    read_path = template_path(template_name)
    fields = get_vhost_headers(read_path)[0]
    if not template_fields:
        template_fields = []
        for key, value in fields:
            value = input_util.prompt_value(key, value)
            template_fields.append([key, value])
    if not os.path.exists(modsec_exception_dir):
        os.makedirs(modsec_exception_dir)
    if not os.path.exists(vhost_dir):
        os.makedirs(vhost_dir)
    with open(modsec, 'a+'):
        pass
    with open(read_path) as template:
        with open(vhost_path, 'w') as host:
            for line in template:
                line = line.replace('DOMAINNAMEE', domain, 10000)
                line = line.replace('USERNAMEE', username, 10000)
                line = line.replace('DASHDOMAINN', dash_domain, 10000)
                line = line.replace('UNDERDOMAINN', under_domain, 10000)
                line = line.replace('HOMEDIRR', home, 10000)
                line = line.replace('LOCALIPP', local_ip, 10000)
                line = line.replace('PUBLICIPP', public_ip, 10000)
                line = line.replace('MODSECC', modsec, 10000)
                for key, value in template_fields:
                    line = line.replace(key, value, 10000)
                host.write(line)
    print('Created ' + vhost_path)
    reload()
Exemple #15
0
def make_dkim_pair(domain):
    """
    Generate a new DKIM public key and private key. Then give EXIM access to
    those files.

    Args:
        domain - generate the keys for this domain
    """
    pem_file = settings.get('dkim_folder') + domain + '.pem'
    pub_file = settings.get('dkim_folder') + domain + '.pub'
    pwd_user = pwd.getpwnam(settings.get('exim_user')).pw_uid
    grp_group = grp.getgrnam(settings.get('exim_group')).gr_gid
    subprocess.run(['openssl', 'genrsa', '-out', pem_file, '2048'])
    subprocess.run(
        ['openssl', 'rsa', '-in', pem_file, '-pubout', '-out', pub_file])
    os.chown(pem_file, pwd_user, grp_group)
    os.chown(pub_file, pwd_user, grp_group)
    os.chmod(pem_file, 0o640)
    os.chmod(pub_file, 0o640)
Exemple #16
0
def get_mail_domains():
    """Get an array of all domains registered in the mail system."""
    domains = []
    with open(settings.get('mail_domain_file')) as file:
        for line in file:
            segments = line.split(':')
            domain = segments[0].strip().lower()
            if domain != '*':
                domains.append(domain)
    return sorted(domains)
Exemple #17
0
 def get_distro(self):
     distro = settings.get('imap_distro')
     if distro == 'unset':
         detected_distro = detect_distro_code()
         if detected_distro:
             distro = detected_distro
             settings.set('imap_distro', distro)
     if distro == 'unset':
         distro = self.select_distro('Select your current operating system')
         settings.set('imap_distro', distro)
     return distro
Exemple #18
0
def account_exists(account):
    """Check if an email address is registered in the email system."""
    account = account.lower() + ':'
    length = len(account)
    found = False
    with open(settings.get('mail_shadow_file')) as shadow:
        for line in shadow:
            if line[:length].lower() == account:
                found = True
                break
    return found
Exemple #19
0
def is_frozen(slug):
    """
    Returns True if the slug is set to be restricted from updating.
    """
    freeze_file = settings.get('install_path') + 'etc/build-freeze'
    if os.path.exists(freeze_file):
        with open(freeze_file) as frozen:
            for line in frozen:
                if slug == line.strip():
                    return True
    return False
Exemple #20
0
def libs_path():
    path = settings.get('openssl_libs')
    if path == 'unset':
        paths = ['/usr/local/ssl/lib', '/usr/local/lib64', '/usr/local/lib']
        at = -1
        while path == 'unset' or not os.path.exists(path + '/libssl.so.1.1'):
            at += 1
            if at >= len(paths):
                return False
            path = paths[at]
        settings.set('openssl_libs', path)
    return path
Exemple #21
0
 def cleanup_old_versions(self, log):
     found = False
     found_version = False
     for logname in builder.find_old_build_elements(
             settings.get('install_path') + 'var/log/build/php-' +
             self.versions['sub'] + '.', '.log'):
         os.remove(logname)
         log.log("Removed old log file " + logname)
     for folder in builder.find_old_build_elements(
             '/usr/local/src/php-' + self.versions['sub'] + '.', '/'):
         shutil.rmtree(folder)
         log.log("Removed old source directory " + folder)
Exemple #22
0
    def clean(self, log):
        """
        Clean build binaries for the software.

        Args:
            log - An open log file or null
        """
        old_pwd = os.getcwd()
        target_dir = self.source_dir()
        if os.path.exists(target_dir):
            os.chdir(target_dir)
            log.run(['make', 'clean', '-l', settings.get('max_build_load')])
        os.chdir(old_pwd)
Exemple #23
0
def get_account_from_domain(domain):
    """
    Get the username of the system user that stores email for the given domain.

    Args:
        domain - The domain to check
    """
    domain = domain.lower()
    with open(settings.get('mail_domain_file')) as file:
        for line in file:
            segments = line.split(':')
            if segments[0].strip().lower() == domain:
                return segments[1].strip()
    return False
Exemple #24
0
def get_local_deploy_domains():
    """
    Returns an array of domains that should have a copy of new certificates
    placed in ~/certs/ after renewal.
    """
    local_deploy = []
    local_filename = settings.get('install_path') + 'etc/local-cert-deploy'
    if os.path.exists(local_filename):
        with open(local_filename) as domain_list:
            for domain in domain_list:
                domain = domain.lower().strip()
                if not domain.startswith('#'):
                    local_deploy.append(domain.lower().strip())
    return local_deploy
Exemple #25
0
def remove_local_deploy(domain):
    """
    Unregister a domain to recieve copies of new certificates in the matching
    user's ~/cert directory.

    Args:
        domain - The domain to unregister
    """
    domain = domain.strip()
    filename = settings.get('install_path') + 'etc/local-cert-deploy'
    return file_filter.RemoveExact(filename,
                                   domain,
                                   ignore_trim=True,
                                   ignore_case=True).run()
Exemple #26
0
def template_list(hide_ssl=False):
    """
    Get an array containing all of the nginx vhost template file names exluding
    path.

    Args:
        hide_ssl - Only show non-SSL templates
    """
    templates = []
    folder_name = settings.get('install_path') + 'etc/nginx-templates/'
    for temp in glob.glob(folder_name + '*'):
        if not hide_ssl or not temp.endswith('-ssl'):
            templates.append(temp[len(folder_name):])
    return sorted(templates)
Exemple #27
0
def get_public_dkim_key(domain):
    """
    Get the contents of a public DKIM key with no line breaks.

    Args:
        domain - Get the public key for this domain
    """
    key = ''
    with open(settings.get('dkim_folder') + domain + '.pub') as pub:
        for line in pub:
            if line.startswith('-----'):
                continue
            key += line.replace('\n', '').replace('\r', '')
    return key
Exemple #28
0
def get_connection():
    """
    Cet a connected MySQL connection.
    """
    root_needs_pass = settings.get_bool('db_root_requires_password')
    socket = settings.get('mysql_socket')
    if (root_needs_pass):
        bitpass = getpass('Enter the MySQL root password: '******'root',
                                 passwd=bitpass)
    else:
        return connector.connect(unix_socket=socket, user='******')
Exemple #29
0
def _setpass(address):
    from libsw import email
    from getpass import getpass
    if address != False and not email.account_exists(address):
        print(address + ' does not exist on this server.')
        address = False
    if address == False:
        address = email.select_email()
    password = email.hash_password( getpass('Email Password: '******'Password Updated.')
    else:
        from libsw import settings
        print('Error. Password Not Updated. Check ' + settings.get('mail_shadow_file') + ' for syntax errors.')
Exemple #30
0
def make_zone(domain):
    """
    Create a new zone file for the given domain name. The new zone file is
    populated with values for the new domain. The index of zone files is not
    rebuilt to include the new zone and Bind is not restarted or reloaded.

    Args:
        domain - The primary domain of the zone file
    """
    if not os.path.exists(zone_folder):
        os.mkdir(zone_folder)
    template = open(settings.get('install_path') + 'etc/zone-file', 'r')
    ns1 = settings.get('nameserver_one')
    ns2 = settings.get('nameserver_two')
    dns_authority = settings.get('dns_authority')
    ip = settings.get('public_ip')
    with open(zone_filename(domain), 'w') as zone:
        for line in template:
            line = line.replace('DOMAINNAMEE', domain, 10000)
            line = line.replace('NAMESERVER_ONEE', ns1, 10000)
            line = line.replace('NAMESERVER_TWOO', ns2, 10000)
            line = line.replace('DNS_AUTHORITYY', dns_authority, 10000)
            line = line.replace('PUBLIC_IPP', ip, 10000)
            zone.write(line)