HEX
Server: Apache
System: Linux sxb1plzcpnl440011.prod.sxb1.secureserver.net 4.18.0-553.54.1.lve.el8.x86_64 #1 SMP Wed Jun 4 13:01:13 UTC 2025 x86_64
User: xfp2mtarcm67 (7705020)
PHP: 7.3.33
Disabled: NONE
Upload Files
File: //opt/alt/python37/lib/python3.7/site-packages/orphanedaccountscanner/main.py
#! /opt/alt/python37/bin/python3
import os
import re
import json
import typing
import socket
import datetime
import requests
from typing import Dict

from config import oas_url

from utils.ranking import rank

dirs = {
    '/home': {
        'type': 'account'
    },
}

ignore = [
    'gdlinuxm',
    'cpsupport',
    'gdresell',
    'gdmigrate',
    'vpsmigrate',
    'cpanelsolr',
    'diablo',
    'gdlegal',
    'binlogs',
    'cphulkd',
    'gdlinuxm_wp2',
    'horde',
    'modsec',
    'mysql',
    'performance_schema',
    'roundcube',
    'ikvminit',
    'srebackup',
    'svc4xdmzoss1h9vet'
]

SSOT = {
    'accounts': [],
    'databases': []
}

LOCAL = {
    'accounts': {},
    'databases': {}
}

localSOT = '/home/diablo/non_orphan_accounts'

#'accounts' [{
#    'db_after_asr': {
#        'uid': 1,
#        'gid': 1,
#        'last_accessed': 1
#    }
#},
#
#]

def system_health() -> bool:
    for _ in dirs:
        if not os.path.exists(_):
            raise SystemError('Directory not found')
    return True


def get_hostname() -> str:
    if socket.gethostname() == str():
        raise TypeError("Hostname audit event failed!")
    return socket.gethostname().split('.')[0]


def check_hostname() -> bool:
    """
        Grabs a servers unix hostname and checks if it's a cPanel server

        Returns: bool
    """
    short_name = get_hostname()
    hostname_regex = '^(p3|sg2|sxb1|bom1)(p|t)l(m|z)cpnl\d{2,}$'

    if re.search(hostname_regex, short_name):
        return True


# Local account scanning
def directory_scan(dir) -> list:
    """
        Parses a given directory and returns a list of sub directories ignoring
        files and hidden dirs/files

        Returns: list of dirs
    """
    if dir not in ['/home', '/var/lib/mysql']:
        raise TypeError('We have no idea how to scan that, sorry')

    try:
        entries = []
        with os.scandir(dir) as scan_path:
            for entry in scan_path:
                if not entry.name.startswith('.') and entry.is_file():
                    # both parsers need dirs and not hidden
                    continue
                else:
                    entries.append(entry)
    except OSError as error_message:
        raise SystemError(error_message)
    return entries


def get_directory_info(dir: os.DirEntry, base_dir: str,) -> list:
    stat = dir.stat()
    if stat.st_gid == 199 or stat.st_gid == 0:
        # Skip GDSTAFF and ROOT owned things
        return
    if os.path.islink(dir):
        # Skip symlinks
        return
    if dir.name in ignore:
        # Skip all things that we are explicitly ignoring
        return

    # If there's not a trailing / the name conc. doesn't work
    if base_dir[-1] is not '/':
        base_dir += '/'

    #from subprocess import run
    #process = run(['du', '-s', base_dir + dir.name], capture_output=True, text=True)
    #size_in_kb = process.stdout.split('\t')[0]
    size_in_kb = 0

    return [ dir.name, stat.st_uid, stat.st_gid, stat.st_atime , size_in_kb ]


relevance_queries = {
    'cpanel_migrations': {
        'description': 'cpmove_ accounts'
    }
}


removal_command = ['']


def process(accounts: Dict[str, Dict[str, str]], ssot):
    real = []
    rank_2 = []
    rank_3 = []
    rank_4 = []
    for account in accounts:
        rank = 0
        for query in relevance_queries:
            account_details = accounts[account]
            if account_details['gid'] <= 9999:
                rank = -1
            if 'cpmove_' in account:
                # query and rank significance
                rank += 3
            if account in ssot:
                rank = -1
            if account not in ssot:
                rank += 3
            if account in ignore:
                rank = -1
            rank = 4 if rank >= 4 else rank
        if rank == 0 or rank == -1:
            real.append((account, rank))
        if rank == 1 or rank == 2:
            rank_2.append((account, rank))
        if rank == 3:
            rank_3.append((account, rank))
        if rank == 4:
            rank_4.append((account, rank))
    return real, rank_2, rank_3, rank_4


if __name__ == '__main__':
    # Build a list of commands to ensure the host is operational to scan
    verification_commands = [
        check_hostname(),
        system_health()
    ]
    for _ in verification_commands:
        if not _ == True:
            raise SystemError('unable to verify server')

    # Get data from source of truth
    f = open(f'/home/diablo/non_orphan_accounts')
    ssot = { 'users': [] }
    for line in f:
        ssot['users'].append(line.rstrip())

    ACCOUNTS = ssot['users']

    # Get data from local_ l_
    l_accounts = directory_scan('/home')
    for entry in l_accounts:
        try:
            name, uid, gid, st_atime, size = get_directory_info(entry, '/home/')
            LOCAL['accounts'][name] = {
                'uid': uid,
                'gid': gid,
                'st_atime': datetime.datetime.fromtimestamp(st_atime).strftime("%Y-%m-%d %I:%M:%S"),
                'size': size
            }
        except Exception as e:
            pass
    real, rank_2, rank_3, rank_4= process(LOCAL['accounts'], ACCOUNTS)
    print(len(rank_3), rank_3)