1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-04-27 08:43:40 -07:00

Support Posix ACL APIs on MS-Windows.

src/w32.c: Include sddl.h and sys/acl.h.
 (SDDL_REVISION_1): Define if not already defined.
 (g_b_init_get_security_descriptor_dacl)
 (g_b_init_convert_sd_to_sddl, g_b_init_convert_sddl_to_sd)
 (g_b_init_is_valid_security_descriptor)
 (g_b_init_set_file_security): New static flags.
 (globals_of_w32): Initialize them to zero.
 (SetFileSecurity_Name): New string constant.
 (SetFileSecurity_Proc, GetSecurityDescriptorDacl_Proc)
 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)
 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)
 (IsValidSecurityDescriptor_Proc): New typedefs.
 (get_file_security, get_security_descriptor_owner)
 (get_security_descriptor_group): Set errno to ENOTSUP.
 (set_file_security, get_security_descriptor_dacl)
 (is_valid_security_descriptor, convert_sd_to_sddl)
 (convert_sddl_to_sd, acl_valid, acl_to_text, acl_from_text)
 (acl_free, acl_get_file, acl_set_file): New functions.
 src/fileio.c (Fcopy_file) [WINDOWSNT]: Support copying ACLs.

 nt/inc/sys/acl.h: New file.
 nt/inc/ms-w32.h (ENOTSUP): Define if undefined.
 nt/config.nt (HAVE_POSIX_ACL): Define.

 doc/lispref/files.texi (File Attributes, Changing Files): Update to include
 MS-Windows support for ACLs.
This commit is contained in:
Eli Zaretskii 2012-12-17 21:14:34 +02:00
parent 207a7ef053
commit 66447e07c1
10 changed files with 518 additions and 6 deletions

View file

@ -1,3 +1,8 @@
2012-12-17 Eli Zaretskii <eliz@gnu.org>
* files.texi (File Attributes, Changing Files): Update to include
MS-Windows support for ACLs.
2012-12-16 Romain Francoise <romain@orebokech.com>
* files.texi (File Attributes): Document ACL support and new

View file

@ -1357,13 +1357,14 @@ support, then the return value is @code{(nil nil nil nil)}.
If Emacs has been compiled with @dfn{ACL} (access control list)
support, you can use the function @code{file-acl} to retrieve a file's
ACL entries. The format is platform-specific; on GNU/Linux and BSD,
Emacs uses the POSIX ACL interface. For the function
@code{set-file-acl}, see @ref{Changing Files}.
Emacs uses the POSIX ACL interface, while on MS-Windows Emacs emulates
the POSIX ACL interface with native file security APIs. For the
function @code{set-file-acl}, see @ref{Changing Files}.
@defun file-acl filename
This function returns the ACL entries of the file @var{filename}.
The return value is a string containing the textual representation of
the ACL entries, like the following:
the ACL entries. On Posix hosts, it looks like this:
@example
@group
@ -1375,6 +1376,12 @@ other::r--
@end group
@end example
@cindex security descriptor, file
@cindex SDDL, MS-Windows
On MS-Windows, the return value is a textual description of the file's
@dfn{security descriptor} in @acronym{SDDL}, the @dfn{Security
Descriptor Definition Language}.
If the file does not exist or is inaccessible, or if Emacs was unable to
determine the ACL entries, then the return value is @code{nil}. The
latter can happen for local files if Emacs was not compiled with ACL
@ -1719,7 +1726,8 @@ SELinux support.
This function sets the ACL entries of the file @var{filename} to
@var{acl-string}. @xref{File Attributes}, for a brief description of
ACLs. The @var{acl-string} argument should be a string containing the
textual representation of the desired ACL entries.
textual representation of the desired ACL entries in the format
appropriate for the ACL interface being used.
@end defun
@node File Names

View file

@ -44,8 +44,9 @@ simply disabling Transient Mark mode does the same thing.
*** Emacs preserves the ACL entries of files when backing up.
+++
*** New functions `file-acl' and `set-file-acl' get and set the ACL
entries of a file. On GNU/Linux the POSIX ACL interface is used via
libacl.
entries of a file. On GNU/Linux, the POSIX ACL interface is used via
libacl. On MS-Windows, the NT Security APIs are used to emulate the
POSIX ACL interfaces.
* Editing Changes in Emacs 24.4

View file

@ -1,3 +1,11 @@
2012-12-17 Eli Zaretskii <eliz@gnu.org>
* inc/sys/acl.h: New file.
* inc/ms-w32.h (ENOTSUP): Define if undefined.
* config.nt (HAVE_POSIX_ACL): Define.
2012-12-15 Eli Zaretskii <eliz@gnu.org>
* inc/ms-w32.h (sys_unlink): Provide prototype.

View file

@ -725,6 +725,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Define to 1 if you have the <png.h> header file. */
#undef HAVE_PNG_H
/* Define to 1 if you have the POSIX ACL support. */
#define HAVE_POSIX_ACL 1
/* Define to 1 if you have the `posix_memalign' function. */
#undef HAVE_POSIX_MEMALIGN

View file

@ -293,6 +293,10 @@ extern struct tm *localtime_r (time_t const * restrict, struct tm * restrict);
#define NSIG 23
#endif
#ifndef ENOTSUP
#define ENOTSUP ENOSYS
#endif
#ifdef _MSC_VER
typedef int sigset_t;
typedef int ssize_t;

25
nt/inc/sys/acl.h Normal file
View file

@ -0,0 +1,25 @@
/* Emulation of Posix ACLs for Windows. */
#ifndef ACL_H
#define ACL_H
#define NOMINMAX 1 /* don't define min and max */
#include <windows.h>
typedef PSECURITY_DESCRIPTOR acl_t;
typedef unsigned acl_type_t;
/* Values of acl_type_t */
#define ACL_TYPE_ACCESS 0
#define ACL_TYPE_DEFAULT 1
typedef unsigned acl_perm_t;
extern int acl_valid (acl_t);
extern acl_t acl_get_file (const char *, acl_type_t);
extern int acl_set_file (const char *, acl_type_t, acl_t);
extern char * acl_to_text (acl_t, ssize_t *);
extern acl_t acl_from_text (const char *);
extern int acl_free (void *);
#endif /* ACL_H */

View file

@ -1,3 +1,27 @@
2012-12-17 Eli Zaretskii <eliz@gnu.org>
Emulate Posix ACL APIs on MS-Windows.
* w32.c: Include sddl.h and sys/acl.h.
(SDDL_REVISION_1): Define if not already defined.
(g_b_init_get_security_descriptor_dacl)
(g_b_init_convert_sd_to_sddl, g_b_init_convert_sddl_to_sd)
(g_b_init_is_valid_security_descriptor)
(g_b_init_set_file_security): New static flags.
(globals_of_w32): Initialize them to zero.
(SetFileSecurity_Name): New string constant.
(SetFileSecurity_Proc, GetSecurityDescriptorDacl_Proc)
(ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)
(ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)
(IsValidSecurityDescriptor_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group): Set errno to ENOTSUP.
(set_file_security, get_security_descriptor_dacl)
(is_valid_security_descriptor, convert_sd_to_sddl)
(convert_sddl_to_sd, acl_valid, acl_to_text, acl_from_text)
(acl_free, acl_get_file, acl_set_file): New functions.
* fileio.c (Fcopy_file) [WINDOWSNT]: Support copying ACLs.
2012-12-17 Paul Eggert <eggert@cs.ucla.edu>
Don't reraise SIGCHLD, as that can now lose (Bug#13192).

View file

@ -1956,6 +1956,14 @@ entries (depending on how Emacs was built). */)
out_st.st_mode = 0;
#ifdef WINDOWSNT
if (!NILP (preserve_extended_attributes))
{
#ifdef HAVE_POSIX_ACL
acl = acl_get_file (SDATA (encoded_file), ACL_TYPE_ACCESS);
if (acl == NULL && errno != ENOTSUP)
report_file_error ("Getting ACL", Fcons (file, Qnil));
#endif
}
if (!CopyFile (SDATA (encoded_file),
SDATA (encoded_newname),
FALSE))
@ -1983,6 +1991,17 @@ entries (depending on how Emacs was built). */)
/* Restore original attributes. */
SetFileAttributes (filename, attributes);
}
#ifdef HAVE_POSIX_ACL
if (acl != NULL)
{
bool fail =
acl_set_file (SDATA (encoded_newname), ACL_TYPE_ACCESS, acl) != 0;
if (fail && errno != ENOTSUP)
report_file_error ("Setting ACL", Fcons (newname, Qnil));
acl_free (acl);
}
#endif
#else /* not WINDOWSNT */
immediate_quit = 1;
ifd = emacs_open (SSDATA (encoded_file), O_RDONLY, 0);

415
src/w32.c
View file

@ -117,6 +117,15 @@ typedef struct _PROCESS_MEMORY_COUNTERS_EX {
#include <winioctl.h>
#include <aclapi.h>
#include <sddl.h>
#include <sys/acl.h>
/* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
define them by hand if not already defined. */
#ifndef SDDL_REVISION_1
#define SDDL_REVISION_1 1
#endif /* SDDL_REVISION_1 */
#ifdef _MSC_VER
/* MSVC doesn't provide the definition of REPARSE_DATA_BUFFER and the
@ -257,6 +266,11 @@ static BOOL g_b_init_copy_sid;
static BOOL g_b_init_get_native_system_info;
static BOOL g_b_init_get_system_times;
static BOOL g_b_init_create_symbolic_link;
static BOOL g_b_init_get_security_descriptor_dacl;
static BOOL g_b_init_convert_sd_to_sddl;
static BOOL g_b_init_convert_sddl_to_sd;
static BOOL g_b_init_is_valid_security_descriptor;
static BOOL g_b_init_set_file_security;
/*
BEGIN: Wrapper functions around OpenProcessToken
@ -286,9 +300,11 @@ GetProcessTimes_Proc get_process_times_fn = NULL;
#ifdef _UNICODE
const char * const LookupAccountSid_Name = "LookupAccountSidW";
const char * const GetFileSecurity_Name = "GetFileSecurityW";
const char * const SetFileSecurity_Name = "SetFileSecurityW";
#else
const char * const LookupAccountSid_Name = "LookupAccountSidA";
const char * const GetFileSecurity_Name = "GetFileSecurityA";
const char * const SetFileSecurity_Name = "SetFileSecurityA";
#endif
typedef BOOL (WINAPI * LookupAccountSid_Proc) (
LPCTSTR lpSystemName,
@ -318,6 +334,10 @@ typedef BOOL (WINAPI * GetFileSecurity_Proc) (
PSECURITY_DESCRIPTOR pSecurityDescriptor,
DWORD nLength,
LPDWORD lpnLengthNeeded);
typedef BOOL (WINAPI *SetFileSecurity_Proc) (
LPCTSTR lpFileName,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR pSecurityDescriptor);
typedef BOOL (WINAPI * GetSecurityDescriptorOwner_Proc) (
PSECURITY_DESCRIPTOR pSecurityDescriptor,
PSID *pOwner,
@ -326,6 +346,11 @@ typedef BOOL (WINAPI * GetSecurityDescriptorGroup_Proc) (
PSECURITY_DESCRIPTOR pSecurityDescriptor,
PSID *pGroup,
LPBOOL lpbGroupDefaulted);
typedef BOOL (WINAPI *GetSecurityDescriptorDacl_Proc) (
PSECURITY_DESCRIPTOR pSecurityDescriptor,
LPBOOL lpbDaclPresent,
PACL *pDacl,
LPBOOL lpbDaclDefaulted);
typedef BOOL (WINAPI * IsValidSid_Proc) (
PSID sid);
typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_Proc) (
@ -376,6 +401,18 @@ typedef BOOLEAN (WINAPI *CreateSymbolicLink_Proc) (
LPTSTR lpSymlinkFileName,
LPTSTR lpTargetFileName,
DWORD dwFlags);
typedef BOOL (WINAPI *ConvertStringSecurityDescriptorToSecurityDescriptor_Proc) (
LPCTSTR StringSecurityDescriptor,
DWORD StringSDRevision,
PSECURITY_DESCRIPTOR *SecurityDescriptor,
PULONG SecurityDescriptorSize);
typedef BOOL (WINAPI *ConvertSecurityDescriptorToStringSecurityDescriptor_Proc) (
PSECURITY_DESCRIPTOR SecurityDescriptor,
DWORD RequestedStringSDRevision,
SECURITY_INFORMATION SecurityInformation,
LPTSTR *StringSecurityDescriptor,
PULONG StringSecurityDescriptorLen);
typedef BOOL (WINAPI *IsValidSecurityDescriptor_Proc) (PSECURITY_DESCRIPTOR);
/* ** A utility function ** */
static BOOL
@ -621,6 +658,7 @@ get_file_security (LPCTSTR lpFileName,
HMODULE hm_advapi32 = NULL;
if (is_windows_9x () == TRUE)
{
errno = ENOTSUP;
return FALSE;
}
if (g_b_init_get_file_security == 0)
@ -633,6 +671,7 @@ get_file_security (LPCTSTR lpFileName,
}
if (s_pfn_Get_File_Security == NULL)
{
errno = ENOTSUP;
return FALSE;
}
return (s_pfn_Get_File_Security (lpFileName, RequestedInformation,
@ -640,6 +679,35 @@ get_file_security (LPCTSTR lpFileName,
lpnLengthNeeded));
}
static BOOL WINAPI
set_file_security (LPCTSTR lpFileName,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR pSecurityDescriptor)
{
static SetFileSecurity_Proc s_pfn_Set_File_Security = NULL;
HMODULE hm_advapi32 = NULL;
if (is_windows_9x () == TRUE)
{
errno = ENOTSUP;
return FALSE;
}
if (g_b_init_set_file_security == 0)
{
g_b_init_set_file_security = 1;
hm_advapi32 = LoadLibrary ("Advapi32.dll");
s_pfn_Set_File_Security =
(SetFileSecurity_Proc) GetProcAddress (
hm_advapi32, SetFileSecurity_Name);
}
if (s_pfn_Set_File_Security == NULL)
{
errno = ENOTSUP;
return FALSE;
}
return (s_pfn_Set_File_Security (lpFileName, SecurityInformation,
pSecurityDescriptor));
}
static BOOL WINAPI
get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
PSID *pOwner,
@ -649,6 +717,7 @@ get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
HMODULE hm_advapi32 = NULL;
if (is_windows_9x () == TRUE)
{
errno = ENOTSUP;
return FALSE;
}
if (g_b_init_get_security_descriptor_owner == 0)
@ -661,6 +730,7 @@ get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
}
if (s_pfn_Get_Security_Descriptor_Owner == NULL)
{
errno = ENOTSUP;
return FALSE;
}
return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor, pOwner,
@ -676,6 +746,7 @@ get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
HMODULE hm_advapi32 = NULL;
if (is_windows_9x () == TRUE)
{
errno = ENOTSUP;
return FALSE;
}
if (g_b_init_get_security_descriptor_group == 0)
@ -688,12 +759,44 @@ get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
}
if (s_pfn_Get_Security_Descriptor_Group == NULL)
{
errno = ENOTSUP;
return FALSE;
}
return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor, pGroup,
lpbGroupDefaulted));
}
static BOOL WINAPI
get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor,
LPBOOL lpbDaclPresent,
PACL *pDacl,
LPBOOL lpbDaclDefaulted)
{
static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl = NULL;
HMODULE hm_advapi32 = NULL;
if (is_windows_9x () == TRUE)
{
errno = ENOTSUP;
return FALSE;
}
if (g_b_init_get_security_descriptor_dacl == 0)
{
g_b_init_get_security_descriptor_dacl = 1;
hm_advapi32 = LoadLibrary ("Advapi32.dll");
s_pfn_Get_Security_Descriptor_Dacl =
(GetSecurityDescriptorDacl_Proc) GetProcAddress (
hm_advapi32, "GetSecurityDescriptorDacl");
}
if (s_pfn_Get_Security_Descriptor_Dacl == NULL)
{
errno = ENOTSUP;
return FALSE;
}
return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor,
lpbDaclPresent, pDacl,
lpbDaclDefaulted));
}
static BOOL WINAPI
is_valid_sid (PSID sid)
{
@ -888,6 +991,120 @@ create_symbolic_link (LPTSTR lpSymlinkFilename,
}
return retval;
}
static BOOL WINAPI
is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor)
{
static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc = NULL;
if (is_windows_9x () == TRUE)
{
errno = ENOTSUP;
return FALSE;
}
if (g_b_init_is_valid_security_descriptor == 0)
{
g_b_init_is_valid_security_descriptor = 1;
s_pfn_Is_Valid_Security_Descriptor_Proc =
(IsValidSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
"IsValidSecurityDescriptor");
}
if (s_pfn_Is_Valid_Security_Descriptor_Proc == NULL)
{
errno = ENOTSUP;
return FALSE;
}
return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor);
}
static BOOL WINAPI
convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor,
DWORD RequestedStringSDRevision,
SECURITY_INFORMATION SecurityInformation,
LPTSTR *StringSecurityDescriptor,
PULONG StringSecurityDescriptorLen)
{
static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL = NULL;
BOOL retval;
if (is_windows_9x () == TRUE)
{
errno = ENOTSUP;
return FALSE;
}
if (g_b_init_convert_sd_to_sddl == 0)
{
g_b_init_convert_sd_to_sddl = 1;
#ifdef _UNICODE
s_pfn_Convert_SD_To_SDDL =
(ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
"ConvertSecurityDescriptorToStringSecurityDescriptorW");
#else
s_pfn_Convert_SD_To_SDDL =
(ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
"ConvertSecurityDescriptorToStringSecurityDescriptorA");
#endif
}
if (s_pfn_Convert_SD_To_SDDL == NULL)
{
errno = ENOTSUP;
return FALSE;
}
retval = s_pfn_Convert_SD_To_SDDL (SecurityDescriptor,
RequestedStringSDRevision,
SecurityInformation,
StringSecurityDescriptor,
StringSecurityDescriptorLen);
return retval;
}
static BOOL WINAPI
convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor,
DWORD StringSDRevision,
PSECURITY_DESCRIPTOR *SecurityDescriptor,
PULONG SecurityDescriptorSize)
{
static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD = NULL;
BOOL retval;
if (is_windows_9x () == TRUE)
{
errno = ENOTSUP;
return FALSE;
}
if (g_b_init_convert_sddl_to_sd == 0)
{
g_b_init_convert_sddl_to_sd = 1;
#ifdef _UNICODE
s_pfn_Convert_SDDL_To_SD =
(ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
"ConvertStringSecurityDescriptorToSecurityDescriptorW");
#else
s_pfn_Convert_SDDL_To_SD =
(ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
"ConvertStringSecurityDescriptorToSecurityDescriptorA");
#endif
}
if (s_pfn_Convert_SDDL_To_SD == NULL)
{
errno = ENOTSUP;
return FALSE;
}
retval = s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor,
StringSDRevision,
SecurityDescriptor,
SecurityDescriptorSize);
return retval;
}
/* Return 1 if P is a valid pointer to an object of size SIZE. Return
@ -4477,6 +4694,199 @@ chase_symlinks (const char *file)
return target;
}
/* Posix ACL emulation. */
int
acl_valid (acl_t acl)
{
return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR)acl) ? 0 : -1;
}
char *
acl_to_text (acl_t acl, ssize_t *size)
{
LPTSTR str_acl;
SECURITY_INFORMATION flags =
OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION;
char *retval = NULL;
ssize_t local_size;
int e = errno;
errno = 0;
if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR)acl, SDDL_REVISION_1, flags, &str_acl, &local_size))
{
errno = e;
/* We don't want to mix heaps, so we duplicate the string in our
heap and free the one allocated by the API. */
retval = xstrdup (str_acl);
if (size)
*size = local_size;
LocalFree (str_acl);
}
else if (errno != ENOTSUP)
errno = EINVAL;
return retval;
}
acl_t
acl_from_text (const char *acl_str)
{
PSECURITY_DESCRIPTOR psd, retval = NULL;
ULONG sd_size;
int e = errno;
errno = 0;
if (convert_sddl_to_sd (acl_str, SDDL_REVISION_1, &psd, &sd_size))
{
errno = e;
retval = xmalloc (sd_size);
memcpy (retval, psd, sd_size);
LocalFree (psd);
}
else if (errno != ENOTSUP)
errno = EINVAL;
return retval;
}
int
acl_free (void *ptr)
{
xfree (ptr);
return 0;
}
acl_t
acl_get_file (const char *fname, acl_type_t type)
{
PSECURITY_DESCRIPTOR psd = NULL;
if (type == ACL_TYPE_ACCESS)
{
DWORD sd_len, err;
SECURITY_INFORMATION si =
OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION ;
int e = errno;
errno = 0;
if (!get_file_security (fname, si, psd, 0, &sd_len)
&& errno != ENOTSUP)
{
err = GetLastError ();
if (err == ERROR_INSUFFICIENT_BUFFER)
{
psd = xmalloc (sd_len);
if (!get_file_security (fname, si, psd, sd_len, &sd_len))
{
xfree (psd);
errno = EIO;
psd = NULL;
}
}
else if (err == ERROR_FILE_NOT_FOUND
|| err == ERROR_PATH_NOT_FOUND)
errno = ENOENT;
else
errno = EIO;
}
else if (!errno)
errno = e;
}
else if (type != ACL_TYPE_DEFAULT)
errno = EINVAL;
return psd;
}
int
acl_set_file (const char *fname, acl_type_t type, acl_t acl)
{
TOKEN_PRIVILEGES old1, old2;
DWORD err;
BOOL res;
int st = 0, retval = -1;
SECURITY_INFORMATION flags = 0;
PSID psid;
PACL pacl;
BOOL dflt;
BOOL dacl_present;
int e;
if (acl_valid (acl) != 0
|| (type != ACL_TYPE_DEFAULT && type != ACL_TYPE_ACCESS))
{
errno = EINVAL;
return -1;
}
if (type == ACL_TYPE_DEFAULT)
{
errno = ENOSYS;
return -1;
}
if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR)acl, &psid, &dflt)
&& psid)
flags |= OWNER_SECURITY_INFORMATION;
if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR)acl, &psid, &dflt)
&& psid)
flags |= GROUP_SECURITY_INFORMATION;
if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR)acl, &dacl_present,
&pacl, &dflt)
&& dacl_present)
flags |= DACL_SECURITY_INFORMATION;
if (!flags)
return 0;
/* According to KB-245153, setting the owner will succeed if either:
(1) the caller is the user who will be the new owner, and has the
SE_TAKE_OWNERSHIP privilege, or
(2) the caller has the SE_RESTORE privilege, in which case she can
set any valid user or group as the owner
We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
privileges, and disregard any failures in obtaining them. If
these privileges cannot be obtained, and do not already exist in
the calling thread's security token, this function could fail
with EPERM. */
if (enable_privilege (SE_TAKE_OWNERSHIP_NAME, TRUE, &old1))
st++;
if (enable_privilege (SE_RESTORE_NAME, TRUE, &old2))
st++;
e = errno;
errno = 0;
set_file_security ((char *)fname, flags, (PSECURITY_DESCRIPTOR)acl);
err = GetLastError ();
if (st >= 2)
restore_privilege (&old2);
if (st >= 1)
restore_privilege (&old1);
if (errno == ENOTSUP)
;
else if (err == ERROR_SUCCESS)
{
retval = 0;
errno = e;
}
else if (err == ERROR_INVALID_OWNER)
errno = EPERM;
else if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
errno = ENOENT;
return retval;
}
/* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
have a fixed max size for file names, so we don't need the kind of
alloc/malloc/realloc dance the gnulib version does. We also don't
@ -6848,6 +7258,11 @@ globals_of_w32 (void)
g_b_init_get_native_system_info = 0;
g_b_init_get_system_times = 0;
g_b_init_create_symbolic_link = 0;
g_b_init_get_security_descriptor_dacl = 0;
g_b_init_convert_sd_to_sddl = 0;
g_b_init_convert_sddl_to_sd = 0;
g_b_init_is_valid_security_descriptor = 0;
g_b_init_set_file_security = 0;
num_of_processors = 0;
/* The following sets a handler for shutdown notifications for
console apps. This actually applies to Emacs in both console and