Duplicate entries in Samba ACL

Hello everyone,

I have noticed that the ACLs of some files that are shared via samba contain a large number of duplicate entries. This leads to problems that I have described here.

This is such a ACL:

# File: /mnt/pvm/share/file.xlsx
# owner: 21156
# group: 20512
# mode: 0o100070
# trivial_acl: false
# ACL flags: none
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
group:domain\userxyz:rwxpDdaARWcCo-:------I:allow
            group@:rwxpDdaARWcCo-:------I:allow
group:domain\administrator:rwxpDdaARWcCo-:------I:allow
            group@:rwxpDdaARWcCo-:------I:allow
group:domain\group:rwxp-daARWc---:------I:allow

Does anyone have any idea how the ACLs of these files could be cleaned up? I’m running TrueNAS Scale Dragonfish-24.04.2.3.

Best regards!

I was able to solve this problem with two scripts that I would like to share in case anyone encounters this problem. I was able to solve my problem with them, but please be careful with these scripts and make sure you have a backup.

The first script identifies *.xls and *.xlsx files with duplicate ACE in their ACL and writes the full paths into a txt-file.

#!/bin/bash

# Directory where files with duplicate ACL entries will be checked
DIR="/mnt/pvm/users/roland"

# File to store the results
OUTPUT_FILE="files_with_duplicate_acls.txt"
> "$OUTPUT_FILE"  # Clear or create the file

# Function to check for duplicate ACL entries
check_for_duplicate_acls() {
    local file="$1"

    # Read the ACL, sort it, and check for duplicate entries
    if nfs4xdr_getfacl "$file" | awk '/^group:/ || /^owner@:/ || /^user:/ || /^everyone@:/ {print}' | sort | uniq -d | grep -q .; then
        # If duplicates are found, add the file to the result list
        echo "$file" >> "$OUTPUT_FILE"
    fi
}

# Iterate through all .xls and .xlsx files in the specified directory and subdirectories
find "$DIR" -type f \( -name "*.xls" -o -name "*.xlsx" \) | while read -r file; do
    check_for_duplicate_acls "$file"
done

echo "Check completed. Files with duplicate ACL entries have been saved in $OUTPUT_FILE."

The second script uses the list to alter the ACL of these files.

#!/bin/bash

# Path to the list of files to process (please adjust)
FILE_LIST="files_with_duplicate_acls.txt"

# Check if the file exists
if [[ ! -f "$FILE_LIST" ]]; then
    echo "File list $FILE_LIST not found. Please check the path."
    exit 1
fi

# Loop over all files in the list
while IFS= read -r FILE; do

    # Check if the file exists
    if [[ ! -f "$FILE" ]]; then
        echo "File $FILE does not exist, skipping."
        continue
    fi

    # Temporary files for the ACL backup and cleaned ACL
    TEMP_ACL=$(mktemp)
    SORTED_ACL=$(mktemp)

    # Export the original ACL and save temporarily
    nfs4xdr_getfacl "$FILE" > "$TEMP_ACL"

    # Check if the ACL was successfully exported
    if [ $? -ne 0 ]; then
        echo "Error reading the ACL from $FILE"
        rm "$TEMP_ACL" "$SORTED_ACL"
        continue
    fi

    # Remove duplicate ACEs with sort and uniq
    grep -E '^(group:|owner@:|user:|everyone@:)' "$TEMP_ACL" | sort | uniq > "$SORTED_ACL"

    # Retain header lines and assemble the cleaned ACL
    grep -vE '^(group:|owner@:|user:|everyone@:)' "$TEMP_ACL" > "$TEMP_ACL.header"
    cat "$TEMP_ACL.header" "$SORTED_ACL" > "$TEMP_ACL.cleaned"

    # Backup the original ACL
    cp "$TEMP_ACL" "$FILE.acl.bak"
    echo "Backup of the ACL for $FILE saved as $FILE.acl.bak"

    # Apply the cleaned ACL
    nfs4xdr_setfacl -S "$TEMP_ACL.cleaned" "$FILE"

    # Check if the ACL was successfully applied
    if [ $? -eq 0 ]; then
        echo "Duplicates removed from the ACL of $FILE and ACL successfully updated."
        # Delete the backup since the application was successful
        rm "$FILE.acl.bak"
    else
        echo "Error applying the ACL for $FILE. Backup will be retained."
    fi

    # Delete temporary files
    rm "$TEMP_ACL" "$SORTED_ACL" "$TEMP_ACL.header" "$TEMP_ACL.cleaned"

done < "$FILE_LIST"