HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux mail.btech-izolacje.pl 5.15.0-140-generic #150-Ubuntu SMP Sat Apr 12 06:00:09 UTC 2025 x86_64
User: pewna6876 (1017)
PHP: 8.2.28
Disabled: NONE
Upload Files
File: //bin/i360-storage-new
#!/opt/imunify360/venv/bin/python
#
# i360-storage-new      Python script to compile rules for appropriate
#                       proactive module version.
#

import argparse
import os
from os import path
import logging
import time
import shutil
import subprocess
import sys
import tempfile


VERSION = '8.4'
SRC = "/var/imunify360/files/proactive/rules/%s" % VERSION
DEST = "/usr/share/i360-php-opts/sigs/%s" % VERSION
TOOL = "/usr/bin/i360-storage.v2"
MUST_HAVE_ITEMS = ('rules.yaml',
                   'params_pattern_list',
                   'rce_patterns_list')
RESULT_V1 = [ '.rules', '.rulesdump' ]
RESULT_V2 = '.rules.v2'
TOOL_OLD = "/usr/bin/i360-storage.immunity"


def must_have_items_check(silently_skip):
    if not path.exists(SRC):
        sys.exit(0 if silently_skip else
                 "ERROR: directory '%s' does not EXIST" % SRC)

    for item in MUST_HAVE_ITEMS:
        if not path.exists(path.join(SRC, item)):
            sys.exit(0 if silently_skip else
                     "ERROR: file '%s' is NOT FOUND in '%s' directory" % (item, SRC))


if __name__ == '__main__':
    ts_begin = time.time()
    logging.basicConfig(filename='/var/log/proactive_defense_compiler.log',
      filemode='w', level=logging.DEBUG, format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
    parser = argparse.ArgumentParser(description="compile PA rules [%s -> %s]" % (SRC, DEST))
    parser.add_argument("--silent-on-noop",
                        action="store_true",
                        help="do nothing if %s does not exist" % SRC)
    parser.add_argument("--optimize",
                        action="store_true",
                        default=False,
                        help="skip v1 compilation if v2 is available")
    args = parser.parse_args()

    skip_v1 = args.optimize
    must_have_items_check(args.silent_on_noop)
    tempdir = tempfile.mktemp(prefix='%s_tmpdir_' % path.basename(DEST),
                              dir=path.dirname(DEST))
    shutil.copytree(SRC, tempdir)
    os.chdir(tempdir)
    os.umask(0o022)

    result = []
    try:
        output = subprocess.check_output([TOOL, tempdir + '/.rules.v2', tempdir], stderr=subprocess.STDOUT, universal_newlines=True)
    except subprocess.CalledProcessError as e:
        # full backtrace is not needed for tool call error
        logging.critical('%s\n==================================' % e.output)
        if e.returncode == 2:
            skip_v1 = False
            print("ERROR: %s" % e)
        else:
            sys.exit("ERROR: %s" % e)
    else:
        result.append(RESULT_V2)

    if skip_v1 == False:
        try:
            output = subprocess.check_output(
                        [TOOL_OLD, 'mkbin'],
                        stderr=subprocess.STDOUT,
                        universal_newlines=True
                    )
            output = subprocess.check_output(
                        [TOOL_OLD,
                         'mkdump',
                         '.rules',
                         '.rulesdump'],
                        stderr=subprocess.STDOUT,
                        universal_newlines=True
                    )
        except subprocess.CalledProcessError as e:
            # full backtrace is not needed for tool call error
            logging.critical(
                    '%s\n==================================' % e.output
                    )
            sys.exit("ERROR: %s" % e)
        result.extend(RESULT_V1)

    os.makedirs(DEST, mode=0o755, exist_ok=True)
    for item in result:
        # get ready for atomic rewrite (copy + rename)
        tmpfn = tempfile.mktemp(suffix='_i360tmp', prefix=item, dir=DEST)
        # copy data and mode bits
        if os.path.exists(path.join(tempdir, item)):
            shutil.copy(path.join(tempdir, item), tmpfn)

            # that is Ok for .rulesdump + .rules to be handled not as a single step,
            # as far so far .rules is a fallback when we fail to mmap() .rulesdump
            os.rename(tmpfn, path.join(DEST, item))

    os.chdir(tempfile.gettempdir())  # chdir away from tempdir
    shutil.rmtree(tempdir)
    ts_end = time.time()
    logging.info("Success. Execution time %d s" % (ts_end - ts_begin))
    print("Success.")