Created
August 27, 2012 14:52
-
-
Save k-takata/3489193 to your computer and use it in GitHub Desktop.
fix ACL setting on Win32
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -r 536aa8b0c934 src/os_win32.c | |
--- a/src/os_win32.c Wed Aug 15 17:43:31 2012 +0200 | |
+++ b/src/os_win32.c Fri Aug 31 19:26:04 2012 +0900 | |
@@ -433,19 +433,33 @@ | |
#ifdef HAVE_ACL | |
# include <aclapi.h> | |
+# ifndef PROTECTED_DACL_SECURITY_INFORMATION | |
+# define PROTECTED_DACL_SECURITY_INFORMATION 0x80000000L | |
+# endif | |
/* | |
* These are needed to dynamically load the ADVAPI DLL, which is not | |
* implemented under Windows 95 (and causes VIM to crash) | |
*/ | |
-typedef DWORD (WINAPI *PSNSECINFO) (LPTSTR, enum SE_OBJECT_TYPE, | |
+typedef DWORD (WINAPI *PSNSECINFO) (LPSTR, enum SE_OBJECT_TYPE, | |
SECURITY_INFORMATION, PSID, PSID, PACL, PACL); | |
typedef DWORD (WINAPI *PGNSECINFO) (LPSTR, enum SE_OBJECT_TYPE, | |
SECURITY_INFORMATION, PSID *, PSID *, PACL *, PACL *, | |
PSECURITY_DESCRIPTOR *); | |
+# ifdef FEAT_MBYTE | |
+typedef DWORD (WINAPI *PSNSECINFOW) (LPWSTR, enum SE_OBJECT_TYPE, | |
+ SECURITY_INFORMATION, PSID, PSID, PACL, PACL); | |
+typedef DWORD (WINAPI *PGNSECINFOW) (LPWSTR, enum SE_OBJECT_TYPE, | |
+ SECURITY_INFORMATION, PSID *, PSID *, PACL *, PACL *, | |
+ PSECURITY_DESCRIPTOR *); | |
+# endif | |
static HANDLE advapi_lib = NULL; /* Handle for ADVAPI library */ | |
static PSNSECINFO pSetNamedSecurityInfo; | |
static PGNSECINFO pGetNamedSecurityInfo; | |
+# ifdef FEAT_MBYTE | |
+static PSNSECINFOW pSetNamedSecurityInfoW; | |
+static PGNSECINFOW pGetNamedSecurityInfoW; | |
+# endif | |
#endif | |
typedef BOOL (WINAPI *PSETHANDLEINFORMATION)(HANDLE, DWORD, DWORD); | |
@@ -453,6 +467,42 @@ | |
static BOOL allowPiping = FALSE; | |
static PSETHANDLEINFORMATION pSetHandleInformation; | |
+#ifdef HAVE_ACL | |
+/* | |
+ * Enables or disables the specified privilege. | |
+ */ | |
+ static BOOL | |
+win32_enable_privilege(LPTSTR lpszPrivilege, BOOL bEnable) | |
+{ | |
+ BOOL bResult; | |
+ LUID luid; | |
+ HANDLE hToken; | |
+ TOKEN_PRIVILEGES tokenPrivileges; | |
+ | |
+ if (!OpenProcessToken(GetCurrentProcess(), | |
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) | |
+ return FALSE; | |
+ | |
+ if (!LookupPrivilegeValue(NULL, lpszPrivilege, &luid)) | |
+ { | |
+ CloseHandle(hToken); | |
+ return FALSE; | |
+ } | |
+ | |
+ tokenPrivileges.PrivilegeCount = 1; | |
+ tokenPrivileges.Privileges[0].Luid = luid; | |
+ tokenPrivileges.Privileges[0].Attributes = bEnable ? | |
+ SE_PRIVILEGE_ENABLED : 0; | |
+ | |
+ bResult = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, | |
+ sizeof(TOKEN_PRIVILEGES), NULL, NULL); | |
+ | |
+ CloseHandle(hToken); | |
+ | |
+ return bResult && GetLastError() == ERROR_SUCCESS; | |
+} | |
+#endif | |
+ | |
/* | |
* Set g_PlatformId to VER_PLATFORM_WIN32_NT (NT) or | |
* VER_PLATFORM_WIN32_WINDOWS (Win95). | |
@@ -492,14 +542,27 @@ | |
"SetNamedSecurityInfoA"); | |
pGetNamedSecurityInfo = (PGNSECINFO)GetProcAddress(advapi_lib, | |
"GetNamedSecurityInfoA"); | |
+# ifdef FEAT_MBYTE | |
+ pSetNamedSecurityInfoW = (PSNSECINFOW)GetProcAddress(advapi_lib, | |
+ "SetNamedSecurityInfoW"); | |
+ pGetNamedSecurityInfoW = (PGNSECINFOW)GetProcAddress(advapi_lib, | |
+ "GetNamedSecurityInfoW"); | |
+# endif | |
if (pSetNamedSecurityInfo == NULL | |
- || pGetNamedSecurityInfo == NULL) | |
+ || pGetNamedSecurityInfo == NULL | |
+# ifdef FEAT_MBYTE | |
+ || pSetNamedSecurityInfoW == NULL | |
+ || pGetNamedSecurityInfoW == NULL | |
+# endif | |
+ ) | |
{ | |
/* If we can't get the function addresses, set advapi_lib | |
* to NULL so that we don't use them. */ | |
FreeLibrary(advapi_lib); | |
advapi_lib = NULL; | |
} | |
+ /* Enable privilege for getting or setting SACLs. */ | |
+ win32_enable_privilege(SE_SECURITY_NAME, TRUE); | |
} | |
} | |
#endif | |
@@ -2906,6 +2969,7 @@ | |
return (vim_acl_T)NULL; | |
#else | |
struct my_acl *p = NULL; | |
+ DWORD err; | |
/* This only works on Windows NT and 2000. */ | |
if (g_PlatformId == VER_PLATFORM_WIN32_NT && advapi_lib != NULL) | |
@@ -2913,23 +2977,82 @@ | |
p = (struct my_acl *)alloc_clear((unsigned)sizeof(struct my_acl)); | |
if (p != NULL) | |
{ | |
- if (pGetNamedSecurityInfo( | |
- (LPTSTR)fname, // Abstract filename | |
- SE_FILE_OBJECT, // File Object | |
- // Retrieve the entire security descriptor. | |
- OWNER_SECURITY_INFORMATION | | |
- GROUP_SECURITY_INFORMATION | | |
- DACL_SECURITY_INFORMATION | | |
- SACL_SECURITY_INFORMATION, | |
- &p->pSidOwner, // Ownership information. | |
- &p->pSidGroup, // Group membership. | |
- &p->pDacl, // Discretionary information. | |
- &p->pSacl, // For auditing purposes. | |
- &p->pSecurityDescriptor | |
- ) != ERROR_SUCCESS) | |
+# ifdef FEAT_MBYTE | |
+ WCHAR *wn = NULL; | |
+ | |
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) | |
+ wn = enc_to_utf16(fname, NULL); | |
+ if (wn != NULL) | |
{ | |
- mch_free_acl((vim_acl_T)p); | |
- p = NULL; | |
+ /* Try to retrieve the entire security descriptor. */ | |
+ err = pGetNamedSecurityInfoW( | |
+ wn, // Abstract filename | |
+ SE_FILE_OBJECT, // File Object | |
+ OWNER_SECURITY_INFORMATION | | |
+ GROUP_SECURITY_INFORMATION | | |
+ DACL_SECURITY_INFORMATION | | |
+ SACL_SECURITY_INFORMATION, | |
+ &p->pSidOwner, // Ownership information. | |
+ &p->pSidGroup, // Group membership. | |
+ &p->pDacl, // Discretionary information. | |
+ &p->pSacl, // For auditing purposes. | |
+ &p->pSecurityDescriptor); | |
+ if (err == ERROR_ACCESS_DENIED || | |
+ err == ERROR_PRIVILEGE_NOT_HELD) | |
+ { | |
+ /* Retrieve only DACL. */ | |
+ (void)pGetNamedSecurityInfoW( | |
+ wn, | |
+ SE_FILE_OBJECT, | |
+ DACL_SECURITY_INFORMATION, | |
+ NULL, | |
+ NULL, | |
+ &p->pDacl, | |
+ NULL, | |
+ &p->pSecurityDescriptor); | |
+ } | |
+ if (p->pSecurityDescriptor == NULL) | |
+ { | |
+ mch_free_acl((vim_acl_T)p); | |
+ p = NULL; | |
+ } | |
+ vim_free(wn); | |
+ } | |
+ else | |
+# endif | |
+ { | |
+ /* Try to retrieve the entire security descriptor. */ | |
+ err = pGetNamedSecurityInfo( | |
+ (LPSTR)fname, // Abstract filename | |
+ SE_FILE_OBJECT, // File Object | |
+ OWNER_SECURITY_INFORMATION | | |
+ GROUP_SECURITY_INFORMATION | | |
+ DACL_SECURITY_INFORMATION | | |
+ SACL_SECURITY_INFORMATION, | |
+ &p->pSidOwner, // Ownership information. | |
+ &p->pSidGroup, // Group membership. | |
+ &p->pDacl, // Discretionary information. | |
+ &p->pSacl, // For auditing purposes. | |
+ &p->pSecurityDescriptor); | |
+ if (err == ERROR_ACCESS_DENIED || | |
+ err == ERROR_PRIVILEGE_NOT_HELD) | |
+ { | |
+ /* Retrieve only DACL. */ | |
+ (void)pGetNamedSecurityInfo( | |
+ (LPSTR)fname, | |
+ SE_FILE_OBJECT, | |
+ DACL_SECURITY_INFORMATION, | |
+ NULL, | |
+ NULL, | |
+ &p->pDacl, | |
+ NULL, | |
+ &p->pSecurityDescriptor); | |
+ } | |
+ if (p->pSecurityDescriptor == NULL) | |
+ { | |
+ mch_free_acl((vim_acl_T)p); | |
+ p = NULL; | |
+ } | |
} | |
} | |
} | |
@@ -2938,6 +3061,29 @@ | |
#endif | |
} | |
+#ifdef HAVE_ACL | |
+/* | |
+ * Check if "acl" contains inherited ACE. | |
+ */ | |
+ static BOOL | |
+is_acl_inherited(PACL acl) | |
+{ | |
+ DWORD i; | |
+ ACL_SIZE_INFORMATION acl_info; | |
+ PACCESS_ALLOWED_ACE ace; | |
+ | |
+ acl_info.AceCount = 0; | |
+ GetAclInformation(acl, &acl_info, sizeof(acl_info), AclSizeInformation); | |
+ for (i = 0; i < acl_info.AceCount; i++) | |
+ { | |
+ GetAce(acl, i, (LPVOID *)&ace); | |
+ if (ace->Header.AceFlags & INHERITED_ACE) | |
+ return TRUE; | |
+ } | |
+ return FALSE; | |
+} | |
+#endif | |
+ | |
/* | |
* Set the ACL of file "fname" to "acl" (unless it's NULL). | |
* Errors are ignored. | |
@@ -2948,21 +3094,61 @@ | |
{ | |
#ifdef HAVE_ACL | |
struct my_acl *p = (struct my_acl *)acl; | |
+ SECURITY_INFORMATION sec_info = 0; | |
if (p != NULL && advapi_lib != NULL) | |
- (void)pSetNamedSecurityInfo( | |
- (LPTSTR)fname, // Abstract filename | |
- SE_FILE_OBJECT, // File Object | |
- // Retrieve the entire security descriptor. | |
- OWNER_SECURITY_INFORMATION | | |
- GROUP_SECURITY_INFORMATION | | |
- DACL_SECURITY_INFORMATION | | |
- SACL_SECURITY_INFORMATION, | |
- p->pSidOwner, // Ownership information. | |
- p->pSidGroup, // Group membership. | |
- p->pDacl, // Discretionary information. | |
- p->pSacl // For auditing purposes. | |
- ); | |
+ { | |
+# ifdef FEAT_MBYTE | |
+ WCHAR *wn = NULL; | |
+# endif | |
+ | |
+ /* Set security flags */ | |
+ if (p->pSidOwner) | |
+ sec_info |= OWNER_SECURITY_INFORMATION; | |
+ if (p->pSidGroup) | |
+ sec_info |= GROUP_SECURITY_INFORMATION; | |
+ if (p->pDacl) | |
+ { | |
+ sec_info |= DACL_SECURITY_INFORMATION; | |
+ /* Do not inherit its parent's DACL. | |
+ * If the DACL is inherited, Cygwin permissions would be changed. | |
+ */ | |
+ if (!is_acl_inherited(p->pDacl)) | |
+ sec_info |= PROTECTED_DACL_SECURITY_INFORMATION; | |
+ } | |
+ if (p->pSacl) | |
+ sec_info |= SACL_SECURITY_INFORMATION; | |
+ | |
+# ifdef FEAT_MBYTE | |
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) | |
+ wn = enc_to_utf16(fname, NULL); | |
+ if (wn != NULL) | |
+ { | |
+ (void)pSetNamedSecurityInfoW( | |
+ wn, // Abstract filename | |
+ SE_FILE_OBJECT, // File Object | |
+ sec_info, | |
+ p->pSidOwner, // Ownership information. | |
+ p->pSidGroup, // Group membership. | |
+ p->pDacl, // Discretionary information. | |
+ p->pSacl // For auditing purposes. | |
+ ); | |
+ vim_free(wn); | |
+ } | |
+ else | |
+# endif | |
+ { | |
+ (void)pSetNamedSecurityInfo( | |
+ (LPSTR)fname, // Abstract filename | |
+ SE_FILE_OBJECT, // File Object | |
+ sec_info, | |
+ p->pSidOwner, // Ownership information. | |
+ p->pSidGroup, // Group membership. | |
+ p->pDacl, // Discretionary information. | |
+ p->pSacl // For auditing purposes. | |
+ ); | |
+ } | |
+ } | |
#endif | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment