emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r111259: Support Posix ACL APIs on MS


From: Eli Zaretskii
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r111259: Support Posix ACL APIs on MS-Windows.
Date: Mon, 17 Dec 2012 21:14:34 +0200
User-agent: Bazaar (2.5.0)

------------------------------------------------------------
revno: 111259
committer: Eli Zaretskii <address@hidden>
branch nick: trunk
timestamp: Mon 2012-12-17 21:14:34 +0200
message:
  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.
added:
  nt/inc/sys/acl.h
modified:
  doc/lispref/ChangeLog
  doc/lispref/files.texi
  etc/NEWS
  nt/ChangeLog
  nt/config.nt
  nt/inc/ms-w32.h
  src/ChangeLog
  src/fileio.c
  src/w32.c
=== modified file 'doc/lispref/ChangeLog'
--- a/doc/lispref/ChangeLog     2012-12-16 18:22:27 +0000
+++ b/doc/lispref/ChangeLog     2012-12-17 19:14:34 +0000
@@ -1,3 +1,8 @@
+2012-12-17  Eli Zaretskii  <address@hidden>
+
+       * files.texi (File Attributes, Changing Files): Update to include
+       MS-Windows support for ACLs.
+
 2012-12-16  Romain Francoise  <address@hidden>
 
        * files.texi (File Attributes): Document ACL support and new

=== modified file 'doc/lispref/files.texi'
--- a/doc/lispref/files.texi    2012-12-16 18:22:27 +0000
+++ b/doc/lispref/files.texi    2012-12-17 19:14:34 +0000
@@ -1357,13 +1357,14 @@
   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
address@hidden, 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 @@
 @end group
 @end example
 
address@hidden security descriptor, file
address@hidden SDDL, MS-Windows
+On MS-Windows, the return value is a textual description of the file's
address@hidden 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 @@
 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

=== modified file 'etc/NEWS'
--- a/etc/NEWS  2012-12-16 18:22:27 +0000
+++ b/etc/NEWS  2012-12-17 19:14:34 +0000
@@ -44,8 +44,9 @@
 *** 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
 

=== modified file 'nt/ChangeLog'
--- a/nt/ChangeLog      2012-12-15 13:42:33 +0000
+++ b/nt/ChangeLog      2012-12-17 19:14:34 +0000
@@ -1,3 +1,11 @@
+2012-12-17  Eli Zaretskii  <address@hidden>
+
+       * 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  <address@hidden>
 
        * inc/ms-w32.h (sys_unlink): Provide prototype.

=== modified file 'nt/config.nt'
--- a/nt/config.nt      2012-12-13 01:18:28 +0000
+++ b/nt/config.nt      2012-12-17 19:14:34 +0000
@@ -725,6 +725,9 @@
 /* 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
 

=== modified file 'nt/inc/ms-w32.h'
--- a/nt/inc/ms-w32.h   2012-12-15 13:38:21 +0000
+++ b/nt/inc/ms-w32.h   2012-12-17 19:14:34 +0000
@@ -293,6 +293,10 @@
 #define NSIG 23
 #endif
 
+#ifndef ENOTSUP
+#define ENOTSUP ENOSYS
+#endif
+
 #ifdef _MSC_VER
 typedef int sigset_t;
 typedef int ssize_t;

=== added file 'nt/inc/sys/acl.h'
--- a/nt/inc/sys/acl.h  1970-01-01 00:00:00 +0000
+++ b/nt/inc/sys/acl.h  2012-12-17 19:14:34 +0000
@@ -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 */

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2012-12-17 17:51:25 +0000
+++ b/src/ChangeLog     2012-12-17 19:14:34 +0000
@@ -1,3 +1,27 @@
+2012-12-17  Eli Zaretskii  <address@hidden>
+
+       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  <address@hidden>
 
        Don't reraise SIGCHLD, as that can now lose (Bug#13192).

=== modified file 'src/fileio.c'
--- a/src/fileio.c      2012-12-16 18:22:27 +0000
+++ b/src/fileio.c      2012-12-17 19:14:34 +0000
@@ -1956,6 +1956,14 @@
     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 @@
       /* 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);

=== modified file 'src/w32.c'
--- a/src/w32.c 2012-12-15 11:04:14 +0000
+++ b/src/w32.c 2012-12-17 19:14:34 +0000
@@ -117,6 +117,15 @@
 
 #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_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 @@
 #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 @@
     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 @@
     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 @@
     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 @@
   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 @@
     }
   if (s_pfn_Get_File_Security == NULL)
     {
+      errno = ENOTSUP;
       return FALSE;
     }
   return (s_pfn_Get_File_Security (lpFileName, RequestedInformation,
@@ -641,6 +680,35 @@
 }
 
 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,
                               LPBOOL lpbOwnerDefaulted)
@@ -649,6 +717,7 @@
   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 @@
     }
   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 @@
   HMODULE hm_advapi32 = NULL;
   if (is_windows_9x () == TRUE)
     {
+      errno = ENOTSUP;
       return FALSE;
     }
   if (g_b_init_get_security_descriptor_group == 0)
@@ -688,6 +759,7 @@
     }
   if (s_pfn_Get_Security_Descriptor_Group == NULL)
     {
+      errno = ENOTSUP;
       return FALSE;
     }
   return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor, pGroup,
@@ -695,6 +767,37 @@
 }
 
 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)
 {
   static IsValidSid_Proc s_pfn_Is_Valid_Sid = NULL;
@@ -888,6 +991,120 @@
     }
   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 @@
   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 @@
   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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]