summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <bram@vim.org>2013-06-29 15:36:26 +0200
committerBram Moolenaar <bram@vim.org>2013-06-29 15:36:26 +0200
commitd50bbce283ed8dcba1142ced20419c21a24b63b1 (patch)
tree00220c08aaadd740502de584ad6df27a22a1b651
parente3c902841ced870a62408b382538220ef4ba9166 (diff)
downloadvim-d50bbce283ed8dcba1142ced20419c21a24b63b1.tar.gz
updated for version 7.3.1267v7.3.1267v7-3-1267
Problem: MS-Windows ACL support doesn't work well. Solution: Implement more ACL support. (Ken Takata)
-rw-r--r--src/os_win32.c248
-rw-r--r--src/version.c2
2 files changed, 219 insertions, 31 deletions
diff --git a/src/os_win32.c b/src/os_win32.c
index 123b892e..9d4ae0b9 100644
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -481,20 +481,34 @@ DWORD g_PlatformId;
# ifndef PROTO
# include <aclapi.h>
# endif
+# 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);
@@ -502,6 +516,42 @@ typedef BOOL (WINAPI *PSETHANDLEINFORMATION)(HANDLE, DWORD, DWORD);
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).
@@ -541,14 +591,27 @@ PlatformId(void)
"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
@@ -3091,6 +3154,7 @@ mch_get_acl(char_u *fname)
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)
@@ -3098,23 +3162,82 @@ mch_get_acl(char_u *fname)
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)
+ {
+ /* 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
{
- mch_free_acl((vim_acl_T)p);
- p = NULL;
+ /* 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;
+ }
}
}
}
@@ -3123,6 +3246,29 @@ mch_get_acl(char_u *fname)
#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.
@@ -3133,21 +3279,61 @@ mch_set_acl(char_u *fname, vim_acl_T acl)
{
#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
}
diff --git a/src/version.c b/src/version.c
index b35ed20a..d554cd60 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1267,
+/**/
1266,
/**/
1265,