MOON
Server: Apache
System: Linux vps.erhabenn.com.br 3.10.0-1160.119.1.el7.tuxcare.els2.x86_64 #1 SMP Mon Jul 15 12:09:18 UTC 2024 x86_64
User: machen (1008)
PHP: 8.2.31
Disabled: NONE
Upload Files
File: //opt/microsoft/omsagent/tst/modules/install/check_files.py
import os
import re
import subprocess

from error_codes import *
from errors      import error_info
from helpers     import geninfo_lookup
from .check_oms  import comp_versions_ge

# get files/directories/links from data files

def get_data(f, variables, files, links, dirs):
    curr_section = None
    with open(f, 'r') as data_file:
        for line in data_file:
            line = line.rstrip('\n')
            # skip comments
            cstart = line.find('#')
            if (cstart != -1):
                line = line[:cstart]

            # skip empty lines
            if (line == ''):
                continue            

            # new section
            if (line.startswith('%')):
                curr_section = line[1:]
                continue

            # line contains variable, needs to be replaced with content
            while ('${{' in line):
                vstart = line.index('${{')
                vend = line.index('}}') + 2
                l = line[vstart:vend]
                v = line[vstart+3:vend-2]
                if (v in list(variables.keys())):
                    line = line.replace(l, variables[v])
                else:
                    break

            # variable line
            if (curr_section == "Variables"):
                # parsed_line: [variable name, content]
                parsed_line = (line.replace(' ','')).split(':')
                variables[parsed_line[0]] = (parsed_line[1]).strip("'")
                continue

            # file line
            elif (curr_section == "Files"):
                # parsed_line: [filepath, install filepath, permissions, user, group]
                parsed_line = (line.replace(' ','')).split(';')
                files[parsed_line[0]] = parsed_line[2:5]
                continue

            # link line
            elif (curr_section == "Links"):
                # parsed_line: [filepath, install filepath, permissions, user, group]
                parsed_line = (line.replace(' ','')).split(';')
                links[parsed_line[0]] = parsed_line[2:5] + [parsed_line[1]]
                continue

            # directory line
            elif (curr_section == "Directories"):
                # parsed_line: [filepath, permissions, user, group]
                parsed_line = (line.replace(' ','')).split(';')
                dirs[parsed_line[0]] = parsed_line[1:4]
                continue

            # installation code
            else:
                # check for changes in owners or permissions
                if (line.startswith('chmod ')):
                    # parsed_line: ['chmod', (recursive,) new permissions, filepath]
                    parsed_line = line.split()
                    path = parsed_line[-1]
                    # skip over anything with undefined variables
                    if (not path.startswith('/')):
                        continue
                    new_perms = parsed_line[-2]
                    if (parsed_line[1] == '-R'):
                        # recursively apply new perms
                        for f in (files.keys()):
                            if (f.startswith(path)):
                                files[f][0] = new_perms
                        for l in (links.keys()):
                            if (l.startswith(path)):
                                links[l][0] = new_perms
                        for d in (dirs.keys()):
                            if (d.startswith(path)):
                                dirs[d][0]  = new_perms
                    else: # not recursive
                        if path in files:
                            files[path][0] = new_perms
                        elif path in links:
                            links[path][0] = new_perms
                        elif path in dirs:
                            dirs[path][0]  = new_perms




# Convert between octal permission and symbolic permission
def perm_oct_to_symb(p):
    binstr = ''
    for i in range(3):
        binstr += format(int(p[i]), '03b')
    symbstr = 'rwxrwxrwx'
    result = ''
    for j in range(9):
        if (binstr[j] == '0'):
            result += '-'
        else:
            result += symbstr[j]
    return result

def perm_symb_to_oct(p):
    binstr = ''
    for i in range(9):
        if (p[i] == '-'):
            binstr += '0'
        else:
            binstr += '1'
    result = ''
    for j in range(0,9,3):
        result += str(int(binstr[j:j+3], 2))
    return result



# Check permissions are correct for each file
# info: [permissions, user, group]
def check_permissions(f, perm_info, corr_info, typ, perms_err):
    success = NO_ERROR
    # check user
    perm_user = perm_info[1]
    corr_user = corr_info[1]
    if ((perm_user != corr_user) and (perm_user != 'omsagent')):
        perms_err.append((typ, f, 'user', perm_user, corr_user))
        success = WARN_FILE_PERMS
    
    # check group
    perm_group = perm_info[2]
    corr_group = corr_info[2]
    if ((perm_group != corr_group) and (perm_group != 'omiusers')):
        perms_err.append((typ, f, 'group', perm_group, corr_group))
        success = WARN_FILE_PERMS
    
    # check permissions
    perms = (perm_info[0])[1:].rstrip('.')
    corr_perms = perm_oct_to_symb(corr_info[0])
    if (perms != corr_perms):
        perms_err.append((typ, f, 'permissions', perms, corr_perms))
        success = WARN_FILE_PERMS
    return success
    


# Check directories exist

def get_ll_dir(ll_output, d):
    ll_lines = ll_output.split('\n')
    d_end = os.path.basename(d)
    ll_line = list(filter(lambda x : x.endswith(' ' + d_end), ll_lines))[0]
    return ll_line.split()

def check_dirs(dirs, exist_err, perms_err):
    success = NO_ERROR
    missing_dirs = []
    for d in (dirs.keys()):
        if (any(d.startswith(md) for md in missing_dirs)):
            # parent folder doesn't exist, skip checking child folder
            continue
        # check if folder exists
        elif (not os.path.isdir(d)):
            missing_dirs += d
            exist_err.append(('directory', d))
            success = ERR_FILE_MISSING
            continue
        # check if permissions are correct
        if (success != ERR_FILE_MISSING):
            # get permissions
            ll_output = subprocess.check_output(['ls', '-l', os.path.join(d, '..')],\
                            universal_newlines=True)
            # ll_info: [perms, items, user, group, size, month mod, day mod, time mod, name]
            ll_info = get_ll_dir(ll_output, d)
            perm_info = [ll_info[0]] + ll_info[2:4]
            corr_info = dirs[d]
            if (check_permissions(d, perm_info, corr_info, "directory", perms_err) != NO_ERROR):
                success = WARN_FILE_PERMS
    return success



# Check files exist

def check_files(files, exist_err, perms_err):
    success = NO_ERROR
    for f in (files.keys()):
        # check if file exists
        if (not os.path.isfile(f)):
            exist_err.append(('file', f))
            success = ERR_FILE_MISSING
            continue
        # check if permissions are correct
        if (success != ERR_FILE_MISSING):
            # get permissions
            ll_output = subprocess.check_output(['ls', '-l', f], universal_newlines=True)
            # ll_info: [perms, items, user, group, size, month mod, day mod, time mod, name]
            ll_info = ll_output.split()
            perm_info = [ll_info[0]] + ll_info[2:4]
            corr_info = files[f]
            if (check_permissions(f, perm_info, corr_info, "file", perms_err) != NO_ERROR):
                success = WARN_FILE_PERMS
    return success

            



# Check links exist

def check_links(links, exist_err, perms_err):
    success = True
    for l in (links.keys()):
        # check if link exists
        if (not os.path.islink(l)):
            exist_err.append(('link', l))
            success = ERR_FILE_MISSING
            continue
        # check if permissions are correct
        if (success != ERR_FILE_MISSING):
            linked_file = links[l][-1]
            # in case a link points to a link
            while (os.path.islink(linked_file)):
                linked_file = links[linked_file][-1]
            # get permissions
            if (os.path.isdir(linked_file)):
                ll_output = subprocess.check_output(['ls', '-l', os.path.join(linked_file, '..')],\
                                universal_newlines=True)
                ll_info = get_ll_dir(ll_output, linked_file)
            elif (os.path.isfile(linked_file)):
                ll_output = subprocess.check_output(['ls', '-l', linked_file],\
                                universal_newlines=True)
                ll_info = ll_output.split()
            # ll_info: [perms, items, user, group, size, month mod, day mod, time mod, name]
            perm_info = [ll_info[0]] + ll_info[2:4]
            corr_info = links[l][:-1]
            if (check_permissions(l, perm_info, corr_info, "link", perms_err) != NO_ERROR):
                success = WARN_FILE_PERMS
    return success





# Check everything

def check_filesystem(DFS_PATH):
    success = NO_ERROR

    # create lists to track errors
    exist_err = []
    perms_err = []

    datafiles = os.listdir(DFS_PATH)
    for df in datafiles:        
        variables = dict()  # {var name : content}
        files = dict()      # {path : [perms, user, group]}
        links = dict()      # {path : [perms, user, group, linked path]}
        dirs = dict()       # {path : [perms, user, group]}

        # TEMP FIX: add in variables for RUBY_ARCH and RUBY_ARCM
        if (df.endswith("ruby.data")):
            variables['RUBY_ARCH'] = 'x86_64-linux'
            variables['RUBY_ARCM'] = 'x86_64-linux'

        # TEMP FIX: look for specific directory if in linux_rpm.data
        if ((df == "linux_rpm.data") and (not os.path.exists('/usr/sbin/semodule'))):
            continue

        # populate dictionaries with info from data files
        get_data((os.path.join(DFS_PATH, df)), variables, files, links, dirs)

        # check everything
        checked_dirs = check_dirs(dirs, exist_err, perms_err)
        checked_files = check_files(files, exist_err, perms_err)
        checked_links = check_links(links, exist_err, perms_err)

        # some paths are missing
        if (ERR_FILE_MISSING in [checked_dirs, checked_files, checked_links]):
            success = ERR_FILE_MISSING

        # some paths have incorrect permissions
        elif ((WARN_FILE_PERMS in [checked_dirs, checked_files, checked_links]) and (success != ERR_FILE_MISSING)):
            success = WARN_FILE_PERMS

    # update errors
    if (success == ERR_FILE_MISSING):
        error_info.extend(exist_err)
    elif (success == WARN_FILE_PERMS):
        error_info.extend(perms_err)

    return success