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:
parent
207a7ef053
commit
66447e07c1
10 changed files with 518 additions and 6 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
5
etc/NEWS
5
etc/NEWS
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
25
nt/inc/sys/acl.h
Normal 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 */
|
||||
|
|
@ -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).
|
||||
|
|
|
|||
19
src/fileio.c
19
src/fileio.c
|
|
@ -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
415
src/w32.c
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue