Blob Blame History Raw
To: vim_dev@googlegroups.com
Subject: Patch 7.3.1267
Fcc: outbox
From: Bram Moolenaar <Bram@moolenaar.net>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
------------

Patch 7.3.1267
Problem:    MS-Windows ACL support doesn't work well.
Solution:   Implement more ACL support. (Ken Takata)
Files:	    src/os_win32.c


*** ../vim-7.3.1266/src/os_win32.c	2013-06-16 16:34:53.000000000 +0200
--- src/os_win32.c	2013-06-29 15:33:52.000000000 +0200
***************
*** 481,500 ****
  # ifndef PROTO
  #  include <aclapi.h>
  # 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,
  	SECURITY_INFORMATION, PSID, PSID, PACL, PACL);
  typedef DWORD (WINAPI *PGNSECINFO) (LPSTR, enum SE_OBJECT_TYPE,
  	SECURITY_INFORMATION, PSID *, PSID *, PACL *, PACL *,
  	PSECURITY_DESCRIPTOR *);
  
  static HANDLE advapi_lib = NULL;	/* Handle for ADVAPI library */
  static PSNSECINFO pSetNamedSecurityInfo;
  static PGNSECINFO pGetNamedSecurityInfo;
  #endif
  
  typedef BOOL (WINAPI *PSETHANDLEINFORMATION)(HANDLE, DWORD, DWORD);
--- 481,514 ----
  # 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) (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,507 ****
--- 516,557 ----
  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,554 ****
  						      "SetNamedSecurityInfoA");
  		pGetNamedSecurityInfo = (PGNSECINFO)GetProcAddress(advapi_lib,
  						      "GetNamedSecurityInfoA");
  		if (pSetNamedSecurityInfo == NULL
! 			|| pGetNamedSecurityInfo == NULL)
  		{
  		    /* 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;
  		}
  	    }
  	}
  #endif
--- 591,617 ----
  						      "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
! # 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,3096 ****
--- 3154,3160 ----
      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,3120 ****
  	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)
  	    {
! 		mch_free_acl((vim_acl_T)p);
! 		p = NULL;
  	    }
  	}
      }
--- 3162,3243 ----
  	p = (struct my_acl *)alloc_clear((unsigned)sizeof(struct my_acl));
  	if (p != NULL)
  	{
! # 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
  	    {
! 		/* 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,3128 ****
--- 3246,3274 ----
  #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,3153 ****
  {
  #ifdef HAVE_ACL
      struct my_acl   *p = (struct my_acl *)acl;
  
      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.
! 		    );
  #endif
  }
  
--- 3279,3339 ----
  {
  #ifdef HAVE_ACL
      struct my_acl   *p = (struct my_acl *)acl;
+     SECURITY_INFORMATION    sec_info = 0;
  
      if (p != NULL && advapi_lib != NULL)
!     {
! # 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
  }
  
*** ../vim-7.3.1266/src/version.c	2013-06-29 15:19:17.000000000 +0200
--- src/version.c	2013-06-29 15:35:23.000000000 +0200
***************
*** 730,731 ****
--- 730,733 ----
  {   /* Add new patch number below this line */
+ /**/
+     1267,
  /**/

-- 
We do not stumble over mountains, but over molehills.
				Confucius

 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///