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 /* Create owner for local security descriptor. */
438 if (!SetSecurityDescriptorOwner (&sd, owner_sid, FALSE))
444 /* Create group for local security descriptor. */
445 if (!SetSecurityDescriptorGroup (&sd, group_sid, FALSE))
451 /* Initialize local access control list. */
452 PACL acl = (PACL) alloca (3072);
453 if (!InitializeAcl (acl, 3072, ACL_REVISION))
459 /* From here fill ACL. */
460 size_t acl_len = sizeof (ACL);
463 /* Construct allow attribute for owner.
464 Don't set FILE_READ/WRITE_ATTRIBUTES unconditionally on Samba, otherwise
465 it enforces read permissions. Same for other's below. */
466 DWORD owner_allow = STANDARD_RIGHTS_ALL
468 ? 0 : (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES));
469 if (attribute & S_IRUSR)
470 owner_allow |= FILE_GENERIC_READ;
471 if (attribute & S_IWUSR)
472 owner_allow |= FILE_GENERIC_WRITE;
473 if (attribute & S_IXUSR)
474 owner_allow |= FILE_GENERIC_EXECUTE & ~FILE_READ_ATTRIBUTES;
475 if (S_ISDIR (attribute)
476 && (attribute & (S_IWUSR | S_IXUSR)) == (S_IWUSR | S_IXUSR))
477 owner_allow |= FILE_DELETE_CHILD;
479 /* Construct allow attribute for group. */
480 DWORD group_allow = STANDARD_RIGHTS_READ
481 | (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES);
482 if (attribute & S_IRGRP)
483 group_allow |= FILE_GENERIC_READ;
484 if (attribute & S_IWGRP)
485 group_allow |= FILE_GENERIC_WRITE;
486 if (attribute & S_IXGRP)
487 group_allow |= FILE_GENERIC_EXECUTE & ~FILE_READ_ATTRIBUTES;
488 if (S_ISDIR (attribute)
489 && (attribute & (S_IWGRP | S_IXGRP)) == (S_IWGRP | S_IXGRP)
490 && !(attribute & S_ISVTX))
491 group_allow |= FILE_DELETE_CHILD;
493 /* Construct allow attribute for everyone. */
494 DWORD other_allow = STANDARD_RIGHTS_READ
495 | (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES);
496 if (attribute & S_IROTH)
497 other_allow |= FILE_GENERIC_READ;
498 if (attribute & S_IWOTH)
499 other_allow |= FILE_GENERIC_WRITE;
500 if (attribute & S_IXOTH)
501 other_allow |= FILE_GENERIC_EXECUTE & ~FILE_READ_ATTRIBUTES;
502 if (S_ISDIR (attribute)
503 && (attribute & (S_IWOTH | S_IXOTH)) == (S_IWOTH | S_IXOTH)
504 && !(attribute & S_ISVTX))
505 other_allow |= FILE_DELETE_CHILD;
507 /* Construct SUID, SGID and VTX bits in NULL ACE. */
508 DWORD null_allow = 0L;
509 if (attribute & (S_ISUID | S_ISGID | S_ISVTX))
511 if (attribute & S_ISUID)
512 null_allow |= FILE_APPEND_DATA;
513 if (attribute & S_ISGID)
514 null_allow |= FILE_WRITE_DATA;
515 if (attribute & S_ISVTX)
516 null_allow |= FILE_READ_DATA;
519 /* Add owner and group permissions if SIDs are equal
520 and construct deny attributes for group and owner. */
522 if ((isownergroup = (owner_sid == group_sid)))
523 owner_allow |= group_allow;
525 DWORD owner_deny = ~owner_allow & (group_allow | other_allow);
526 owner_deny &= ~(STANDARD_RIGHTS_READ
527 | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES);
529 DWORD group_deny = ~group_allow & other_allow;
530 group_deny &= ~(STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES);
532 /* Set deny ACE for owner. */
534 && !add_access_denied_ace (acl, ace_off++, owner_deny,
535 owner_sid, acl_len, NO_INHERITANCE))
537 /* Set deny ACE for group here to respect the canonical order,
538 if this does not impact owner */
539 if (group_deny && !(group_deny & owner_allow) && !isownergroup
540 && !add_access_denied_ace (acl, ace_off++, group_deny,
541 group_sid, acl_len, NO_INHERITANCE))
543 /* Set allow ACE for owner. */
544 if (!add_access_allowed_ace (acl, ace_off++, owner_allow,
545 owner_sid, acl_len, NO_INHERITANCE))
547 /* Set deny ACE for group, if still needed. */
548 if (group_deny & owner_allow && !isownergroup
549 && !add_access_denied_ace (acl, ace_off++, group_deny,
550 group_sid, acl_len, NO_INHERITANCE))
552 /* Set allow ACE for group. */
554 && !add_access_allowed_ace (acl, ace_off++, group_allow,
555 group_sid, acl_len, NO_INHERITANCE))
558 /* Set allow ACE for everyone. */
559 if (!add_access_allowed_ace (acl, ace_off++, other_allow,
560 well_known_world_sid, acl_len, NO_INHERITANCE))
562 /* Set null ACE for special bits. */
564 && !add_access_allowed_ace (acl, ace_off++, null_allow,
565 well_known_null_sid, acl_len, NO_INHERITANCE))
568 /* Fill ACL with unrelated ACEs from current security descriptor. */
570 BOOL acl_exists = FALSE;
571 ACCESS_ALLOWED_ACE *ace;
572 if (GetSecurityDescriptorDacl (sd_ret, &acl_exists, &oacl, &dummy)
573 && acl_exists && oacl)
574 for (DWORD i = 0; i < oacl->AceCount; ++i)
575 if (GetAce (oacl, i, (PVOID *) &ace))
577 cygpsid ace_sid ((PSID) &ace->SidStart);
579 /* Check for related ACEs. */
580 if (ace_sid == well_known_null_sid)
582 if ((ace_sid == cur_owner_sid)
583 || (ace_sid == owner_sid)
584 || (ace_sid == cur_group_sid)
585 || (ace_sid == group_sid)
586 || (ace_sid == well_known_world_sid))
588 if (ace->Header.AceFlags
589 & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))
590 ace->Header.AceFlags |= INHERIT_ONLY_ACE;
594 else if ((attribute & S_JUSTCREATED)
595 && !(ace->Header.AceFlags & INHERITED_ACE))
596 /* Since files and dirs are created with a NULL descriptor,
597 inheritence rules kick in. However, if no inheritable entries
598 exist in the parent object, Windows will create entries from the
599 user token's default DACL in the file DACL. These entries are
600 not desired and we drop them silently here. */
603 * Add unrelated ACCESS_DENIED_ACE to the beginning but
604 * behind the owner_deny, ACCESS_ALLOWED_ACE to the end.
605 * FIXME: this would break the order of the inherit-only ACEs
607 if (!AddAce (acl, ACL_REVISION,
608 ace->Header.AceType == ACCESS_DENIED_ACE_TYPE?
609 (owner_deny ? 1 : 0) : MAXDWORD,
610 (LPVOID) ace, ace->Header.AceSize))
615 acl_len += ace->Header.AceSize;
618 /* Construct appropriate inherit attribute for new directories */
619 if (S_ISDIR (attribute) && (attribute & S_JUSTCREATED))
621 const DWORD inherit = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
624 #if 0 /* FIXME: Not done currently as this breaks the canonical order */
625 /* Set deny ACE for owner. */
627 && !add_access_denied_ace (acl, ace_off++, owner_deny,
628 well_known_creator_owner_sid, acl_len, inherit))
630 /* Set deny ACE for group here to respect the canonical order,
631 if this does not impact owner */
632 if (group_deny && !(group_deny & owner_allow)
633 && !add_access_denied_ace (acl, ace_off++, group_deny,
634 well_known_creator_group_sid, acl_len, inherit))
637 /* Set allow ACE for owner. */
638 if (!add_access_allowed_ace (acl, ace_off++, owner_allow,
639 well_known_creator_owner_sid, acl_len,
642 #if 0 /* FIXME: Not done currently as this breaks the canonical order and
643 won't be preserved on chown and chmod */
644 /* Set deny ACE for group, conflicting with owner_allow. */
645 if (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 group. */
651 if (!add_access_allowed_ace (acl, ace_off++, group_allow,
652 well_known_creator_group_sid, acl_len,
655 /* Set allow ACE for everyone. */
656 if (!add_access_allowed_ace (acl, ace_off++, other_allow,
657 well_known_world_sid, acl_len, inherit))
661 /* Set AclSize to computed value. */
662 acl->AclSize = acl_len;
663 debug_printf ("ACL-Size: %d", acl_len);
665 /* Create DACL for local security descriptor. */
666 if (!SetSecurityDescriptorDacl (&sd, TRUE, acl, FALSE))
672 /* Make self relative security descriptor. */
674 MakeSelfRelativeSD (&sd, sd_ret, &sd_size);
680 if (!sd_ret.malloc (sd_size))
685 if (!MakeSelfRelativeSD (&sd, sd_ret, &sd_size))
690 debug_printf ("Created SD-Size: %u", sd_ret.size ());
696 set_security_attribute (path_conv &pc, int attribute, PSECURITY_ATTRIBUTES psa,
697 security_descriptor &sd)
699 psa->lpSecurityDescriptor = sd.malloc (SECURITY_DESCRIPTOR_MIN_LENGTH);
700 InitializeSecurityDescriptor ((PSECURITY_DESCRIPTOR)psa->lpSecurityDescriptor,
701 SECURITY_DESCRIPTOR_REVISION);
702 psa->lpSecurityDescriptor = alloc_sd (pc, geteuid32 (), getegid32 (),
707 set_file_attribute (HANDLE handle, path_conv &pc,
708 __uid32_t uid, __gid32_t gid, int attribute)
714 security_descriptor sd;
716 if (!get_file_sd (handle, pc, sd)
717 && alloc_sd (pc, uid, gid, attribute, sd))
718 ret = set_file_sd (handle, pc, sd,
719 uid != ILLEGAL_UID || gid != ILLEGAL_GID);
723 syscall_printf ("%d = set_file_attribute (%S, %d, %d, %p)",
724 ret, pc.get_nt_native_path (), uid, gid, attribute);
729 check_access (security_descriptor &sd, GENERIC_MAPPING &mapping,
730 DWORD desired, int flags, bool effective)
735 DWORD plen = sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES);
736 PPRIVILEGE_SET pset = (PPRIVILEGE_SET) alloca (plen);
737 HANDLE tok = ((effective && cygheap->user.issetuid ())
738 ? cygheap->user.imp_token ()
741 if (!tok && !DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL,
742 SecurityImpersonation, TokenImpersonation,
745 system_printf ("DuplicateTokenEx failed, %E");
747 syscall_printf ("DuplicateTokenEx failed, %E");
752 if (!AccessCheck (sd, tok, desired, &mapping, pset, &plen, &granted, &status))
756 /* CV, 2006-10-16: Now, that's really weird. Imagine a user who has no
757 standard access to a file, but who has backup and restore privileges
758 and these privileges are enabled in the access token. One would
759 expect that the AccessCheck function takes this into consideration
760 when returning the access status. Otherwise, why bother with the
761 pset parameter, right?
762 But not so. AccessCheck actually returns a status of "false" here,
763 even though opening a file with backup resp. restore intent
764 naturally succeeds for this user. This definitely spoils the results
765 of access(2) for administrative users or the SYSTEM account. So, in
766 case the access check fails, another check against the user's
767 backup/restore privileges has to be made. Sigh. */
768 int granted_flags = 0;
771 pset->PrivilegeCount = 1;
773 pset->Privilege[0].Luid.HighPart = 0L;
774 pset->Privilege[0].Luid.LowPart = SE_BACKUP_PRIVILEGE;
775 pset->Privilege[0].Attributes = 0;
776 if (PrivilegeCheck (tok, pset, &status) && status)
777 granted_flags |= R_OK;
781 pset->PrivilegeCount = 1;
783 pset->Privilege[0].Luid.HighPart = 0L;
784 pset->Privilege[0].Luid.LowPart = SE_RESTORE_PRIVILEGE;
785 pset->Privilege[0].Attributes = 0;
786 if (PrivilegeCheck (tok, pset, &status) && status)
787 granted_flags |= W_OK;
789 if (granted_flags == flags)
800 check_file_access (path_conv &pc, int flags, bool effective)
802 security_descriptor sd;
804 static GENERIC_MAPPING NO_COPY mapping = { FILE_GENERIC_READ,
806 FILE_GENERIC_EXECUTE,
810 desired |= FILE_READ_DATA;
812 desired |= FILE_WRITE_DATA;
814 desired |= FILE_EXECUTE;
815 if (!get_file_sd (NULL, pc, sd))
816 ret = check_access (sd, mapping, desired, flags, effective);
817 debug_printf ("flags %x, ret %d", flags, ret);
822 check_registry_access (HANDLE hdl, int flags, bool effective)
824 security_descriptor sd;
826 static GENERIC_MAPPING NO_COPY mapping = { KEY_READ,
832 desired |= KEY_ENUMERATE_SUB_KEYS;
834 desired |= KEY_SET_VALUE;
836 desired |= KEY_QUERY_VALUE;
837 if (!get_reg_sd (hdl, sd))
838 ret = check_access (sd, mapping, desired, flags, effective);
839 /* As long as we can't write the registry... */
845 debug_printf ("flags %x, ret %d", flags, ret);