Skip to content

Instantly share code, notes, and snippets.

@jessepeterson
Last active November 28, 2016 20:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jessepeterson/50d58d0de0e12345c42f8d34c1ce52dc to your computer and use it in GitHub Desktop.
Save jessepeterson/50d58d0de0e12345c42f8d34c1ce52dc to your computer and use it in GitHub Desktop.
Finds bad ACE qualifiers (user/group UUIDs) in ACLs on files on macOS. Takes a list of file/directory names on stdin.
#!/usr/bin/python
'''
Takes a list of file names/paths on stdin and checks to see if they have
unresolvable ACE entries in their ACLs. E.g. ACEs which have a non-resolvable
UUID on the system.
Usage:
find /some/file/path | /path/to/findbadacls.py
'''
import sys
import os
from ctypes import *
from ctypes.util import find_library
import uuid
from pipes import quote
libc = cdll.LoadLibrary(find_library('c'))
# from <sys/acl.h>
ACL_TYPE_EXTENDED = 0x00000100
ACL_FIRST_ENTRY = 0
ACL_NEXT_ENTRY = -1
ACL_LAST_ENTRY = -2
acl_get_file = libc.acl_get_file
acl_get_file.argtypes = [c_char_p, c_int]
acl_get_file.restype = c_void_p
acl_free = libc.acl_free
acl_free.argtypes = [c_void_p]
acl_free.restype = c_int
class ACLEntry(Structure):
pass
acl_get_entry = libc.acl_get_entry
acl_get_entry.argtypes = [c_void_p, c_int, POINTER(POINTER(ACLEntry))]
acl_get_entry.restype = c_int
acl_get_qualifier = libc.acl_get_qualifier
acl_get_qualifier.argtypes = [POINTER(ACLEntry)]
acl_get_qualifier.restype = POINTER(c_ubyte * 16)
mbr_uuid_to_id = libc.mbr_uuid_to_id
mbr_uuid_to_id.argtypes = [(c_ubyte * 16), POINTER(c_uint), POINTER(c_int)]
mbr_uuid_to_id.restype = c_int
for stdinline in sys.stdin:
if stdinline[-1] == '\n':
filename = stdinline[:-1]
if os.path.exists(filename):
acl = acl_get_file(filename, ACL_TYPE_EXTENDED)
entry = POINTER(ACLEntry)()
uid = c_uint()
idtype = c_int()
if acl:
bad_acls = []
ace_i = 0
while True:
if acl_get_entry(acl, ACL_FIRST_ENTRY if not entry else ACL_NEXT_ENTRY, byref(entry)) != 0:
break
q_uuid = acl_get_qualifier(entry)
p_uuid = uuid.UUID(bytes=''.join([chr(x) for x in q_uuid.contents[0:16]]))
if mbr_uuid_to_id(q_uuid.contents, byref(uid), byref(idtype)) != 0:
bad_acls.append(ace_i)
acl_free(q_uuid)
ace_i += 1
if bad_acls:
print '#', filename
bad_acls.reverse()
for ace_i in bad_acls:
print "/bin/chmod -a# %d %s" % (ace_i, quote(filename))
acl_free(acl)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment