diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2022-08-04 17:58:50 +0300 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2022-08-05 13:02:11 +0300 |
commit | 007e23d6390af11582e55453269b7a51c723d2dd (patch) | |
tree | 8e8cff3ca23f5e56d9766a5ee6c6abb366611b07 /winsup/cygwin/security.cc | |
parent | 1e428bee1c5ef7c76ba4e46e6693b913edc9bbf3 (diff) |
Cygwin: Reorganize cygwin source dir
Create subdirs and move files accordingly:
- DevDocs: doc files
- fhandler: fhandler sources, split fhandler.cc into base.cc and null.cc
- local_includes: local include files
- scripts: scripts called during build
- sec: security sources
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diffstat (limited to 'winsup/cygwin/security.cc')
-rw-r--r-- | winsup/cygwin/security.cc | 748 |
1 files changed, 0 insertions, 748 deletions
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc deleted file mode 100644 index 04e777852..000000000 --- a/winsup/cygwin/security.cc +++ /dev/null @@ -1,748 +0,0 @@ -/* security.cc: NT file access control functions - - Originaly written by Gunther Ebert, gunther.ebert@ixos-leipzig.de - Completely rewritten by Corinna Vinschen <corinna@vinschen.de> - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#include "winsup.h" -#include <unistd.h> -#include <stdlib.h> -#include <cygwin/acl.h> -#include "cygerrno.h" -#include "security.h" -#include "path.h" -#include "fhandler.h" -#include "dtable.h" -#include "pinfo.h" -#include "cygheap.h" -#include "ntdll.h" -#include "tls_pbuf.h" -#include <aclapi.h> - -#define ALL_SECURITY_INFORMATION (DACL_SECURITY_INFORMATION \ - | GROUP_SECURITY_INFORMATION \ - | OWNER_SECURITY_INFORMATION) - -static GENERIC_MAPPING NO_COPY_RO file_mapping = { FILE_GENERIC_READ, - FILE_GENERIC_WRITE, - FILE_GENERIC_EXECUTE, - FILE_ALL_ACCESS }; -LONG -get_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd, - bool justcreated) -{ - NTSTATUS status = STATUS_SUCCESS; - OBJECT_ATTRIBUTES attr; - IO_STATUS_BLOCK io; - ULONG len = SD_MAXIMUM_SIZE, rlen; - - /* Allocate space for the security descriptor. */ - if (!sd.malloc (len)) - { - set_errno (ENOMEM); - return -1; - } - /* Try to fetch the security descriptor if the handle is valid. */ - if (fh) - { - status = NtQuerySecurityObject (fh, ALL_SECURITY_INFORMATION, - sd, len, &rlen); - if (!NT_SUCCESS (status)) - debug_printf ("NtQuerySecurityObject (%S), status %y", - pc.get_nt_native_path (), status); - } - /* If the handle was NULL, or fetching with the original handle didn't work, - try to reopen the file with READ_CONTROL and fetch the security descriptor - using that handle. */ - if (!fh || !NT_SUCCESS (status)) - { - status = NtOpenFile (&fh, READ_CONTROL, - fh ? pc.init_reopen_attr (attr, fh) - : pc.get_object_attr (attr, sec_none_nih), - &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT - | pc.is_known_reparse_point () - ? FILE_OPEN_REPARSE_POINT : 0); - if (!NT_SUCCESS (status)) - { - sd.free (); - __seterrno_from_nt_status (status); - return -1; - } - status = NtQuerySecurityObject (fh, ALL_SECURITY_INFORMATION, - sd, len, &rlen); - NtClose (fh); - if (!NT_SUCCESS (status)) - { - sd.free (); - __seterrno_from_nt_status (status); - return -1; - } - } - /* We have a security descriptor now. Unfortunately, if you want to know - if an ACE is inherited from the parent object, this isn't sufficient. - - In the simple case, the SDs control word contains one of the - SE_DACL_AUTO_INHERITED or SE_DACL_PROTECTED flags, or at least one of - the ACEs has the INHERITED_ACE flag set. In all of these cases we - know the DACL has been inherited. - - If none of these flags is set in the SD, the information whether - or not an ACE has been inherited is not available in the DACL of the - object. In this case GetSecurityInfo fetches the SD from the parent - directory and tests if the object's SD contains inherited ACEs from the - parent. - - Note that we're not testing the SE_DACL_AUTO_INHERITED and - SE_DACL_PROTECTED flags here because we know the state the file's SD - is in. Since we're creating all files with a NULL descriptor, the DACL - is either inherited from the parent, or it's the default DACL. In - neither case, one of these flags is set. - - For speed, we're not calling RtlConvertToAutoInheritSecurityObject - anymore (but keep the code here for reference). Rather we just test - if one of the parent's ACEs is inheritable. If so, we know we inherited - it and set the SE_DACL_AUTO_INHERITED flag. If not, we may assume our - object's DACL is the default DACL. - - This functionality is slow and the extra information is only required - when the file has been created and the permissions are about to be set - to POSIX permissions. Therefore we only use it in case the file just - got created. */ - if (justcreated) - { - PACL dacl; - BOOLEAN exists, def; - ACCESS_ALLOWED_ACE *ace; - UNICODE_STRING dirname; - PSECURITY_DESCRIPTOR psd; - tmp_pathbuf tp; - - /* Open the parent directory with READ_CONTROL... */ - RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, NULL); - InitializeObjectAttributes (&attr, &dirname, pc.objcaseinsensitive (), - NULL, NULL); - status = NtOpenFile (&fh, READ_CONTROL, &attr, &io, - FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT - | FILE_OPEN_REPARSE_POINT); - if (!NT_SUCCESS (status)) - { - debug_printf ("NtOpenFile (%S), status %y", &dirname, status); - return 0; - } - /* ... fetch the parent's security descriptor ... */ - psd = (PSECURITY_DESCRIPTOR) tp.w_get (); - status = NtQuerySecurityObject (fh, ALL_SECURITY_INFORMATION, - psd, len, &rlen); - NtClose (fh); - if (!NT_SUCCESS (status)) - { - debug_printf ("NtQuerySecurityObject (%S), status %y", - &dirname, status); - return 0; - } -#if 0 - /* ... and create a new security descriptor in which all inherited ACEs - are marked with the INHERITED_ACE flag. For a description of the - undocumented RtlConvertToAutoInheritSecurityObject function from - ntdll.dll see the MSDN man page for the advapi32 function - ConvertToAutoInheritPrivateObjectSecurity. Fortunately the latter - is just a shim. */ - PSECURITY_DESCRIPTOR nsd; - status = RtlConvertToAutoInheritSecurityObject (psd, sd, &nsd, NULL, - pc.isdir (), - &file_mapping); - if (!NT_SUCCESS (status)) - { - debug_printf ("RtlConvertToAutoInheritSecurityObject (%S), status %y", - &dirname, status); - return 0; - } - /* Eventually copy the new security descriptor into sd and delete the - original one created by RtlConvertToAutoInheritSecurityObject from - the heap. */ - len = RtlLengthSecurityDescriptor (nsd); - memcpy ((PSECURITY_DESCRIPTOR) sd, nsd, len); - RtlDeleteSecurityObject (&nsd); -#else - /* ... and check the parent descriptor for inheritable ACEs matching - our current object type (file/dir). The simple truth in our case - is, either the parent dir had inheritable ACEs and all our ACEs are - inherited, or the parent dir didn't have inheritable ACEs and all - our ACEs are taken from the default DACL. */ - bool inherited = false; - BYTE search_flags = pc.isdir () ? SUB_CONTAINERS_AND_OBJECTS_INHERIT - : SUB_OBJECTS_ONLY_INHERIT; - if (NT_SUCCESS (RtlGetDaclSecurityDescriptor (psd, &exists, &dacl, &def)) - && exists && dacl) - for (ULONG idx = 0; idx < dacl->AceCount; ++idx) - if (NT_SUCCESS (RtlGetAce (dacl, idx, (PVOID *) &ace)) - && (ace->Header.AceFlags & search_flags)) - { - inherited = true; - break; - } - /* Then, if the parent descriptor contained inheritable ACEs, we mark - the SD as SE_DACL_AUTO_INHERITED. Note that this requires the - matching check in get_posix_access. If we ever revert to - RtlConvertToAutoInheritSecurityObject, the check in get_posix_access - has to test every single ACE for the INHERITED_ACE flag again. */ - if (inherited - && NT_SUCCESS (RtlGetDaclSecurityDescriptor (sd, &exists, &dacl, - &def)) - && exists && dacl) - RtlSetControlSecurityDescriptor (sd, SE_DACL_AUTO_INHERITED, - SE_DACL_AUTO_INHERITED); -#endif - } - return 0; -} - -LONG -set_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd, bool is_chown) -{ - NTSTATUS status = STATUS_SUCCESS; - int retry = 0; - int res = -1; - - for (; retry < 2; ++retry) - { - if (fh) - { - status = NtSetSecurityObject (fh, - is_chown ? ALL_SECURITY_INFORMATION - : DACL_SECURITY_INFORMATION, - sd); - if (NT_SUCCESS (status)) - { - res = 0; - break; - } - } - if (!retry) - { - OBJECT_ATTRIBUTES attr; - IO_STATUS_BLOCK io; - status = NtOpenFile (&fh, (is_chown ? WRITE_OWNER : 0) | WRITE_DAC, - fh ? pc.init_reopen_attr (attr, fh) - : pc.get_object_attr (attr, sec_none_nih), - &io, - FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT - | pc.is_known_reparse_point () - ? FILE_OPEN_REPARSE_POINT : 0); - if (!NT_SUCCESS (status)) - { - fh = NULL; - break; - } - } - } - if (retry && fh) - NtClose (fh); - if (!NT_SUCCESS (status)) - __seterrno_from_nt_status (status); - return res; -} - -static int -get_reg_sd (HANDLE handle, security_descriptor &sd_ret) -{ - LONG ret; - DWORD len = 0; - - ret = RegGetKeySecurity ((HKEY) handle, ALL_SECURITY_INFORMATION, - sd_ret, &len); - if (ret == ERROR_INSUFFICIENT_BUFFER) - { - if (!sd_ret.malloc (len)) - set_errno (ENOMEM); - else - ret = RegGetKeySecurity ((HKEY) handle, ALL_SECURITY_INFORMATION, - sd_ret, &len); - } - if (ret != ERROR_SUCCESS) - { - __seterrno (); - return -1; - } - return 0; -} - -int -get_reg_attribute (HKEY hkey, mode_t *attribute, uid_t *uidret, - gid_t *gidret) -{ - security_descriptor sd; - - if (!get_reg_sd (hkey, sd)) - { - get_posix_access (sd, attribute, uidret, gidret, NULL, 0); - return 0; - } - /* The entries are already set to default values */ - return -1; -} - -int -get_file_attribute (HANDLE handle, path_conv &pc, - mode_t *attribute, uid_t *uidret, gid_t *gidret) -{ - if (pc.has_acls ()) - { - security_descriptor sd; - - if (!get_file_sd (handle, pc, sd, false)) - { - get_posix_access (sd, attribute, uidret, gidret, NULL, 0); - return 0; - } - /* ENOSYS is returned by get_file_sd if fetching the DACL from a remote - share returns STATUS_INVALID_NETWORK_RESPONSE, which in turn is - converted to ERROR_BAD_NET_RESP. This potentially occurs when trying - to fetch DACLs from a NT4 machine which is not part of the domain of - the requesting machine. */ - else if (get_errno () != ENOSYS) - { - if (uidret) - *uidret = ILLEGAL_UID; - if (gidret) - *gidret = ILLEGAL_GID; - - return -1; - } - } - - if (uidret) - *uidret = myself->uid; - if (gidret) - *gidret = myself->gid; - - return -1; -} - -bool -add_access_allowed_ace (PACL acl, DWORD attributes, PSID sid, size_t &len_add, - DWORD inherit) -{ - NTSTATUS status = RtlAddAccessAllowedAceEx (acl, ACL_REVISION, inherit, - attributes, sid); - if (!NT_SUCCESS (status)) - { - __seterrno_from_nt_status (status); - return false; - } - len_add += sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD) + RtlLengthSid (sid); - return true; -} - -bool -add_access_denied_ace (PACL acl, DWORD attributes, PSID sid, size_t &len_add, - DWORD inherit) -{ - NTSTATUS status = RtlAddAccessDeniedAceEx (acl, ACL_REVISION, inherit, - attributes, sid); - if (!NT_SUCCESS (status)) - { - __seterrno_from_nt_status (status); - return false; - } - len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD) + RtlLengthSid (sid); - return true; -} - -void -set_security_attribute (path_conv &pc, int attribute, PSECURITY_ATTRIBUTES psa, - security_descriptor &sd) -{ - psa->lpSecurityDescriptor = sd.malloc (SECURITY_DESCRIPTOR_MIN_LENGTH); - RtlCreateSecurityDescriptor ((PSECURITY_DESCRIPTOR) psa->lpSecurityDescriptor, - SECURITY_DESCRIPTOR_REVISION); - psa->lpSecurityDescriptor = set_posix_access (attribute, geteuid (), - getegid (), NULL, 0, - sd, false); -} - -int -get_object_sd (HANDLE handle, security_descriptor &sd) -{ - ULONG len = 0; - NTSTATUS status; - - status = NtQuerySecurityObject (handle, ALL_SECURITY_INFORMATION, - sd, len, &len); - if (status != STATUS_BUFFER_TOO_SMALL) - { - __seterrno_from_nt_status (status); - return -1; - } - if (!sd.malloc (len)) - { - set_errno (ENOMEM); - return -1; - } - status = NtQuerySecurityObject (handle, ALL_SECURITY_INFORMATION, - sd, len, &len); - if (!NT_SUCCESS (status)) - { - __seterrno_from_nt_status (status); - return -1; - } - return 0; -} - -int -get_object_attribute (HANDLE handle, uid_t *uidret, gid_t *gidret, - mode_t *attribute) -{ - security_descriptor sd; - - if (get_object_sd (handle, sd)) - return -1; - return get_posix_access (sd, attribute, uidret, gidret, NULL, 0) - >= 0 ? 0 : -1; -} - -int -create_object_sd_from_attribute (uid_t uid, gid_t gid, mode_t attribute, - security_descriptor &sd) -{ - return set_posix_access (attribute, uid, gid, NULL, 0, sd, false) - ? 0 : -1; -} - -int -set_object_sd (HANDLE handle, security_descriptor &sd, bool chown) -{ - NTSTATUS status; - status = NtSetSecurityObject (handle, chown ? ALL_SECURITY_INFORMATION - : DACL_SECURITY_INFORMATION, sd); - if (!NT_SUCCESS (status)) - { - __seterrno_from_nt_status (status); - return -1; - } - return 0; -} - -int -set_object_attribute (HANDLE handle, uid_t uid, gid_t gid, mode_t attribute) -{ - security_descriptor sd; - - if (create_object_sd_from_attribute (uid, gid, attribute, sd) - || set_object_sd (handle, sd, uid != ILLEGAL_UID || gid != ILLEGAL_GID)) - return -1; - return 0; -} - -int -set_created_file_access (HANDLE handle, path_conv &pc, mode_t attr) -{ - int ret = -1; - security_descriptor sd, sd_ret; - mode_t attr_rd; - uid_t uid; - gid_t gid; - tmp_pathbuf tp; - aclent_t *aclp; - int nentries, idx; - bool std_acl; - - if (!get_file_sd (handle, pc, sd, true)) - { - attr |= S_JUSTCREATED; - if (pc.isdir ()) - attr |= S_IFDIR; - attr_rd = attr; - aclp = (aclent_t *) tp.c_get (); - if ((nentries = get_posix_access (sd, &attr_rd, &uid, &gid, aclp, - MAX_ACL_ENTRIES, &std_acl)) >= 0) - { - if (S_ISLNK (attr)) - { - /* Symlinks always get the request POSIX perms. */ - aclp[0].a_perm = (attr >> 6) & S_IRWXO; - if ((idx = searchace (aclp, nentries, GROUP_OBJ)) >= 0) - aclp[idx].a_perm = (attr >> 3) & S_IRWXO; - if ((idx = searchace (aclp, nentries, CLASS_OBJ)) >= 0) - aclp[idx].a_perm = (attr >> 3) & S_IRWXO; - if ((idx = searchace (aclp, nentries, OTHER_OBJ)) >= 0) - aclp[idx].a_perm = attr & S_IRWXO; - } - else - { - /* Overwrite ACL permissions as required by POSIX 1003.1e - draft 17. */ - aclp[0].a_perm &= (attr >> 6) & S_IRWXO; - if ((idx = searchace (aclp, nentries, CLASS_OBJ)) >= 0) - aclp[idx].a_perm &= (attr >> 3) & S_IRWXO; - if (std_acl - && (idx = searchace (aclp, nentries, GROUP_OBJ)) >= 0) - aclp[idx].a_perm &= (attr >> 3) & S_IRWXO; - if ((idx = searchace (aclp, nentries, OTHER_OBJ)) >= 0) - aclp[idx].a_perm &= attr & S_IRWXO; - } - /* Construct appropriate inherit attribute for new directories. - Basically we do this only for the sake of non-Cygwin applications. - Cygwin applications don't need these. Additionally, if the - S_ISGID bit is set, propagate it. */ - if (S_ISDIR (attr)) - { - if (searchace (aclp, nentries, DEF_USER_OBJ) < 0) - { - aclp[nentries].a_type = DEF_USER_OBJ; - aclp[nentries].a_id = ILLEGAL_UID; - aclp[nentries++].a_perm = (attr >> 6) & S_IRWXO; - } - if (searchace (aclp, nentries, DEF_GROUP_OBJ) < 0) - { - aclp[nentries].a_type = DEF_GROUP_OBJ; - aclp[nentries].a_id = ILLEGAL_GID; - aclp[nentries++].a_perm = (attr >> 3) & S_IRWXO; - } - if (searchace (aclp, nentries, DEF_OTHER_OBJ) < 0) - { - aclp[nentries].a_type = DEF_OTHER_OBJ; - aclp[nentries].a_id = ILLEGAL_UID; - aclp[nentries++].a_perm = attr & S_IRWXO; - } - if (attr_rd & S_ISGID) - attr |= S_ISGID; - } - if (set_posix_access (attr, uid, gid, aclp, nentries, sd_ret, - pc.fs_is_samba ())) - ret = set_file_sd (handle, pc, sd_ret, attr_rd & S_ISGID); - } - } - return ret; -} - -static int -check_access (security_descriptor &sd, GENERIC_MAPPING &mapping, - ACCESS_MASK desired, int flags, bool effective) -{ - int ret = -1; - NTSTATUS status, allow; - ACCESS_MASK granted; - DWORD plen = sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES); - PPRIVILEGE_SET pset = (PPRIVILEGE_SET) alloca (plen); - HANDLE tok = ((effective && cygheap->user.issetuid ()) - ? cygheap->user.imp_token () - : hProcImpToken); - - if (!tok) - { - if (!DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL, - SecurityImpersonation, TokenImpersonation, - &hProcImpToken)) - { - __seterrno (); - return ret; - } - tok = hProcImpToken; - } - - status = NtAccessCheck (sd, tok, desired, &mapping, pset, &plen, &granted, - &allow); - if (!NT_SUCCESS (status)) - __seterrno (); - else if (!NT_SUCCESS (allow)) - { - /* CV, 2006-10-16: Now, that's really weird. Imagine a user who has no - standard access to a file, but who has backup and restore privileges - and these privileges are enabled in the access token. One would - expect that the AccessCheck function takes this into consideration - when returning the access status. Otherwise, why bother with the - pset parameter, right? - But not so. AccessCheck actually returns a status of "false" here, - even though opening a file with backup resp. restore intent - naturally succeeds for this user. This definitely spoils the results - of access(2) for administrative users or the SYSTEM account. So, in - case the access check fails, another check against the user's - backup/restore privileges has to be made. Sigh. */ - int granted_flags = 0; - BOOLEAN has_priv; - - if (flags & R_OK) - { - pset->PrivilegeCount = 1; - pset->Control = 0; - pset->Privilege[0].Luid.HighPart = 0L; - pset->Privilege[0].Luid.LowPart = SE_BACKUP_PRIVILEGE; - pset->Privilege[0].Attributes = 0; - status = NtPrivilegeCheck (tok, pset, &has_priv); - if (NT_SUCCESS (status) && has_priv) - granted_flags |= R_OK; - } - if (flags & W_OK) - { - pset->PrivilegeCount = 1; - pset->Control = 0; - pset->Privilege[0].Luid.HighPart = 0L; - pset->Privilege[0].Luid.LowPart = SE_RESTORE_PRIVILEGE; - pset->Privilege[0].Attributes = 0; - status = NtPrivilegeCheck (tok, pset, &has_priv); - if (NT_SUCCESS (status) && has_priv) - granted_flags |= W_OK; - } - if (granted_flags == flags) - ret = 0; - else - set_errno (EACCES); - } - else - ret = 0; - return ret; -} - -/* Samba override. Check security descriptor for Samba UNIX user and group - accounts and check if we have an RFC 2307 mapping to a Windows account. - Create a new security descriptor with all of the UNIX accounts with - valid mapping replaced with their Windows counterpart. */ -static void -convert_samba_sd (security_descriptor &sd_ret) -{ - NTSTATUS status; - BOOLEAN dummy; - PSID sid; - cygsid owner; - cygsid group; - SECURITY_DESCRIPTOR sd; - cyg_ldap cldap; - tmp_pathbuf tp; - PACL acl, oacl; - size_t acl_len; - PACCESS_ALLOWED_ACE ace; - - if (!NT_SUCCESS (RtlGetOwnerSecurityDescriptor (sd_ret, &sid, &dummy))) - return; - owner = sid; - if (!NT_SUCCESS (RtlGetGroupSecurityDescriptor (sd_ret, &sid, &dummy))) - return; - group = sid; - - if (sid_id_auth (owner) == 22) - { - struct passwd *pwd; - uid_t uid = owner.get_uid (&cldap); - if (uid < UNIX_POSIX_OFFSET && (pwd = internal_getpwuid (uid))) - owner.getfrompw (pwd); - } - if (sid_id_auth (group) == 22) - { - struct group *grp; - gid_t gid = group.get_gid (&cldap); - if (gid < UNIX_POSIX_OFFSET && (grp = internal_getgrgid (gid))) - group.getfromgr (grp); - } - - if (!NT_SUCCESS (RtlGetDaclSecurityDescriptor (sd_ret, &dummy, - &oacl, &dummy))) - return; - acl = (PACL) tp.w_get (); - RtlCreateAcl (acl, ACL_MAXIMUM_SIZE, ACL_REVISION); - acl_len = sizeof (ACL); - - for (DWORD i = 0; i < oacl->AceCount; ++i) - if (NT_SUCCESS (RtlGetAce (oacl, i, (PVOID *) &ace))) - { - cygsid ace_sid ((PSID) &ace->SidStart); - if (sid_id_auth (ace_sid) == 22) - { - if (sid_sub_auth (ace_sid, 0) == 1) /* user */ - { - struct passwd *pwd; - uid_t uid = ace_sid.get_uid (&cldap); - if (uid < UNIX_POSIX_OFFSET && (pwd = internal_getpwuid (uid))) - ace_sid.getfrompw (pwd); - } - else if (sid_sub_auth (ace_sid, 0) == 2) /* group */ - { - struct group *grp; - gid_t gid = ace_sid.get_gid (&cldap); - if (gid < UNIX_POSIX_OFFSET && (grp = internal_getgrgid (gid))) - ace_sid.getfromgr (grp); - } - } - if (!add_access_allowed_ace (acl, ace->Mask, ace_sid, acl_len, - ace->Header.AceFlags)) - return; - } - acl->AclSize = acl_len; - - RtlCreateSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION); - RtlSetControlSecurityDescriptor (&sd, SE_DACL_PROTECTED, SE_DACL_PROTECTED); - RtlSetOwnerSecurityDescriptor (&sd, owner, FALSE); - RtlSetGroupSecurityDescriptor (&sd, group, FALSE); - - status = RtlSetDaclSecurityDescriptor (&sd, TRUE, acl, FALSE); - if (!NT_SUCCESS (status)) - return; - DWORD sd_size = 0; - status = RtlAbsoluteToSelfRelativeSD (&sd, sd_ret, &sd_size); - if (sd_size > 0 && sd_ret.malloc (sd_size)) - RtlAbsoluteToSelfRelativeSD (&sd, sd_ret, &sd_size); -} - -int -check_file_access (path_conv &pc, int flags, bool effective) -{ - security_descriptor sd; - int ret = -1; - ACCESS_MASK desired = 0; - if (flags & R_OK) - desired |= FILE_READ_DATA; - if (flags & W_OK) - desired |= FILE_WRITE_DATA; - if (flags & X_OK) - desired |= FILE_EXECUTE; - if (!get_file_sd (pc.handle (), pc, sd, false)) - { - /* Tweak Samba security descriptor as necessary. */ - if (pc.fs_is_samba ()) - convert_samba_sd (sd); - ret = check_access (sd, file_mapping, desired, flags, effective); - } - debug_printf ("flags %y, ret %d", flags, ret); - return ret; -} - -int -check_registry_access (HANDLE hdl, int flags, bool effective) -{ - security_descriptor sd; - int ret = -1; - static GENERIC_MAPPING NO_COPY_RO reg_mapping = { KEY_READ, - KEY_WRITE, - KEY_EXECUTE, - KEY_ALL_ACCESS }; - ACCESS_MASK desired = 0; - if (flags & R_OK) - desired |= KEY_ENUMERATE_SUB_KEYS; - if (flags & W_OK) - desired |= KEY_SET_VALUE; - if (flags & X_OK) - desired |= KEY_QUERY_VALUE; - - if ((HKEY) hdl == HKEY_PERFORMANCE_DATA) - /* RegGetKeySecurity() always fails with ERROR_INVALID_HANDLE. */ - ret = 0; - else if (!get_reg_sd (hdl, sd)) - ret = check_access (sd, reg_mapping, desired, flags, effective); - - /* As long as we can't write the registry... */ - if (flags & W_OK) - { - set_errno (EROFS); - ret = -1; - } - debug_printf ("flags %y, ret %d", flags, ret); - return ret; -} |