* sec_helper.cc (security_descriptor::free): If sd_size is 0, call
LocalFree instead of ::free. * sec_acl.cc: Throughout replace old ACE flag definitions with current definitions as used in MSDN man pages. * security.cc: Ditto. * fhandler.cc (fhandler_base::open): Make sure file has really been just created before fixing file permissions. Add S_JUSTCREATED attribute to set_file_attribute call. * fhandler_disk_file.cc (fhandler_disk_file::mkdir): Always create dir with default security descriptor and fix descriptor afterwards. Add S_JUSTCREATED flag to set_file_attribute call. * fhandler_socket.cc (fhandler_socket::bind): Ditto for AF_LOCAL socket files. * path.cc (symlink_worker): Ditto for symlinks. * security.cc (get_file_sd): Call GetSecurityInfo rather than NtQuerySecurityObject. Explain why. Change error handling accordingly. (alloc_sd): Skip non-inherited, non-standard entries in ACL if S_JUSTCREATED attribute is set. Explain why. Minor format fixes. * security.h (S_JUSTCREATED): New define. (security_descriptor::operator=): New operator.
This commit is contained in:
@ -24,6 +24,7 @@ details. */
|
||||
#include "cygheap.h"
|
||||
#include "ntdll.h"
|
||||
#include "pwdgrp.h"
|
||||
#include <aclapi.h>
|
||||
|
||||
#define ALL_SECURITY_INFORMATION (DACL_SECURITY_INFORMATION \
|
||||
| GROUP_SECURITY_INFORMATION \
|
||||
@ -32,8 +33,7 @@ details. */
|
||||
LONG
|
||||
get_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
ULONG len = 0;
|
||||
DWORD error = ERROR_SUCCESS;
|
||||
int retry = 0;
|
||||
int res = -1;
|
||||
|
||||
@ -41,20 +41,17 @@ get_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd)
|
||||
{
|
||||
if (fh)
|
||||
{
|
||||
status = NtQuerySecurityObject (fh, ALL_SECURITY_INFORMATION,
|
||||
sd, len, &len);
|
||||
if (status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
if (!sd.malloc (len))
|
||||
{
|
||||
set_errno (ENOMEM);
|
||||
break;
|
||||
}
|
||||
status = NtQuerySecurityObject (fh, ALL_SECURITY_INFORMATION,
|
||||
sd, len, &len);
|
||||
}
|
||||
if (NT_SUCCESS (status))
|
||||
/* Amazing but true. If you want to know if an ACE is inherited
|
||||
from the parent object, you can't use the NtQuerySecurityObject
|
||||
function. In the DACL returned by this functions, the
|
||||
INHERITED_ACE flag is never set. Only by calling GetSecurityInfo
|
||||
you get this information. Oh well. */
|
||||
PSECURITY_DESCRIPTOR psd;
|
||||
error = GetSecurityInfo (fh, SE_FILE_OBJECT, ALL_SECURITY_INFORMATION,
|
||||
NULL, NULL, NULL, NULL, &psd);
|
||||
if (error == ERROR_SUCCESS)
|
||||
{
|
||||
sd = psd;
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
@ -63,6 +60,7 @@ get_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd)
|
||||
{
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
IO_STATUS_BLOCK io;
|
||||
NTSTATUS status;
|
||||
|
||||
status = NtOpenFile (&fh, READ_CONTROL,
|
||||
pc.get_object_attr (attr, sec_none_nih),
|
||||
@ -71,14 +69,15 @@ get_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd)
|
||||
if (!NT_SUCCESS (status))
|
||||
{
|
||||
fh = NULL;
|
||||
error = RtlNtStatusToDosError (status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (retry && fh)
|
||||
NtClose (fh);
|
||||
if (!NT_SUCCESS (status))
|
||||
__seterrno_from_nt_status (status);
|
||||
if (error != ERROR_SUCCESS)
|
||||
__seterrno_from_win_error (error);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -138,7 +137,7 @@ get_attribute_from_acl (mode_t *attribute, PACL acl, PSID owner_sid,
|
||||
{
|
||||
if (!GetAce (acl, i, (PVOID *) &ace))
|
||||
continue;
|
||||
if (ace->Header.AceFlags & INHERIT_ONLY)
|
||||
if (ace->Header.AceFlags & INHERIT_ONLY_ACE)
|
||||
continue;
|
||||
switch (ace->Header.AceType)
|
||||
{
|
||||
@ -386,6 +385,9 @@ alloc_sd (path_conv &pc, __uid32_t uid, __gid32_t gid, int attribute,
|
||||
{
|
||||
BOOL dummy;
|
||||
|
||||
/* NOTE: If the high bit of attribute is set, we have just created
|
||||
a file or directory. See below for an explanation. */
|
||||
|
||||
debug_printf("uid %d, gid %d, attribute %x", uid, gid, attribute);
|
||||
|
||||
/* Get owner and group from current security descriptor. */
|
||||
@ -583,15 +585,24 @@ alloc_sd (path_conv &pc, __uid32_t uid, __gid32_t gid, int attribute,
|
||||
|| (ace_sid == group_sid)
|
||||
|| (ace_sid == well_known_world_sid))
|
||||
{
|
||||
if (ace->Header.AceFlags & SUB_CONTAINERS_AND_OBJECTS_INHERIT)
|
||||
ace->Header.AceFlags |= INHERIT_ONLY;
|
||||
if (ace->Header.AceFlags
|
||||
& (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))
|
||||
ace->Header.AceFlags |= INHERIT_ONLY_ACE;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else if ((attribute & S_JUSTCREATED)
|
||||
&& !(ace->Header.AceFlags & INHERITED_ACE))
|
||||
/* Since files and dirs are created with a NULL descriptor,
|
||||
inheritence rules kick in. However, if no inheritable entries
|
||||
exist in the parent object, Windows will create entries from the
|
||||
user token's default DACL in the file DACL. These entries are
|
||||
not desired and we drop them silently here. */
|
||||
continue;
|
||||
/*
|
||||
* Add unrelated ACCESS_DENIED_ACE to the beginning but
|
||||
* behind the owner_deny, ACCESS_ALLOWED_ACE to the end.
|
||||
* FIXME: this would break the order of the inherit_only ACEs
|
||||
* FIXME: this would break the order of the inherit-only ACEs
|
||||
*/
|
||||
if (!AddAce (acl, ACL_REVISION,
|
||||
ace->Header.AceType == ACCESS_DENIED_ACE_TYPE?
|
||||
@ -611,9 +622,10 @@ alloc_sd (path_conv &pc, __uid32_t uid, __gid32_t gid, int attribute,
|
||||
impact. */
|
||||
|
||||
/* Construct appropriate inherit attribute for new directories */
|
||||
if (S_ISDIR (attribute) && !acl_exists)
|
||||
if (S_ISDIR (attribute) && (attribute & S_JUSTCREATED))
|
||||
{
|
||||
const DWORD inherit = SUB_CONTAINERS_AND_OBJECTS_INHERIT | INHERIT_ONLY;
|
||||
const DWORD inherit = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
|
||||
| INHERIT_ONLY_ACE;
|
||||
|
||||
#if 0 /* FIXME: Not done currently as this breaks the canonical order */
|
||||
/* Set deny ACE for owner. */
|
||||
@ -630,7 +642,8 @@ alloc_sd (path_conv &pc, __uid32_t uid, __gid32_t gid, int attribute,
|
||||
#endif
|
||||
/* Set allow ACE for owner. */
|
||||
if (!add_access_allowed_ace (acl, ace_off++, owner_allow,
|
||||
well_known_creator_owner_sid, acl_len, inherit))
|
||||
well_known_creator_owner_sid, acl_len,
|
||||
inherit))
|
||||
return NULL;
|
||||
#if 0 /* FIXME: Not done currently as this breaks the canonical order and
|
||||
won't be preserved on chown and chmod */
|
||||
@ -642,7 +655,8 @@ alloc_sd (path_conv &pc, __uid32_t uid, __gid32_t gid, int attribute,
|
||||
#endif
|
||||
/* Set allow ACE for group. */
|
||||
if (!add_access_allowed_ace (acl, ace_off++, group_allow,
|
||||
well_known_creator_group_sid, acl_len, inherit))
|
||||
well_known_creator_group_sid, acl_len,
|
||||
inherit))
|
||||
return NULL;
|
||||
/* Set allow ACE for everyone. */
|
||||
if (!add_access_allowed_ace (acl, ace_off++, other_allow,
|
||||
|
Reference in New Issue
Block a user