mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
updated for version 7.3.1267
Problem: MS-Windows ACL support doesn't work well. Solution: Implement more ACL support. (Ken Takata)
This commit is contained in:
248
src/os_win32.c
248
src/os_win32.c
@@ -481,20 +481,34 @@ DWORD g_PlatformId;
|
|||||||
# ifndef PROTO
|
# ifndef PROTO
|
||||||
# include <aclapi.h>
|
# include <aclapi.h>
|
||||||
# endif
|
# 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
|
* These are needed to dynamically load the ADVAPI DLL, which is not
|
||||||
* implemented under Windows 95 (and causes VIM to crash)
|
* 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);
|
SECURITY_INFORMATION, PSID, PSID, PACL, PACL);
|
||||||
typedef DWORD (WINAPI *PGNSECINFO) (LPSTR, enum SE_OBJECT_TYPE,
|
typedef DWORD (WINAPI *PGNSECINFO) (LPSTR, enum SE_OBJECT_TYPE,
|
||||||
SECURITY_INFORMATION, PSID *, PSID *, PACL *, PACL *,
|
SECURITY_INFORMATION, PSID *, PSID *, PACL *, PACL *,
|
||||||
PSECURITY_DESCRIPTOR *);
|
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 HANDLE advapi_lib = NULL; /* Handle for ADVAPI library */
|
||||||
static PSNSECINFO pSetNamedSecurityInfo;
|
static PSNSECINFO pSetNamedSecurityInfo;
|
||||||
static PGNSECINFO pGetNamedSecurityInfo;
|
static PGNSECINFO pGetNamedSecurityInfo;
|
||||||
|
# ifdef FEAT_MBYTE
|
||||||
|
static PSNSECINFOW pSetNamedSecurityInfoW;
|
||||||
|
static PGNSECINFOW pGetNamedSecurityInfoW;
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef BOOL (WINAPI *PSETHANDLEINFORMATION)(HANDLE, DWORD, DWORD);
|
typedef BOOL (WINAPI *PSETHANDLEINFORMATION)(HANDLE, DWORD, DWORD);
|
||||||
@@ -502,6 +516,42 @@ typedef BOOL (WINAPI *PSETHANDLEINFORMATION)(HANDLE, DWORD, DWORD);
|
|||||||
static BOOL allowPiping = FALSE;
|
static BOOL allowPiping = FALSE;
|
||||||
static PSETHANDLEINFORMATION pSetHandleInformation;
|
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
|
* Set g_PlatformId to VER_PLATFORM_WIN32_NT (NT) or
|
||||||
* VER_PLATFORM_WIN32_WINDOWS (Win95).
|
* VER_PLATFORM_WIN32_WINDOWS (Win95).
|
||||||
@@ -541,14 +591,27 @@ PlatformId(void)
|
|||||||
"SetNamedSecurityInfoA");
|
"SetNamedSecurityInfoA");
|
||||||
pGetNamedSecurityInfo = (PGNSECINFO)GetProcAddress(advapi_lib,
|
pGetNamedSecurityInfo = (PGNSECINFO)GetProcAddress(advapi_lib,
|
||||||
"GetNamedSecurityInfoA");
|
"GetNamedSecurityInfoA");
|
||||||
|
# ifdef FEAT_MBYTE
|
||||||
|
pSetNamedSecurityInfoW = (PSNSECINFOW)GetProcAddress(advapi_lib,
|
||||||
|
"SetNamedSecurityInfoW");
|
||||||
|
pGetNamedSecurityInfoW = (PGNSECINFOW)GetProcAddress(advapi_lib,
|
||||||
|
"GetNamedSecurityInfoW");
|
||||||
|
# endif
|
||||||
if (pSetNamedSecurityInfo == NULL
|
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
|
/* If we can't get the function addresses, set advapi_lib
|
||||||
* to NULL so that we don't use them. */
|
* to NULL so that we don't use them. */
|
||||||
FreeLibrary(advapi_lib);
|
FreeLibrary(advapi_lib);
|
||||||
advapi_lib = NULL;
|
advapi_lib = NULL;
|
||||||
}
|
}
|
||||||
|
/* Enable privilege for getting or setting SACLs. */
|
||||||
|
win32_enable_privilege(SE_SECURITY_NAME, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -3091,6 +3154,7 @@ mch_get_acl(char_u *fname)
|
|||||||
return (vim_acl_T)NULL;
|
return (vim_acl_T)NULL;
|
||||||
#else
|
#else
|
||||||
struct my_acl *p = NULL;
|
struct my_acl *p = NULL;
|
||||||
|
DWORD err;
|
||||||
|
|
||||||
/* This only works on Windows NT and 2000. */
|
/* This only works on Windows NT and 2000. */
|
||||||
if (g_PlatformId == VER_PLATFORM_WIN32_NT && advapi_lib != NULL)
|
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));
|
p = (struct my_acl *)alloc_clear((unsigned)sizeof(struct my_acl));
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
{
|
{
|
||||||
if (pGetNamedSecurityInfo(
|
# ifdef FEAT_MBYTE
|
||||||
(LPTSTR)fname, // Abstract filename
|
WCHAR *wn = NULL;
|
||||||
SE_FILE_OBJECT, // File Object
|
|
||||||
// Retrieve the entire security descriptor.
|
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
|
||||||
OWNER_SECURITY_INFORMATION |
|
wn = enc_to_utf16(fname, NULL);
|
||||||
GROUP_SECURITY_INFORMATION |
|
if (wn != NULL)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
mch_free_acl((vim_acl_T)p);
|
/* Try to retrieve the entire security descriptor. */
|
||||||
p = NULL;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3123,6 +3246,29 @@ mch_get_acl(char_u *fname)
|
|||||||
#endif
|
#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).
|
* Set the ACL of file "fname" to "acl" (unless it's NULL).
|
||||||
* Errors are ignored.
|
* Errors are ignored.
|
||||||
@@ -3133,21 +3279,61 @@ mch_set_acl(char_u *fname, vim_acl_T acl)
|
|||||||
{
|
{
|
||||||
#ifdef HAVE_ACL
|
#ifdef HAVE_ACL
|
||||||
struct my_acl *p = (struct my_acl *)acl;
|
struct my_acl *p = (struct my_acl *)acl;
|
||||||
|
SECURITY_INFORMATION sec_info = 0;
|
||||||
|
|
||||||
if (p != NULL && advapi_lib != NULL)
|
if (p != NULL && advapi_lib != NULL)
|
||||||
(void)pSetNamedSecurityInfo(
|
{
|
||||||
(LPTSTR)fname, // Abstract filename
|
# ifdef FEAT_MBYTE
|
||||||
SE_FILE_OBJECT, // File Object
|
WCHAR *wn = NULL;
|
||||||
// Retrieve the entire security descriptor.
|
# endif
|
||||||
OWNER_SECURITY_INFORMATION |
|
|
||||||
GROUP_SECURITY_INFORMATION |
|
/* Set security flags */
|
||||||
DACL_SECURITY_INFORMATION |
|
if (p->pSidOwner)
|
||||||
SACL_SECURITY_INFORMATION,
|
sec_info |= OWNER_SECURITY_INFORMATION;
|
||||||
p->pSidOwner, // Ownership information.
|
if (p->pSidGroup)
|
||||||
p->pSidGroup, // Group membership.
|
sec_info |= GROUP_SECURITY_INFORMATION;
|
||||||
p->pDacl, // Discretionary information.
|
if (p->pDacl)
|
||||||
p->pSacl // For auditing purposes.
|
{
|
||||||
);
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -728,6 +728,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1267,
|
||||||
/**/
|
/**/
|
||||||
1266,
|
1266,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user