island: Split has_expected_permissions() into os-specific functions

This commit is contained in:
Mike Salvatore 2021-06-09 09:47:23 -04:00
parent dc8e2b018d
commit 945e1adf58
1 changed files with 44 additions and 37 deletions

View File

@ -9,45 +9,52 @@ def expand_path(path: str) -> str:
def has_expected_permissions(path: str, expected_permissions: int) -> bool:
if is_windows_os():
# checks that admin has any permissions, user has `expected_permissions`,
# and everyone else has no permissions
return _has_expected_windows_permissions(path, expected_permissions)
import win32api # noqa: E402
import win32security # noqa: E402
return _has_expected_linux_permissions(path, expected_permissions)
FULL_CONTROL = 2032127
ACE_TYPE_ALLOW = 0
ACE_TYPE_DENY = 1
admins_sid, _, _ = win32security.LookupAccountName("", "Administrators")
user_sid, _, _ = win32security.LookupAccountName("", win32api.GetUserName())
security_descriptor = win32security.GetNamedSecurityInfo(
path, win32security.SE_FILE_OBJECT, win32security.DACL_SECURITY_INFORMATION
)
acl = security_descriptor.GetSecurityDescriptorDacl()
for i in range(acl.GetAceCount()):
ace = acl.GetAce(i)
ace_type, _ = ace[0] # 0 for allow, 1 for deny
permissions = ace[1]
sid = ace[-1]
if sid == user_sid:
if not (permissions == expected_permissions and ace_type == ACE_TYPE_ALLOW):
return False
elif sid == admins_sid:
continue
# TODO: consider removing; so many system accounts/groups exist, it's likely to fail
else:
if not (permissions == FULL_CONTROL and ace_type == ACE_TYPE_DENY):
return False
return True
else:
file_mode = os.stat(path).st_mode
file_permissions = file_mode & 0o777
def _has_expected_linux_permissions(path: str, expected_permissions: int) -> bool:
file_mode = os.stat(path).st_mode
file_permissions = file_mode & 0o777
return file_permissions == expected_permissions
def _has_expected_windows_permissions(path: str, expected_permissions: int) -> bool:
# checks that admin has any permissions, user has `expected_permissions`,
# and everyone else has no permissions
import win32api # noqa: E402
import win32security # noqa: E402
FULL_CONTROL = 2032127
ACE_TYPE_ALLOW = 0
ACE_TYPE_DENY = 1
admins_sid, _, _ = win32security.LookupAccountName("", "Administrators")
user_sid, _, _ = win32security.LookupAccountName("", win32api.GetUserName())
security_descriptor = win32security.GetNamedSecurityInfo(
path, win32security.SE_FILE_OBJECT, win32security.DACL_SECURITY_INFORMATION
)
acl = security_descriptor.GetSecurityDescriptorDacl()
for i in range(acl.GetAceCount()):
ace = acl.GetAce(i)
ace_type, _ = ace[0] # 0 for allow, 1 for deny
permissions = ace[1]
sid = ace[-1]
if sid == user_sid:
if not (permissions == expected_permissions and ace_type == ACE_TYPE_ALLOW):
return False
elif sid == admins_sid:
continue
# TODO: consider removing; so many system accounts/groups exist, it's likely to fail
else:
if not (permissions == FULL_CONTROL and ace_type == ACE_TYPE_DENY):
return False
return True