ima_comm()
{
{{with .IMA}}
measure_list=()
appraise_list=()
common_list=()

{{range .AppraiseList}}
appraise_list+=({{.}})
{{end}}

{{range .MeasureList}}
measure_list+=({{.}})
{{end}}

needReboot=false
packages=("ima-evm-utils" "digest-list-tools" "selinux-policy" "selinux-policy-targeted" "policycoreutils")
for pkg in "${packages[@]}"; do
    check_rpm_package ${pkg}
    if [ $? -eq 1 ]; then
        return 1
    fi
done

if [ -d /sys/firmware/efi ]; then
    grub_path=/boot/efi/EFI/openeuler/grub.cfg
else
    grub_path=/boot/grub2/grub.cfg
fi

rm_kernel_param()
{
    for param in "${@}"; do
        cmdline_contains_param=$(grep -q "${param}" /proc/cmdline && echo "true" || echo "false")
        grub_contains_param=$(grep "/vmlinuz-$(uname -r)" "${grub_path}" | grep -q "${param}" && echo "true" || echo "false")
        if [[ "$cmdline_contains_param" == "true" && "$grub_contains_param" == "true" ]]; then
            sed -i "s/ \<${param}\>//g" ${grub_path}
            needReboot=true
        elif [[ "$cmdline_contains_param" == "false" && "$grub_contains_param" == "true" ]]; then
            sed -i "s/ \<${param}\>//g" ${grub_path}
        elif [[ "$cmdline_contains_param" == "true" && "$grub_contains_param" == "false" ]]; then
            needReboot=true
        fi
    done
}

set_kernel_param()
{
    for param in "${@}"; do
        cmdline_contains_param=$(grep -q "${param}" /proc/cmdline && echo "true" || echo "false")
        grub_contains_param=$(grep "/vmlinuz-$(uname -r)" "${grub_path}" | grep -q "${param}" && echo "true" || echo "false")
        if [[ "$cmdline_contains_param" == "false" && "$grub_contains_param" == "false" ]]; then
            sed -i "/vmlinuz-$(uname -r)/ s/$/ ${param}/" "${grub_path}"
            needReboot=true
        elif [[ "$cmdline_contains_param" == "true" && "$grub_contains_param" == "false" ]]; then
            sed -i "/vmlinuz-$(uname -r)/ s/$/ ${param}/" "${grub_path}"
        elif [[ "$cmdline_contains_param" == "false" && "$grub_contains_param" == "true" ]]; then
            needReboot=true
        fi
    done
}

set_selinux_type()
{
    module_name=$(echo "$1" | awk -F'_' '{print $1 "_" $2}')
    semodule -l | grep $module_name > /dev/null
    if [ $? -eq 1 ]; then
        file=/tmp/${module_name}.cil
        cat <<EOF > $file
(type $1)
(roletype object_r $1)
(typeattributeset file_type ($1))
(allow domain $1 (file (append execmod ioctl mounton relabelfrom swapon watch_reads audit_access execute link open relabelto unlink watch_sb create execute_no_trans lock quotaon rename watch watch_with_perm entrypoint getattr map read setattr watch_mount write)))
EOF

        semodule -i $file
        echo "selinux type $1 has been successfully created"
        rm $file
    fi
    chcon -t $1 $2
}

restore_selinux_type()
{
    for type in "$@"; do
        find / -context "*${type}*" -exec restorecon -v {} \; &>/dev/null
    done
}

appraise_param=("ima_appraise=enforce" "ima_appraise_digest_list=digest-nometadata")
measure_param=("ima_digest_list_pcr=11" "ima_template=ima-ng")
measure_type=ima_measure_bprm_t
appraise_type=ima_appraise_bprm_t
all_type=ima_all_bprm_t
restore_selinux_type $measure_type $appraise_type $all_type

if [[ ${#appraise_list[@]} -eq 0 && ${#measure_list[@]} -eq 0 ]]; then
    rm_kernel_param "${appraise_param[@]}"
    rm_kernel_param "${measure_param[@]}"
elif [[ ${#appraise_list[@]} -gt 0 && ${#measure_list[@]} -gt 0 ]]; then
    set_kernel_param "${appraise_param[@]}"
    set_kernel_param "${measure_param[@]}"
elif [[ ${#appraise_list[@]} -gt 0 ]]; then
    rm_kernel_param "${measure_param[@]}"
    set_kernel_param "${appraise_param[@]}"
else
    rm_kernel_param "${appraise_param[@]}"
    set_kernel_param "${measure_param[@]}"
fi

if [[ $needReboot == "true" ]]; then
    echo "IMA startup parameters have been configured! It will take effect by rebooting."
    return 0
fi

unique() {
    echo "$@" | tr ' ' '\n' | sort -u | tr '\n' ' '
}

common_elements() {
    comm -12 <(printf "%s\n" $1 | sort) <(printf "%s\n" $2 | sort)
}

remove_common() {
    grep -Fvxf <(printf "%s\n" $2) <(printf "%s\n" $1)
}

unique_appraise_list=($(unique "${appraise_list[@]}"))
unique_measure_list=($(unique "${measure_list[@]}"))
common_list=($(common_elements "${unique_appraise_list[*]}" "${unique_measure_list[*]}"))
appraise_list=($(remove_common "${unique_appraise_list[*]}" "${common_list[*]}"))
measure_list=($(remove_common "${unique_measure_list[*]}" "${common_list[*]}"))
if [[ ${#common_list[@]} -eq 0 && ${#appraise_list[@]} -eq 0 && ${#measure_list[@]} -eq 0 ]]; then
    echo "IMA is disabled!"
    return 0
fi

for measure_file in "${measure_list[@]}"; do
    set_selinux_type $measure_type $measure_file
done

for appraise_file in "${appraise_list[@]}"; do
    set_selinux_type $appraise_type $appraise_file
done

for common_file in "${common_list[@]}"; do
    set_selinux_type $all_type $common_file
done

ima_policy=/sys/kernel/security/ima/policy
if [ ! -z "$(cat $ima_policy)" ]; then
    echo "IMA policy has been configured! It needs to restart to overwrite policy."
    return 0
fi

tmp_policy=/tmp/ima_policy
if [ -f $tmp_policy ]; then
    rm $tmp_policy
fi



if [[ ${#common_list[@]} -gt 0 || ${#appraise_list[@]} -gt 0 ]]; then
    echo "appraise func=DIGEST_LIST_CHECK appraise_type=imasig|modsig" >> $tmp_policy
    echo "IMA appraise has been successfully enabled! If you want to run some executable file which appraised by IMA, you need to 
1)generate digest list by gen_digest_lists
2)sign it with evmctl
3)import it to /sys/kernel/security/digest_list_data. Correspondingly, if you don't want it to be executed, import it to /sys/kernel/security/digest_list_data_del.
Here is an example:
1)gen_digest_lists -t metadata -f compact -i l:policy -o add -p -1  -m immutable -i I:/usr/bin/ls -d ./
2)evmctl ima_sign --key /path/to/ima.key -a sha256 <DIGEST_LIST_PATH>
3)echo <DIGEST_LIST_PATH> > /sys/kernel/security/ima/digest_list_data"
fi

if [[ ${#common_list[@]} -gt 0 || ${#measure_list[@]} -gt 0 ]]; then
    echo "measure func=DIGEST_LIST_CHECK" >> $tmp_policy
    echo "IMA measure has been successfully enabled!"
fi

if [[ ${#common_list[@]} -gt 0 ]]; then
    echo "appraise func=BPRM_CHECK obj_type=${all_type}" >> $tmp_policy
    echo "measure func=BPRM_CHECK obj_type=${all_type}" >> $tmp_policy
fi

if [[ ${#measure_list[@]} -gt 0 ]]; then
    echo "measure func=BPRM_CHECK obj_type=${measure_type}" >> $tmp_policy
fi

if [[ ${#appraise_list[@]} -gt 0 ]]; then
    echo "appraise func=BPRM_CHECK obj_type=${appraise_type}" >> $tmp_policy
fi

echo $tmp_policy >> $ima_policy
rm $tmp_policy


{{end}}
}
