[PATCH] Second dose on file_writable includes cygwin

U-SOBIG\benson bim2006 at basistech.com
Sun Nov 19 21:01:57 EST 2006


src/ChangeLog addition:

2006-11-19  Benson Margulies  <benson at dchbk.us>

	* fileio.c: Add code to use full Win32 API to check for write access.
          Win32 has the general design policy that you aren't supposed to ask this question, since
          security checks change depending on asynchronous processes. Nonetheless, there is a way,
          by acting as if we are a server doing interpretive access control.

Index: src/fileio.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/fileio.c,v
retrieving revision 1.66.2.7
diff -u -r1.66.2.7 fileio.c
--- src/fileio.c	2005/01/31 02:55:14	1.66.2.7
+++ src/fileio.c	2006/11/20 01:52:19
@@ -57,7 +57,13 @@
 #define WIN32_FILENAMES
 #ifdef WIN32_NATIVE
 #include "nt.h"
+#include <aclapi.h>
 #endif /* WIN32_NATIVE */
+#ifdef CYGWIN
+#include <w32api/aclapi.h>
+#endif
+
+
 #define IS_DRIVE(x) isalpha (x)
 /* Need to lower-case the drive letter, or else expanded
    filenames will sometimes compare inequal, because
@@ -2267,11 +2273,81 @@
 #endif /* not WIN32_NATIVE */
 }
 
+
+
 /* Return nonzero if file FILENAME exists and can be written.  */
 
 static int
 check_writable (const char *filename)
 {
+#if defined(WIN32_NATIVE) || defined(CYGWIN)
+#ifdef CYGWIN
+    char filename_buffer[PATH_MAX];
+#endif
+	// Since this has to work for a directory, we can't just call 'CreateFile'
+	PSECURITY_DESCRIPTOR pDesc; /* Must be freed with LocalFree */
+	/* these need not be freed, they point into pDesc */
+	PSID psidOwner;
+	PSID psidGroup;
+	PACL pDacl;
+	PACL pSacl;
+	/* end of insides of descriptor */
+	DWORD error;
+	DWORD attributes;
+	HANDLE tokenHandle;
+	GENERIC_MAPPING genericMapping;
+	DWORD accessMask;
+	PRIVILEGE_SET PrivilegeSet;
+    DWORD dwPrivSetSize = sizeof( PRIVILEGE_SET );
+    BOOL fAccessGranted = FALSE;
+	DWORD dwAccessAllowed;
+
+#ifdef CYGWIN
+    cygwin_conv_to_full_win32_path(filename, filename_buffer);
+    filename = filename_buffer;
+#endif
+
+	/* Win32 prototype lacks const. */
+	error = GetNamedSecurityInfo((LPTSTR)filename, SE_FILE_OBJECT, 
+		DACL_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION,
+		&psidOwner, &psidGroup, &pDacl, &pSacl, &pDesc);
+	if(error != ERROR_SUCCESS) { // FAT?
+		attributes = GetFileAttributes(filename);
+		return (attributes & FILE_ATTRIBUTE_DIRECTORY) || (0 == (attributes & FILE_ATTRIBUTE_READONLY));
+	}
+
+	genericMapping.GenericRead = FILE_GENERIC_READ;
+    genericMapping.GenericWrite = FILE_GENERIC_WRITE;
+    genericMapping.GenericExecute = FILE_GENERIC_EXECUTE;
+    genericMapping.GenericAll = FILE_ALL_ACCESS;
+
+	if(!ImpersonateSelf(SecurityDelegation)) {
+		return 0;
+	}
+	if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &tokenHandle)) {
+		return 0;
+	}
+
+	accessMask = GENERIC_WRITE;
+	MapGenericMask(&accessMask, &genericMapping);
+
+	if(!AccessCheck(pDesc, tokenHandle, accessMask, &genericMapping,
+					&PrivilegeSet,       // receives privileges used in check
+					&dwPrivSetSize,      // size of PrivilegeSet buffer
+					&dwAccessAllowed,    // receives mask of allowed access rights
+					&fAccessGranted)) 
+	{
+		DWORD oops = GetLastError();
+		CloseHandle(tokenHandle);
+		RevertToSelf();
+		LocalFree(pDesc);
+		return 0;
+	}
+	CloseHandle(tokenHandle);
+	RevertToSelf();
+	LocalFree(pDesc);
+	return fAccessGranted == TRUE;
+#else
 #ifdef HAVE_EACCESS
   return (eaccess (filename, W_OK) >= 0);
 #else
@@ -2281,6 +2357,7 @@
      Opening with O_WRONLY could work for an ordinary file,
      but would lose for directories.  */
   return (access (filename, W_OK) >= 0);
+#endif
 #endif
 }
 



More information about the XEmacs-Patches mailing list