1 /* security.cc: NT file access control functions
3 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007, 2008, 2009 Red Hat, Inc.
6 Originaly written by Gunther Ebert, gunther.ebert@ixos-leipzig.de
7 Completely rewritten by Corinna Vinschen <corinna@vinschen.de>
9 This file is part of Cygwin.
11 This software is a copyrighted work licensed under the terms of the
12 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
29 #define ALL_SECURITY_INFORMATION (DACL_SECURITY_INFORMATION \
30 | GROUP_SECURITY_INFORMATION \
31 | OWNER_SECURITY_INFORMATION)
34 get_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd)
36 DWORD error = ERROR_SUCCESS;
40 for (; retry < 2; ++retry)
44 /* Amazing but true. If you want to know if an ACE is inherited
45 from the parent object, you can't use the NtQuerySecurityObject
46 function. In the DACL returned by this functions, the
47 INHERITED_ACE flag is never set. Only by calling GetSecurityInfo
48 you get this information. Oh well. */
49 PSECURITY_DESCRIPTOR psd;
50 error = GetSecurityInfo (fh, SE_FILE_OBJECT, ALL_SECURITY_INFORMATION,
51 NULL, NULL, NULL, NULL, &psd);
52 if (error == ERROR_SUCCESS)
61 OBJECT_ATTRIBUTES attr;
65 status = NtOpenFile (&fh, READ_CONTROL,
66 pc.get_object_attr (attr, sec_none_nih),
67 &io, FILE_SHARE_VALID_FLAGS,
68 FILE_OPEN_FOR_BACKUP_INTENT);
69 if (!NT_SUCCESS (status))
72 error = RtlNtStatusToDosError (status);
79 if (error != ERROR_SUCCESS)
80 __seterrno_from_win_error (error);
85 set_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd, bool is_chown)
87 NTSTATUS status = STATUS_SUCCESS;
91 for (; retry < 2; ++retry)
95 status = NtSetSecurityObject (fh,
96 is_chown ? ALL_SECURITY_INFORMATION
97 : DACL_SECURITY_INFORMATION,
99 if (NT_SUCCESS (status))
107 OBJECT_ATTRIBUTES attr;
109 status = NtOpenFile (&fh, (is_chown ? WRITE_OWNER : 0) | WRITE_DAC,
110 pc.get_object_attr (attr, sec_none_nih),
111 &io, FILE_SHARE_VALID_FLAGS,
112 FILE_OPEN_FOR_BACKUP_INTENT);
113 if (!NT_SUCCESS (status))
122 if (!NT_SUCCESS (status))
123 __seterrno_from_nt_status (status);
128 get_attribute_from_acl (mode_t *attribute, PACL acl, PSID owner_sid,
129 PSID group_sid, bool grp_member)
131 ACCESS_ALLOWED_ACE *ace;
136 for (DWORD i = 0; i < acl->AceCount; ++i)
138 if (!GetAce (acl, i, (PVOID *) &ace))
140 if (ace->Header.AceFlags & INHERIT_ONLY_ACE)
142 switch (ace->Header.AceType)
144 case ACCESS_ALLOWED_ACE_TYPE:
148 case ACCESS_DENIED_ACE_TYPE:
156 cygpsid ace_sid ((PSID) &ace->SidStart);
157 if (ace_sid == well_known_world_sid)
159 if (ace->Mask & FILE_READ_BITS)
160 *flags |= ((!(*anti & S_IROTH)) ? S_IROTH : 0)
161 | ((!(*anti & S_IRGRP)) ? S_IRGRP : 0)
162 | ((!(*anti & S_IRUSR)) ? S_IRUSR : 0);
163 if (ace->Mask & FILE_WRITE_BITS)
164 *flags |= ((!(*anti & S_IWOTH)) ? S_IWOTH : 0)
165 | ((!(*anti & S_IWGRP)) ? S_IWGRP : 0)
166 | ((!(*anti & S_IWUSR)) ? S_IWUSR : 0);
167 if (ace->Mask & FILE_EXEC_BITS)
168 *flags |= ((!(*anti & S_IXOTH)) ? S_IXOTH : 0)
169 | ((!(*anti & S_IXGRP)) ? S_IXGRP : 0)
170 | ((!(*anti & S_IXUSR)) ? S_IXUSR : 0);
171 if ((S_ISDIR (*attribute)) &&
172 (ace->Mask & (FILE_WRITE_DATA | FILE_EXECUTE | FILE_DELETE_CHILD))
173 == (FILE_WRITE_DATA | FILE_EXECUTE))
176 else if (ace_sid == well_known_null_sid)
178 /* Read SUID, SGID and VTX bits from NULL ACE. */
179 if (ace->Mask & FILE_READ_DATA)
181 if (ace->Mask & FILE_WRITE_DATA)
183 if (ace->Mask & FILE_APPEND_DATA)
186 else if (ace_sid == owner_sid)
188 if (ace->Mask & FILE_READ_BITS)
189 *flags |= ((!(*anti & S_IRUSR)) ? S_IRUSR : 0);
190 if (ace->Mask & FILE_WRITE_BITS)
191 *flags |= ((!(*anti & S_IWUSR)) ? S_IWUSR : 0);
192 if (ace->Mask & FILE_EXEC_BITS)
193 *flags |= ((!(*anti & S_IXUSR)) ? S_IXUSR : 0);
195 else if (ace_sid == group_sid)
197 if (ace->Mask & FILE_READ_BITS)
198 *flags |= ((!(*anti & S_IRGRP)) ? S_IRGRP : 0)
199 | ((grp_member && !(*anti & S_IRUSR)) ? S_IRUSR : 0);
200 if (ace->Mask & FILE_WRITE_BITS)
201 *flags |= ((!(*anti & S_IWGRP)) ? S_IWGRP : 0)
202 | ((grp_member && !(*anti & S_IWUSR)) ? S_IWUSR : 0);
203 if (ace->Mask & FILE_EXEC_BITS)
204 *flags |= ((!(*anti & S_IXGRP)) ? S_IXGRP : 0)
205 | ((grp_member && !(*anti & S_IXUSR)) ? S_IXUSR : 0);
208 *attribute &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX | S_ISGID | S_ISUID);
209 if (owner_sid && group_sid && EqualSid (owner_sid, group_sid)
210 /* FIXME: temporary exception for /var/empty */
211 && well_known_system_sid != group_sid)
213 allow &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
214 allow |= (((allow & S_IRUSR) ? S_IRGRP : 0)
215 | ((allow & S_IWUSR) ? S_IWGRP : 0)
216 | ((allow & S_IXUSR) ? S_IXGRP : 0));
222 get_info_from_sd (PSECURITY_DESCRIPTOR psd, mode_t *attribute,
223 __uid32_t *uidret, __gid32_t *gidret)
227 /* If reading the security descriptor failed, treat the object
230 *attribute &= ~(S_IRWXU | S_IRWXG | S_IRWXO);
232 *uidret = ILLEGAL_UID;
234 *gidret = ILLEGAL_GID;
242 if (!GetSecurityDescriptorOwner (psd, (PSID *) &owner_sid, &dummy))
243 debug_printf ("GetSecurityDescriptorOwner %E");
244 if (!GetSecurityDescriptorGroup (psd, (PSID *) &group_sid, &dummy))
245 debug_printf ("GetSecurityDescriptorGroup %E");
249 bool grp_member = get_sids_info (owner_sid, group_sid, &uid, &gid);
257 syscall_printf ("uid %d, gid %d", uid, gid);
264 if (!GetSecurityDescriptorDacl (psd, &acl_exists, &acl, &dummy))
267 debug_printf ("GetSecurityDescriptorDacl %E");
268 *attribute &= ~(S_IRWXU | S_IRWXG | S_IRWXO);
270 else if (!acl_exists || !acl)
271 *attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
273 get_attribute_from_acl (attribute, acl, owner_sid, group_sid, grp_member);
275 syscall_printf ("%sACL %x, uid %d, gid %d",
276 (!acl_exists || !acl)?"NO ":"", *attribute, uid, gid);
280 get_reg_sd (HANDLE handle, security_descriptor &sd_ret)
285 ret = RegGetKeySecurity ((HKEY) handle, ALL_SECURITY_INFORMATION,
287 if (ret == ERROR_INSUFFICIENT_BUFFER)
289 if (!sd_ret.malloc (len))
292 ret = RegGetKeySecurity ((HKEY) handle, ALL_SECURITY_INFORMATION,
295 if (ret != ERROR_SUCCESS)
304 get_reg_attribute (HKEY hkey, mode_t *attribute, __uid32_t *uidret,
307 security_descriptor sd;
309 if (!get_reg_sd (hkey, sd))
311 get_info_from_sd (sd, attribute, uidret, gidret);
314 /* The entries are already set to default values */
319 get_file_attribute (HANDLE handle, path_conv &pc,
320 mode_t *attribute, __uid32_t *uidret, __gid32_t *gidret)
324 security_descriptor sd;
326 if (!get_file_sd (handle, pc, sd))
328 get_info_from_sd (sd, attribute, uidret, gidret);
334 *uidret = ILLEGAL_UID;
336 *gidret = ILLEGAL_GID;
343 *uidret = myself->uid;
345 *gidret = myself->gid;
351 add_access_allowed_ace (PACL acl, int offset, DWORD attributes,
352 PSID sid, size_t &len_add, DWORD inherit)
354 if (!AddAccessAllowedAce (acl, ACL_REVISION, attributes, sid))
359 ACCESS_ALLOWED_ACE *ace;
360 if (inherit && GetAce (acl, offset, (PVOID *) &ace))
361 ace->Header.AceFlags |= inherit;
362 len_add += sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD) + GetLengthSid (sid);
367 add_access_denied_ace (PACL acl, int offset, DWORD attributes,
368 PSID sid, size_t &len_add, DWORD inherit)
370 if (!AddAccessDeniedAce (acl, ACL_REVISION, attributes, sid))
375 ACCESS_DENIED_ACE *ace;
376 if (inherit && GetAce (acl, offset, (PVOID *) &ace))
377 ace->Header.AceFlags |= inherit;
378 len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD) + GetLengthSid (sid);
382 static PSECURITY_DESCRIPTOR
383 alloc_sd (path_conv &pc, __uid32_t uid, __gid32_t gid, int attribute,
384 security_descriptor &sd_ret)
388 /* NOTE: If the high bit of attribute is set, we have just created
389 a file or directory. See below for an explanation. */
391 debug_printf("uid %d, gid %d, attribute %x", uid, gid, attribute);
393 /* Get owner and group from current security descriptor. */
394 PSID cur_owner_sid = NULL;
395 PSID cur_group_sid = NULL;
396 if (!GetSecurityDescriptorOwner (sd_ret, &cur_owner_sid, &dummy))
397 debug_printf ("GetSecurityDescriptorOwner %E");
398 if (!GetSecurityDescriptorGroup (sd_ret, &cur_group_sid, &dummy))
399 debug_printf ("GetSecurityDescriptorGroup %E");
401 /* Get SID of owner. */
403 /* Check for current user first */
404 if (uid == myself->uid)
405 owner_sid = cygheap->user.sid ();
406 else if (uid == ILLEGAL_UID)
407 owner_sid = cur_owner_sid;
408 else if (!owner_sid.getfrompw (internal_getpwuid (uid)))
413 owner_sid.debug_print ("alloc_sd: owner SID =");
415 /* Get SID of new group. */
417 /* Check for current user first */
418 if (gid == myself->gid)
419 group_sid = cygheap->user.groups.pgsid;
420 else if (gid == ILLEGAL_GID)
421 group_sid = cur_group_sid;
422 else if (!group_sid.getfromgr (internal_getgrgid (gid)))
427 group_sid.debug_print ("alloc_sd: group SID =");
429 /* Initialize local security descriptor. */
430 SECURITY_DESCRIPTOR sd;
431 if (!InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION))
437 /* We set the SE_DACL_PROTECTED flag here to prevent the DACL from being
438 * modified by inheritable ACEs. This flag is available since Win2K. */
439 if (wincap.has_dacl_protect ())
440 sd.Control |= SE_DACL_PROTECTED;
442 /* Create owner for local security descriptor. */
443 if (!SetSecurityDescriptorOwner (&sd, owner_sid, FALSE))
449 /* Create group for local security descriptor. */
450 if (!SetSecurityDescriptorGroup (&sd, group_sid, FALSE))
456 /* Initialize local access control list. */
457 PACL acl = (PACL) alloca (3072);
458 if (!InitializeAcl (acl, 3072, ACL_REVISION))
464 /* From here fill ACL. */
465 size_t acl_len = sizeof (ACL);
468 /* Construct allow attribute for owner.
469 Don't set FILE_READ/WRITE_ATTRIBUTES unconditionally on Samba, otherwise
470 it enforces read permissions. Same for other's below. */
471 DWORD owner_allow = STANDARD_RIGHTS_ALL
473 ? 0 : (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES));
474 if (attribute & S_IRUSR)
475 owner_allow |= FILE_GENERIC_READ;
476 if (attribute & S_IWUSR)
477 owner_allow |= FILE_GENERIC_WRITE;
478 if (attribute & S_IXUSR)
479 owner_allow |= FILE_GENERIC_EXECUTE & ~FILE_READ_ATTRIBUTES;
480 if (S_ISDIR (attribute)
481 && (attribute & (S_IWUSR | S_IXUSR)) == (S_IWUSR | S_IXUSR))
482 owner_allow |= FILE_DELETE_CHILD;
484 /* Construct allow attribute for group. */
485 DWORD group_allow = STANDARD_RIGHTS_READ
486 | (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES);
487 if (attribute & S_IRGRP)
488 group_allow |= FILE_GENERIC_READ;
489 if (attribute & S_IWGRP)
490 group_allow |= FILE_GENERIC_WRITE;
491 if (attribute & S_IXGRP)
492 group_allow |= FILE_GENERIC_EXECUTE & ~FILE_READ_ATTRIBUTES;
493 if (S_ISDIR (attribute)
494 && (attribute & (S_IWGRP | S_IXGRP)) == (S_IWGRP | S_IXGRP)
495 && !(attribute & S_ISVTX))
496 group_allow |= FILE_DELETE_CHILD;
498 /* Construct allow attribute for everyone. */
499 DWORD other_allow = STANDARD_RIGHTS_READ
500 | (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES);
501 if (attribute & S_IROTH)
502 other_allow |= FILE_GENERIC_READ;
503 if (attribute & S_IWOTH)
504 other_allow |= FILE_GENERIC_WRITE;
505 if (attribute & S_IXOTH)
506 other_allow |= FILE_GENERIC_EXECUTE & ~FILE_READ_ATTRIBUTES;
507 if (S_ISDIR (attribute)
508 && (attribute & (S_IWOTH | S_IXOTH)) == (S_IWOTH | S_IXOTH)
509 && !(attribute & S_ISVTX))
510 other_allow |= FILE_DELETE_CHILD;
512 /* Construct SUID, SGID and VTX bits in NULL ACE. */
513 DWORD null_allow = 0L;
514 if (attribute & (S_ISUID | S_ISGID | S_ISVTX))
516 if (attribute & S_ISUID)
517 null_allow |= FILE_APPEND_DATA;
518 if (attribute & S_ISGID)
519 null_allow |= FILE_WRITE_DATA;
520 if (attribute & S_ISVTX)
521 null_allow |= FILE_READ_DATA;
524 /* Add owner and group permissions if SIDs are equal
525 and construct deny attributes for group and owner. */
527 if ((isownergroup = (owner_sid == group_sid)))
528 owner_allow |= group_allow;
530 DWORD owner_deny = ~owner_allow & (group_allow | other_allow);
531 owner_deny &= ~(STANDARD_RIGHTS_READ
532 | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES);
534 DWORD group_deny = ~group_allow & other_allow;
535 group_deny &= ~(STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES);
537 /* Set deny ACE for owner. */
539 && !add_access_denied_ace (acl, ace_off++, owner_deny,
540 owner_sid, acl_len, NO_INHERITANCE))
542 /* Set deny ACE for group here to respect the canonical order,
543 if this does not impact owner */
544 if (group_deny && !(group_deny & owner_allow) && !isownergroup
545 && !add_access_denied_ace (acl, ace_off++, group_deny,
546 group_sid, acl_len, NO_INHERITANCE))
548 /* Set allow ACE for owner. */
549 if (!add_access_allowed_ace (acl, ace_off++, owner_allow,
550 owner_sid, acl_len, NO_INHERITANCE))
552 /* Set deny ACE for group, if still needed. */
553 if (group_deny & owner_allow && !isownergroup
554 && !add_access_denied_ace (acl, ace_off++, group_deny,
555 group_sid, acl_len, NO_INHERITANCE))
557 /* Set allow ACE for group. */
559 && !add_access_allowed_ace (acl, ace_off++, group_allow,
560 group_sid, acl_len, NO_INHERITANCE))
563 /* Set allow ACE for everyone. */
564 if (!add_access_allowed_ace (acl, ace_off++, other_allow,
565 well_known_world_sid, acl_len, NO_INHERITANCE))
567 /* Set null ACE for special bits. */
569 && !add_access_allowed_ace (acl, ace_off++, null_allow,
570 well_known_null_sid, acl_len, NO_INHERITANCE))
573 /* Fill ACL with unrelated ACEs from current security descriptor. */
575 BOOL acl_exists = FALSE;
576 ACCESS_ALLOWED_ACE *ace;
577 if (GetSecurityDescriptorDacl (sd_ret, &acl_exists, &oacl, &dummy)
578 && acl_exists && oacl)
579 for (DWORD i = 0; i < oacl->AceCount; ++i)
580 if (GetAce (oacl, i, (PVOID *) &ace))
582 cygpsid ace_sid ((PSID) &ace->SidStart);
584 /* Check for related ACEs. */
585 if (ace_sid == well_known_null_sid)
587 if ((ace_sid == cur_owner_sid)
588 || (ace_sid == owner_sid)
589 || (ace_sid == cur_group_sid)
590 || (ace_sid == group_sid)
591 || (ace_sid == well_known_world_sid))
593 if (ace->Header.AceFlags
594 & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))
595 ace->Header.AceFlags |= INHERIT_ONLY_ACE;
599 else if (attribute & S_JUSTCREATED)
601 /* Since files and dirs are created with a NULL descriptor,
602 inheritence rules kick in. If no inheritable entries exist
603 in the parent object, Windows will create entries from the
604 user token's default DACL in the file DACL. These entries
605 are not desired and we drop them silently. */
606 if (!(ace->Header.AceFlags & INHERITED_ACE))
608 /* Remove the INHERITED_ACE flag since on POSIX systems
609 inheritance is settled when the file has been created.
610 This also avoids error messages in Windows Explorer when
611 opening a file's security tab. Explorer complains if
612 inheritable ACEs are preceding non-inheritable ACEs. */
613 ace->Header.AceFlags &= ~INHERITED_ACE;
616 * Add unrelated ACCESS_DENIED_ACE to the beginning but
617 * behind the owner_deny, ACCESS_ALLOWED_ACE to the end.
618 * FIXME: this would break the order of the inherit-only ACEs
620 if (!AddAce (acl, ACL_REVISION,
621 ace->Header.AceType == ACCESS_DENIED_ACE_TYPE
622 ? (owner_deny ? 1 : 0) : MAXDWORD,
623 (LPVOID) ace, ace->Header.AceSize))
629 acl_len += ace->Header.AceSize;
632 /* Construct appropriate inherit attribute for new directories */
633 if (S_ISDIR (attribute) && (attribute & S_JUSTCREATED))
635 const DWORD inherit = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
637 #if 0 /* FIXME: Not done currently as this breaks the canonical order */
638 /* Set deny ACE for owner. */
640 && !add_access_denied_ace (acl, ace_off++, owner_deny,
641 well_known_creator_owner_sid, acl_len, inherit))
643 /* Set deny ACE for group here to respect the canonical order,
644 if this does not impact owner */
645 if (group_deny && !(group_deny & owner_allow)
646 && !add_access_denied_ace (acl, ace_off++, group_deny,
647 well_known_creator_group_sid, acl_len, inherit))
650 /* Set allow ACE for owner. */
651 if (!add_access_allowed_ace (acl, ace_off++, owner_allow,
652 well_known_creator_owner_sid, acl_len,
655 #if 0 /* FIXME: Not done currently as this breaks the canonical order and
656 won't be preserved on chown and chmod */
657 /* Set deny ACE for group, conflicting with owner_allow. */
658 if (group_deny & owner_allow
659 && !add_access_denied_ace (acl, ace_off++, group_deny,
660 well_known_creator_group_sid, acl_len, inherit))
663 /* Set allow ACE for group. */
664 if (!add_access_allowed_ace (acl, ace_off++, group_allow,
665 well_known_creator_group_sid, acl_len,
668 /* Set allow ACE for everyone. */
669 if (!add_access_allowed_ace (acl, ace_off++, other_allow,
670 well_known_world_sid, acl_len, inherit))
674 /* Set AclSize to computed value. */
675 acl->AclSize = acl_len;
676 debug_printf ("ACL-Size: %d", acl_len);
678 /* Create DACL for local security descriptor. */
679 if (!SetSecurityDescriptorDacl (&sd, TRUE, acl, FALSE))
685 /* Make self relative security descriptor. */
687 MakeSelfRelativeSD (&sd, sd_ret, &sd_size);
693 if (!sd_ret.malloc (sd_size))
698 if (!MakeSelfRelativeSD (&sd, sd_ret, &sd_size))
703 debug_printf ("Created SD-Size: %u", sd_ret.size ());
709 set_security_attribute (path_conv &pc, int attribute, PSECURITY_ATTRIBUTES psa,
710 security_descriptor &sd)
712 psa->lpSecurityDescriptor = sd.malloc (SECURITY_DESCRIPTOR_MIN_LENGTH);
713 InitializeSecurityDescriptor ((PSECURITY_DESCRIPTOR)psa->lpSecurityDescriptor,
714 SECURITY_DESCRIPTOR_REVISION);
715 psa->lpSecurityDescriptor = alloc_sd (pc, geteuid32 (), getegid32 (),
720 set_file_attribute (HANDLE handle, path_conv &pc,
721 __uid32_t uid, __gid32_t gid, int attribute)
727 security_descriptor sd;
729 if (!get_file_sd (handle, pc, sd)
730 && alloc_sd (pc, uid, gid, attribute, sd))
731 ret = set_file_sd (handle, pc, sd,
732 uid != ILLEGAL_UID || gid != ILLEGAL_GID);
736 syscall_printf ("%d = set_file_attribute (%S, %d, %d, %p)",
737 ret, pc.get_nt_native_path (), uid, gid, attribute);
742 check_access (security_descriptor &sd, GENERIC_MAPPING &mapping,
743 DWORD desired, int flags, bool effective)
748 DWORD plen = sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES);
749 PPRIVILEGE_SET pset = (PPRIVILEGE_SET) alloca (plen);
750 HANDLE tok = ((effective && cygheap->user.issetuid ())
751 ? cygheap->user.imp_token ()
756 if (!DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL,
757 SecurityImpersonation, TokenImpersonation,
766 if (!AccessCheck (sd, tok, desired, &mapping, pset, &plen, &granted, &status))
770 /* CV, 2006-10-16: Now, that's really weird. Imagine a user who has no
771 standard access to a file, but who has backup and restore privileges
772 and these privileges are enabled in the access token. One would
773 expect that the AccessCheck function takes this into consideration
774 when returning the access status. Otherwise, why bother with the
775 pset parameter, right?
776 But not so. AccessCheck actually returns a status of "false" here,
777 even though opening a file with backup resp. restore intent
778 naturally succeeds for this user. This definitely spoils the results
779 of access(2) for administrative users or the SYSTEM account. So, in
780 case the access check fails, another check against the user's
781 backup/restore privileges has to be made. Sigh. */
782 int granted_flags = 0;
785 pset->PrivilegeCount = 1;
787 pset->Privilege[0].Luid.HighPart = 0L;
788 pset->Privilege[0].Luid.LowPart = SE_BACKUP_PRIVILEGE;
789 pset->Privilege[0].Attributes = 0;
790 if (PrivilegeCheck (tok, pset, &status) && status)
791 granted_flags |= R_OK;
795 pset->PrivilegeCount = 1;
797 pset->Privilege[0].Luid.HighPart = 0L;
798 pset->Privilege[0].Luid.LowPart = SE_RESTORE_PRIVILEGE;
799 pset->Privilege[0].Attributes = 0;
800 if (PrivilegeCheck (tok, pset, &status) && status)
801 granted_flags |= W_OK;
803 if (granted_flags == flags)
814 check_file_access (path_conv &pc, int flags, bool effective)
816 security_descriptor sd;
818 static GENERIC_MAPPING NO_COPY mapping = { FILE_GENERIC_READ,
820 FILE_GENERIC_EXECUTE,
824 desired |= FILE_READ_DATA;
826 desired |= FILE_WRITE_DATA;
828 desired |= FILE_EXECUTE;
829 if (!get_file_sd (NULL, pc, sd))
830 ret = check_access (sd, mapping, desired, flags, effective);
831 debug_printf ("flags %x, ret %d", flags, ret);
836 check_registry_access (HANDLE hdl, int flags, bool effective)
838 security_descriptor sd;
840 static GENERIC_MAPPING NO_COPY mapping = { KEY_READ,
846 desired |= KEY_ENUMERATE_SUB_KEYS;
848 desired |= KEY_SET_VALUE;
850 desired |= KEY_QUERY_VALUE;
851 if (!get_reg_sd (hdl, sd))
852 ret = check_access (sd, mapping, desired, flags, effective);
853 /* As long as we can't write the registry... */
859 debug_printf ("flags %x, ret %d", flags, ret);