aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2012-12-17 21:14:34 +0200
committerEli Zaretskii2012-12-17 21:14:34 +0200
commit66447e07c1aa037730127d6fcdd2658f87f13dc0 (patch)
tree0547cb5e75ae1ffeb51d7b3f80275e0a65f70720
parent207a7ef0531ca92468e19115a2c2064c9b22bfd4 (diff)
downloademacs-66447e07c1aa037730127d6fcdd2658f87f13dc0.tar.gz
emacs-66447e07c1aa037730127d6fcdd2658f87f13dc0.zip
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.
-rw-r--r--doc/lispref/ChangeLog5
-rw-r--r--doc/lispref/files.texi16
-rw-r--r--etc/NEWS5
-rw-r--r--nt/ChangeLog8
-rw-r--r--nt/config.nt3
-rw-r--r--nt/inc/ms-w32.h4
-rw-r--r--nt/inc/sys/acl.h25
-rw-r--r--src/ChangeLog24
-rw-r--r--src/fileio.c19
-rw-r--r--src/w32.c415
10 files changed, 518 insertions, 6 deletions
diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog
index 922147844bd..a0bbafb116f 100644
--- a/doc/lispref/ChangeLog
+++ b/doc/lispref/ChangeLog
@@ -1,3 +1,8 @@
12012-12-17 Eli Zaretskii <eliz@gnu.org>
2
3 * files.texi (File Attributes, Changing Files): Update to include
4 MS-Windows support for ACLs.
5
12012-12-16 Romain Francoise <romain@orebokech.com> 62012-12-16 Romain Francoise <romain@orebokech.com>
2 7
3 * files.texi (File Attributes): Document ACL support and new 8 * files.texi (File Attributes): Document ACL support and new
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 93bee961929..5440388fe70 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -1357,13 +1357,14 @@ support, then the return value is @code{(nil nil nil nil)}.
1357 If Emacs has been compiled with @dfn{ACL} (access control list) 1357 If Emacs has been compiled with @dfn{ACL} (access control list)
1358support, you can use the function @code{file-acl} to retrieve a file's 1358support, you can use the function @code{file-acl} to retrieve a file's
1359ACL entries. The format is platform-specific; on GNU/Linux and BSD, 1359ACL entries. The format is platform-specific; on GNU/Linux and BSD,
1360Emacs uses the POSIX ACL interface. For the function 1360Emacs uses the POSIX ACL interface, while on MS-Windows Emacs emulates
1361@code{set-file-acl}, see @ref{Changing Files}. 1361the POSIX ACL interface with native file security APIs. For the
1362function @code{set-file-acl}, see @ref{Changing Files}.
1362 1363
1363@defun file-acl filename 1364@defun file-acl filename
1364This function returns the ACL entries of the file @var{filename}. 1365This function returns the ACL entries of the file @var{filename}.
1365The return value is a string containing the textual representation of 1366The return value is a string containing the textual representation of
1366the ACL entries, like the following: 1367the ACL entries. On Posix hosts, it looks like this:
1367 1368
1368@example 1369@example
1369@group 1370@group
@@ -1375,6 +1376,12 @@ other::r--
1375@end group 1376@end group
1376@end example 1377@end example
1377 1378
1379@cindex security descriptor, file
1380@cindex SDDL, MS-Windows
1381On MS-Windows, the return value is a textual description of the file's
1382@dfn{security descriptor} in @acronym{SDDL}, the @dfn{Security
1383Descriptor Definition Language}.
1384
1378If the file does not exist or is inaccessible, or if Emacs was unable to 1385If the file does not exist or is inaccessible, or if Emacs was unable to
1379determine the ACL entries, then the return value is @code{nil}. The 1386determine the ACL entries, then the return value is @code{nil}. The
1380latter can happen for local files if Emacs was not compiled with ACL 1387latter can happen for local files if Emacs was not compiled with ACL
@@ -1719,7 +1726,8 @@ SELinux support.
1719This function sets the ACL entries of the file @var{filename} to 1726This function sets the ACL entries of the file @var{filename} to
1720@var{acl-string}. @xref{File Attributes}, for a brief description of 1727@var{acl-string}. @xref{File Attributes}, for a brief description of
1721ACLs. The @var{acl-string} argument should be a string containing the 1728ACLs. The @var{acl-string} argument should be a string containing the
1722textual representation of the desired ACL entries. 1729textual representation of the desired ACL entries in the format
1730appropriate for the ACL interface being used.
1723@end defun 1731@end defun
1724 1732
1725@node File Names 1733@node File Names
diff --git a/etc/NEWS b/etc/NEWS
index 1c82b760946..263ca3cd48a 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -44,8 +44,9 @@ simply disabling Transient Mark mode does the same thing.
44*** Emacs preserves the ACL entries of files when backing up. 44*** Emacs preserves the ACL entries of files when backing up.
45+++ 45+++
46*** New functions `file-acl' and `set-file-acl' get and set the ACL 46*** New functions `file-acl' and `set-file-acl' get and set the ACL
47entries of a file. On GNU/Linux the POSIX ACL interface is used via 47entries of a file. On GNU/Linux, the POSIX ACL interface is used via
48libacl. 48libacl. On MS-Windows, the NT Security APIs are used to emulate the
49POSIX ACL interfaces.
49 50
50* Editing Changes in Emacs 24.4 51* Editing Changes in Emacs 24.4
51 52
diff --git a/nt/ChangeLog b/nt/ChangeLog
index bcd15422bdf..114fa826b2b 100644
--- a/nt/ChangeLog
+++ b/nt/ChangeLog
@@ -1,3 +1,11 @@
12012-12-17 Eli Zaretskii <eliz@gnu.org>
2
3 * inc/sys/acl.h: New file.
4
5 * inc/ms-w32.h (ENOTSUP): Define if undefined.
6
7 * config.nt (HAVE_POSIX_ACL): Define.
8
12012-12-15 Eli Zaretskii <eliz@gnu.org> 92012-12-15 Eli Zaretskii <eliz@gnu.org>
2 10
3 * inc/ms-w32.h (sys_unlink): Provide prototype. 11 * inc/ms-w32.h (sys_unlink): Provide prototype.
diff --git a/nt/config.nt b/nt/config.nt
index db26bf6cbae..aef92a8cccd 100644
--- a/nt/config.nt
+++ b/nt/config.nt
@@ -725,6 +725,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
725/* Define to 1 if you have the <png.h> header file. */ 725/* Define to 1 if you have the <png.h> header file. */
726#undef HAVE_PNG_H 726#undef HAVE_PNG_H
727 727
728/* Define to 1 if you have the POSIX ACL support. */
729#define HAVE_POSIX_ACL 1
730
728/* Define to 1 if you have the `posix_memalign' function. */ 731/* Define to 1 if you have the `posix_memalign' function. */
729#undef HAVE_POSIX_MEMALIGN 732#undef HAVE_POSIX_MEMALIGN
730 733
diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h
index aab30391063..78e1d544cde 100644
--- a/nt/inc/ms-w32.h
+++ b/nt/inc/ms-w32.h
@@ -293,6 +293,10 @@ extern struct tm *localtime_r (time_t const * restrict, struct tm * restrict);
293#define NSIG 23 293#define NSIG 23
294#endif 294#endif
295 295
296#ifndef ENOTSUP
297#define ENOTSUP ENOSYS
298#endif
299
296#ifdef _MSC_VER 300#ifdef _MSC_VER
297typedef int sigset_t; 301typedef int sigset_t;
298typedef int ssize_t; 302typedef int ssize_t;
diff --git a/nt/inc/sys/acl.h b/nt/inc/sys/acl.h
new file mode 100644
index 00000000000..3133e3bfc09
--- /dev/null
+++ b/nt/inc/sys/acl.h
@@ -0,0 +1,25 @@
1/* Emulation of Posix ACLs for Windows. */
2
3#ifndef ACL_H
4#define ACL_H
5
6#define NOMINMAX 1 /* don't define min and max */
7#include <windows.h>
8
9typedef PSECURITY_DESCRIPTOR acl_t;
10typedef unsigned acl_type_t;
11
12/* Values of acl_type_t */
13#define ACL_TYPE_ACCESS 0
14#define ACL_TYPE_DEFAULT 1
15
16typedef unsigned acl_perm_t;
17
18extern int acl_valid (acl_t);
19extern acl_t acl_get_file (const char *, acl_type_t);
20extern int acl_set_file (const char *, acl_type_t, acl_t);
21extern char * acl_to_text (acl_t, ssize_t *);
22extern acl_t acl_from_text (const char *);
23extern int acl_free (void *);
24
25#endif /* ACL_H */
diff --git a/src/ChangeLog b/src/ChangeLog
index d5071c541b4..acfd5c561b7 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,27 @@
12012-12-17 Eli Zaretskii <eliz@gnu.org>
2
3 Emulate Posix ACL APIs on MS-Windows.
4 * w32.c: Include sddl.h and sys/acl.h.
5 (SDDL_REVISION_1): Define if not already defined.
6 (g_b_init_get_security_descriptor_dacl)
7 (g_b_init_convert_sd_to_sddl, g_b_init_convert_sddl_to_sd)
8 (g_b_init_is_valid_security_descriptor)
9 (g_b_init_set_file_security): New static flags.
10 (globals_of_w32): Initialize them to zero.
11 (SetFileSecurity_Name): New string constant.
12 (SetFileSecurity_Proc, GetSecurityDescriptorDacl_Proc)
13 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)
14 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)
15 (IsValidSecurityDescriptor_Proc): New typedefs.
16 (get_file_security, get_security_descriptor_owner)
17 (get_security_descriptor_group): Set errno to ENOTSUP.
18 (set_file_security, get_security_descriptor_dacl)
19 (is_valid_security_descriptor, convert_sd_to_sddl)
20 (convert_sddl_to_sd, acl_valid, acl_to_text, acl_from_text)
21 (acl_free, acl_get_file, acl_set_file): New functions.
22
23 * fileio.c (Fcopy_file) [WINDOWSNT]: Support copying ACLs.
24
12012-12-17 Paul Eggert <eggert@cs.ucla.edu> 252012-12-17 Paul Eggert <eggert@cs.ucla.edu>
2 26
3 Don't reraise SIGCHLD, as that can now lose (Bug#13192). 27 Don't reraise SIGCHLD, as that can now lose (Bug#13192).
diff --git a/src/fileio.c b/src/fileio.c
index f1cfe0eb625..26150a7e55b 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1956,6 +1956,14 @@ entries (depending on how Emacs was built). */)
1956 out_st.st_mode = 0; 1956 out_st.st_mode = 0;
1957 1957
1958#ifdef WINDOWSNT 1958#ifdef WINDOWSNT
1959 if (!NILP (preserve_extended_attributes))
1960 {
1961#ifdef HAVE_POSIX_ACL
1962 acl = acl_get_file (SDATA (encoded_file), ACL_TYPE_ACCESS);
1963 if (acl == NULL && errno != ENOTSUP)
1964 report_file_error ("Getting ACL", Fcons (file, Qnil));
1965#endif
1966 }
1959 if (!CopyFile (SDATA (encoded_file), 1967 if (!CopyFile (SDATA (encoded_file),
1960 SDATA (encoded_newname), 1968 SDATA (encoded_newname),
1961 FALSE)) 1969 FALSE))
@@ -1983,6 +1991,17 @@ entries (depending on how Emacs was built). */)
1983 /* Restore original attributes. */ 1991 /* Restore original attributes. */
1984 SetFileAttributes (filename, attributes); 1992 SetFileAttributes (filename, attributes);
1985 } 1993 }
1994#ifdef HAVE_POSIX_ACL
1995 if (acl != NULL)
1996 {
1997 bool fail =
1998 acl_set_file (SDATA (encoded_newname), ACL_TYPE_ACCESS, acl) != 0;
1999 if (fail && errno != ENOTSUP)
2000 report_file_error ("Setting ACL", Fcons (newname, Qnil));
2001
2002 acl_free (acl);
2003 }
2004#endif
1986#else /* not WINDOWSNT */ 2005#else /* not WINDOWSNT */
1987 immediate_quit = 1; 2006 immediate_quit = 1;
1988 ifd = emacs_open (SSDATA (encoded_file), O_RDONLY, 0); 2007 ifd = emacs_open (SSDATA (encoded_file), O_RDONLY, 0);
diff --git a/src/w32.c b/src/w32.c
index 50c81f88c72..8ef07e6b077 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -117,6 +117,15 @@ typedef struct _PROCESS_MEMORY_COUNTERS_EX {
117 117
118#include <winioctl.h> 118#include <winioctl.h>
119#include <aclapi.h> 119#include <aclapi.h>
120#include <sddl.h>
121
122#include <sys/acl.h>
123
124/* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
125 define them by hand if not already defined. */
126#ifndef SDDL_REVISION_1
127#define SDDL_REVISION_1 1
128#endif /* SDDL_REVISION_1 */
120 129
121#ifdef _MSC_VER 130#ifdef _MSC_VER
122/* MSVC doesn't provide the definition of REPARSE_DATA_BUFFER and the 131/* MSVC doesn't provide the definition of REPARSE_DATA_BUFFER and the
@@ -257,6 +266,11 @@ static BOOL g_b_init_copy_sid;
257static BOOL g_b_init_get_native_system_info; 266static BOOL g_b_init_get_native_system_info;
258static BOOL g_b_init_get_system_times; 267static BOOL g_b_init_get_system_times;
259static BOOL g_b_init_create_symbolic_link; 268static BOOL g_b_init_create_symbolic_link;
269static BOOL g_b_init_get_security_descriptor_dacl;
270static BOOL g_b_init_convert_sd_to_sddl;
271static BOOL g_b_init_convert_sddl_to_sd;
272static BOOL g_b_init_is_valid_security_descriptor;
273static BOOL g_b_init_set_file_security;
260 274
261/* 275/*
262 BEGIN: Wrapper functions around OpenProcessToken 276 BEGIN: Wrapper functions around OpenProcessToken
@@ -286,9 +300,11 @@ GetProcessTimes_Proc get_process_times_fn = NULL;
286#ifdef _UNICODE 300#ifdef _UNICODE
287const char * const LookupAccountSid_Name = "LookupAccountSidW"; 301const char * const LookupAccountSid_Name = "LookupAccountSidW";
288const char * const GetFileSecurity_Name = "GetFileSecurityW"; 302const char * const GetFileSecurity_Name = "GetFileSecurityW";
303const char * const SetFileSecurity_Name = "SetFileSecurityW";
289#else 304#else
290const char * const LookupAccountSid_Name = "LookupAccountSidA"; 305const char * const LookupAccountSid_Name = "LookupAccountSidA";
291const char * const GetFileSecurity_Name = "GetFileSecurityA"; 306const char * const GetFileSecurity_Name = "GetFileSecurityA";
307const char * const SetFileSecurity_Name = "SetFileSecurityA";
292#endif 308#endif
293typedef BOOL (WINAPI * LookupAccountSid_Proc) ( 309typedef BOOL (WINAPI * LookupAccountSid_Proc) (
294 LPCTSTR lpSystemName, 310 LPCTSTR lpSystemName,
@@ -318,6 +334,10 @@ typedef BOOL (WINAPI * GetFileSecurity_Proc) (
318 PSECURITY_DESCRIPTOR pSecurityDescriptor, 334 PSECURITY_DESCRIPTOR pSecurityDescriptor,
319 DWORD nLength, 335 DWORD nLength,
320 LPDWORD lpnLengthNeeded); 336 LPDWORD lpnLengthNeeded);
337typedef BOOL (WINAPI *SetFileSecurity_Proc) (
338 LPCTSTR lpFileName,
339 SECURITY_INFORMATION SecurityInformation,
340 PSECURITY_DESCRIPTOR pSecurityDescriptor);
321typedef BOOL (WINAPI * GetSecurityDescriptorOwner_Proc) ( 341typedef BOOL (WINAPI * GetSecurityDescriptorOwner_Proc) (
322 PSECURITY_DESCRIPTOR pSecurityDescriptor, 342 PSECURITY_DESCRIPTOR pSecurityDescriptor,
323 PSID *pOwner, 343 PSID *pOwner,
@@ -326,6 +346,11 @@ typedef BOOL (WINAPI * GetSecurityDescriptorGroup_Proc) (
326 PSECURITY_DESCRIPTOR pSecurityDescriptor, 346 PSECURITY_DESCRIPTOR pSecurityDescriptor,
327 PSID *pGroup, 347 PSID *pGroup,
328 LPBOOL lpbGroupDefaulted); 348 LPBOOL lpbGroupDefaulted);
349typedef BOOL (WINAPI *GetSecurityDescriptorDacl_Proc) (
350 PSECURITY_DESCRIPTOR pSecurityDescriptor,
351 LPBOOL lpbDaclPresent,
352 PACL *pDacl,
353 LPBOOL lpbDaclDefaulted);
329typedef BOOL (WINAPI * IsValidSid_Proc) ( 354typedef BOOL (WINAPI * IsValidSid_Proc) (
330 PSID sid); 355 PSID sid);
331typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_Proc) ( 356typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_Proc) (
@@ -376,6 +401,18 @@ typedef BOOLEAN (WINAPI *CreateSymbolicLink_Proc) (
376 LPTSTR lpSymlinkFileName, 401 LPTSTR lpSymlinkFileName,
377 LPTSTR lpTargetFileName, 402 LPTSTR lpTargetFileName,
378 DWORD dwFlags); 403 DWORD dwFlags);
404typedef BOOL (WINAPI *ConvertStringSecurityDescriptorToSecurityDescriptor_Proc) (
405 LPCTSTR StringSecurityDescriptor,
406 DWORD StringSDRevision,
407 PSECURITY_DESCRIPTOR *SecurityDescriptor,
408 PULONG SecurityDescriptorSize);
409typedef BOOL (WINAPI *ConvertSecurityDescriptorToStringSecurityDescriptor_Proc) (
410 PSECURITY_DESCRIPTOR SecurityDescriptor,
411 DWORD RequestedStringSDRevision,
412 SECURITY_INFORMATION SecurityInformation,
413 LPTSTR *StringSecurityDescriptor,
414 PULONG StringSecurityDescriptorLen);
415typedef BOOL (WINAPI *IsValidSecurityDescriptor_Proc) (PSECURITY_DESCRIPTOR);
379 416
380 /* ** A utility function ** */ 417 /* ** A utility function ** */
381static BOOL 418static BOOL
@@ -621,6 +658,7 @@ get_file_security (LPCTSTR lpFileName,
621 HMODULE hm_advapi32 = NULL; 658 HMODULE hm_advapi32 = NULL;
622 if (is_windows_9x () == TRUE) 659 if (is_windows_9x () == TRUE)
623 { 660 {
661 errno = ENOTSUP;
624 return FALSE; 662 return FALSE;
625 } 663 }
626 if (g_b_init_get_file_security == 0) 664 if (g_b_init_get_file_security == 0)
@@ -633,6 +671,7 @@ get_file_security (LPCTSTR lpFileName,
633 } 671 }
634 if (s_pfn_Get_File_Security == NULL) 672 if (s_pfn_Get_File_Security == NULL)
635 { 673 {
674 errno = ENOTSUP;
636 return FALSE; 675 return FALSE;
637 } 676 }
638 return (s_pfn_Get_File_Security (lpFileName, RequestedInformation, 677 return (s_pfn_Get_File_Security (lpFileName, RequestedInformation,
@@ -641,6 +680,35 @@ get_file_security (LPCTSTR lpFileName,
641} 680}
642 681
643static BOOL WINAPI 682static BOOL WINAPI
683set_file_security (LPCTSTR lpFileName,
684 SECURITY_INFORMATION SecurityInformation,
685 PSECURITY_DESCRIPTOR pSecurityDescriptor)
686{
687 static SetFileSecurity_Proc s_pfn_Set_File_Security = NULL;
688 HMODULE hm_advapi32 = NULL;
689 if (is_windows_9x () == TRUE)
690 {
691 errno = ENOTSUP;
692 return FALSE;
693 }
694 if (g_b_init_set_file_security == 0)
695 {
696 g_b_init_set_file_security = 1;
697 hm_advapi32 = LoadLibrary ("Advapi32.dll");
698 s_pfn_Set_File_Security =
699 (SetFileSecurity_Proc) GetProcAddress (
700 hm_advapi32, SetFileSecurity_Name);
701 }
702 if (s_pfn_Set_File_Security == NULL)
703 {
704 errno = ENOTSUP;
705 return FALSE;
706 }
707 return (s_pfn_Set_File_Security (lpFileName, SecurityInformation,
708 pSecurityDescriptor));
709}
710
711static BOOL WINAPI
644get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor, 712get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
645 PSID *pOwner, 713 PSID *pOwner,
646 LPBOOL lpbOwnerDefaulted) 714 LPBOOL lpbOwnerDefaulted)
@@ -649,6 +717,7 @@ get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
649 HMODULE hm_advapi32 = NULL; 717 HMODULE hm_advapi32 = NULL;
650 if (is_windows_9x () == TRUE) 718 if (is_windows_9x () == TRUE)
651 { 719 {
720 errno = ENOTSUP;
652 return FALSE; 721 return FALSE;
653 } 722 }
654 if (g_b_init_get_security_descriptor_owner == 0) 723 if (g_b_init_get_security_descriptor_owner == 0)
@@ -661,6 +730,7 @@ get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
661 } 730 }
662 if (s_pfn_Get_Security_Descriptor_Owner == NULL) 731 if (s_pfn_Get_Security_Descriptor_Owner == NULL)
663 { 732 {
733 errno = ENOTSUP;
664 return FALSE; 734 return FALSE;
665 } 735 }
666 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor, pOwner, 736 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor, pOwner,
@@ -676,6 +746,7 @@ get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
676 HMODULE hm_advapi32 = NULL; 746 HMODULE hm_advapi32 = NULL;
677 if (is_windows_9x () == TRUE) 747 if (is_windows_9x () == TRUE)
678 { 748 {
749 errno = ENOTSUP;
679 return FALSE; 750 return FALSE;
680 } 751 }
681 if (g_b_init_get_security_descriptor_group == 0) 752 if (g_b_init_get_security_descriptor_group == 0)
@@ -688,6 +759,7 @@ get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
688 } 759 }
689 if (s_pfn_Get_Security_Descriptor_Group == NULL) 760 if (s_pfn_Get_Security_Descriptor_Group == NULL)
690 { 761 {
762 errno = ENOTSUP;
691 return FALSE; 763 return FALSE;
692 } 764 }
693 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor, pGroup, 765 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor, pGroup,
@@ -695,6 +767,37 @@ get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
695} 767}
696 768
697static BOOL WINAPI 769static BOOL WINAPI
770get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor,
771 LPBOOL lpbDaclPresent,
772 PACL *pDacl,
773 LPBOOL lpbDaclDefaulted)
774{
775 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl = NULL;
776 HMODULE hm_advapi32 = NULL;
777 if (is_windows_9x () == TRUE)
778 {
779 errno = ENOTSUP;
780 return FALSE;
781 }
782 if (g_b_init_get_security_descriptor_dacl == 0)
783 {
784 g_b_init_get_security_descriptor_dacl = 1;
785 hm_advapi32 = LoadLibrary ("Advapi32.dll");
786 s_pfn_Get_Security_Descriptor_Dacl =
787 (GetSecurityDescriptorDacl_Proc) GetProcAddress (
788 hm_advapi32, "GetSecurityDescriptorDacl");
789 }
790 if (s_pfn_Get_Security_Descriptor_Dacl == NULL)
791 {
792 errno = ENOTSUP;
793 return FALSE;
794 }
795 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor,
796 lpbDaclPresent, pDacl,
797 lpbDaclDefaulted));
798}
799
800static BOOL WINAPI
698is_valid_sid (PSID sid) 801is_valid_sid (PSID sid)
699{ 802{
700 static IsValidSid_Proc s_pfn_Is_Valid_Sid = NULL; 803 static IsValidSid_Proc s_pfn_Is_Valid_Sid = NULL;
@@ -888,6 +991,120 @@ create_symbolic_link (LPTSTR lpSymlinkFilename,
888 } 991 }
889 return retval; 992 return retval;
890} 993}
994
995static BOOL WINAPI
996is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor)
997{
998 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc = NULL;
999
1000 if (is_windows_9x () == TRUE)
1001 {
1002 errno = ENOTSUP;
1003 return FALSE;
1004 }
1005
1006 if (g_b_init_is_valid_security_descriptor == 0)
1007 {
1008 g_b_init_is_valid_security_descriptor = 1;
1009 s_pfn_Is_Valid_Security_Descriptor_Proc =
1010 (IsValidSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1011 "IsValidSecurityDescriptor");
1012 }
1013 if (s_pfn_Is_Valid_Security_Descriptor_Proc == NULL)
1014 {
1015 errno = ENOTSUP;
1016 return FALSE;
1017 }
1018
1019 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor);
1020}
1021
1022static BOOL WINAPI
1023convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor,
1024 DWORD RequestedStringSDRevision,
1025 SECURITY_INFORMATION SecurityInformation,
1026 LPTSTR *StringSecurityDescriptor,
1027 PULONG StringSecurityDescriptorLen)
1028{
1029 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL = NULL;
1030 BOOL retval;
1031
1032 if (is_windows_9x () == TRUE)
1033 {
1034 errno = ENOTSUP;
1035 return FALSE;
1036 }
1037
1038 if (g_b_init_convert_sd_to_sddl == 0)
1039 {
1040 g_b_init_convert_sd_to_sddl = 1;
1041#ifdef _UNICODE
1042 s_pfn_Convert_SD_To_SDDL =
1043 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1044 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1045#else
1046 s_pfn_Convert_SD_To_SDDL =
1047 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1048 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1049#endif
1050 }
1051 if (s_pfn_Convert_SD_To_SDDL == NULL)
1052 {
1053 errno = ENOTSUP;
1054 return FALSE;
1055 }
1056
1057 retval = s_pfn_Convert_SD_To_SDDL (SecurityDescriptor,
1058 RequestedStringSDRevision,
1059 SecurityInformation,
1060 StringSecurityDescriptor,
1061 StringSecurityDescriptorLen);
1062
1063 return retval;
1064}
1065
1066static BOOL WINAPI
1067convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor,
1068 DWORD StringSDRevision,
1069 PSECURITY_DESCRIPTOR *SecurityDescriptor,
1070 PULONG SecurityDescriptorSize)
1071{
1072 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD = NULL;
1073 BOOL retval;
1074
1075 if (is_windows_9x () == TRUE)
1076 {
1077 errno = ENOTSUP;
1078 return FALSE;
1079 }
1080
1081 if (g_b_init_convert_sddl_to_sd == 0)
1082 {
1083 g_b_init_convert_sddl_to_sd = 1;
1084#ifdef _UNICODE
1085 s_pfn_Convert_SDDL_To_SD =
1086 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1087 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1088#else
1089 s_pfn_Convert_SDDL_To_SD =
1090 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1091 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1092#endif
1093 }
1094 if (s_pfn_Convert_SDDL_To_SD == NULL)
1095 {
1096 errno = ENOTSUP;
1097 return FALSE;
1098 }
1099
1100 retval = s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor,
1101 StringSDRevision,
1102 SecurityDescriptor,
1103 SecurityDescriptorSize);
1104
1105 return retval;
1106}
1107
891 1108
892 1109
893/* Return 1 if P is a valid pointer to an object of size SIZE. Return 1110/* Return 1 if P is a valid pointer to an object of size SIZE. Return
@@ -4477,6 +4694,199 @@ chase_symlinks (const char *file)
4477 return target; 4694 return target;
4478} 4695}
4479 4696
4697
4698/* Posix ACL emulation. */
4699
4700int
4701acl_valid (acl_t acl)
4702{
4703 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR)acl) ? 0 : -1;
4704}
4705
4706char *
4707acl_to_text (acl_t acl, ssize_t *size)
4708{
4709 LPTSTR str_acl;
4710 SECURITY_INFORMATION flags =
4711 OWNER_SECURITY_INFORMATION |
4712 GROUP_SECURITY_INFORMATION |
4713 DACL_SECURITY_INFORMATION;
4714 char *retval = NULL;
4715 ssize_t local_size;
4716 int e = errno;
4717
4718 errno = 0;
4719
4720 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR)acl, SDDL_REVISION_1, flags, &str_acl, &local_size))
4721 {
4722 errno = e;
4723 /* We don't want to mix heaps, so we duplicate the string in our
4724 heap and free the one allocated by the API. */
4725 retval = xstrdup (str_acl);
4726 if (size)
4727 *size = local_size;
4728 LocalFree (str_acl);
4729 }
4730 else if (errno != ENOTSUP)
4731 errno = EINVAL;
4732
4733 return retval;
4734}
4735
4736acl_t
4737acl_from_text (const char *acl_str)
4738{
4739 PSECURITY_DESCRIPTOR psd, retval = NULL;
4740 ULONG sd_size;
4741 int e = errno;
4742
4743 errno = 0;
4744
4745 if (convert_sddl_to_sd (acl_str, SDDL_REVISION_1, &psd, &sd_size))
4746 {
4747 errno = e;
4748 retval = xmalloc (sd_size);
4749 memcpy (retval, psd, sd_size);
4750 LocalFree (psd);
4751 }
4752 else if (errno != ENOTSUP)
4753 errno = EINVAL;
4754
4755 return retval;
4756}
4757
4758int
4759acl_free (void *ptr)
4760{
4761 xfree (ptr);
4762 return 0;
4763}
4764
4765acl_t
4766acl_get_file (const char *fname, acl_type_t type)
4767{
4768 PSECURITY_DESCRIPTOR psd = NULL;
4769
4770 if (type == ACL_TYPE_ACCESS)
4771 {
4772 DWORD sd_len, err;
4773 SECURITY_INFORMATION si =
4774 OWNER_SECURITY_INFORMATION |
4775 GROUP_SECURITY_INFORMATION |
4776 DACL_SECURITY_INFORMATION ;
4777 int e = errno;
4778
4779 errno = 0;
4780 if (!get_file_security (fname, si, psd, 0, &sd_len)
4781 && errno != ENOTSUP)
4782 {
4783 err = GetLastError ();
4784 if (err == ERROR_INSUFFICIENT_BUFFER)
4785 {
4786 psd = xmalloc (sd_len);
4787 if (!get_file_security (fname, si, psd, sd_len, &sd_len))
4788 {
4789 xfree (psd);
4790 errno = EIO;
4791 psd = NULL;
4792 }
4793 }
4794 else if (err == ERROR_FILE_NOT_FOUND
4795 || err == ERROR_PATH_NOT_FOUND)
4796 errno = ENOENT;
4797 else
4798 errno = EIO;
4799 }
4800 else if (!errno)
4801 errno = e;
4802 }
4803 else if (type != ACL_TYPE_DEFAULT)
4804 errno = EINVAL;
4805
4806 return psd;
4807}
4808
4809int
4810acl_set_file (const char *fname, acl_type_t type, acl_t acl)
4811{
4812 TOKEN_PRIVILEGES old1, old2;
4813 DWORD err;
4814 BOOL res;
4815 int st = 0, retval = -1;
4816 SECURITY_INFORMATION flags = 0;
4817 PSID psid;
4818 PACL pacl;
4819 BOOL dflt;
4820 BOOL dacl_present;
4821 int e;
4822
4823 if (acl_valid (acl) != 0
4824 || (type != ACL_TYPE_DEFAULT && type != ACL_TYPE_ACCESS))
4825 {
4826 errno = EINVAL;
4827 return -1;
4828 }
4829
4830 if (type == ACL_TYPE_DEFAULT)
4831 {
4832 errno = ENOSYS;
4833 return -1;
4834 }
4835
4836 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR)acl, &psid, &dflt)
4837 && psid)
4838 flags |= OWNER_SECURITY_INFORMATION;
4839 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR)acl, &psid, &dflt)
4840 && psid)
4841 flags |= GROUP_SECURITY_INFORMATION;
4842 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR)acl, &dacl_present,
4843 &pacl, &dflt)
4844 && dacl_present)
4845 flags |= DACL_SECURITY_INFORMATION;
4846 if (!flags)
4847 return 0;
4848
4849 /* According to KB-245153, setting the owner will succeed if either:
4850 (1) the caller is the user who will be the new owner, and has the
4851 SE_TAKE_OWNERSHIP privilege, or
4852 (2) the caller has the SE_RESTORE privilege, in which case she can
4853 set any valid user or group as the owner
4854
4855 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
4856 privileges, and disregard any failures in obtaining them. If
4857 these privileges cannot be obtained, and do not already exist in
4858 the calling thread's security token, this function could fail
4859 with EPERM. */
4860 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME, TRUE, &old1))
4861 st++;
4862 if (enable_privilege (SE_RESTORE_NAME, TRUE, &old2))
4863 st++;
4864
4865 e = errno;
4866 errno = 0;
4867 set_file_security ((char *)fname, flags, (PSECURITY_DESCRIPTOR)acl);
4868 err = GetLastError ();
4869 if (st >= 2)
4870 restore_privilege (&old2);
4871 if (st >= 1)
4872 restore_privilege (&old1);
4873
4874 if (errno == ENOTSUP)
4875 ;
4876 else if (err == ERROR_SUCCESS)
4877 {
4878 retval = 0;
4879 errno = e;
4880 }
4881 else if (err == ERROR_INVALID_OWNER)
4882 errno = EPERM;
4883 else if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
4884 errno = ENOENT;
4885
4886 return retval;
4887}
4888
4889
4480/* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We 4890/* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
4481 have a fixed max size for file names, so we don't need the kind of 4891 have a fixed max size for file names, so we don't need the kind of
4482 alloc/malloc/realloc dance the gnulib version does. We also don't 4892 alloc/malloc/realloc dance the gnulib version does. We also don't
@@ -6848,6 +7258,11 @@ globals_of_w32 (void)
6848 g_b_init_get_native_system_info = 0; 7258 g_b_init_get_native_system_info = 0;
6849 g_b_init_get_system_times = 0; 7259 g_b_init_get_system_times = 0;
6850 g_b_init_create_symbolic_link = 0; 7260 g_b_init_create_symbolic_link = 0;
7261 g_b_init_get_security_descriptor_dacl = 0;
7262 g_b_init_convert_sd_to_sddl = 0;
7263 g_b_init_convert_sddl_to_sd = 0;
7264 g_b_init_is_valid_security_descriptor = 0;
7265 g_b_init_set_file_security = 0;
6851 num_of_processors = 0; 7266 num_of_processors = 0;
6852 /* The following sets a handler for shutdown notifications for 7267 /* The following sets a handler for shutdown notifications for
6853 console apps. This actually applies to Emacs in both console and 7268 console apps. This actually applies to Emacs in both console and