src/ChangeLog addition:
2006-11-19 Benson Margulies <benson(a)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
}
_______________________________________________
XEmacs-Patches mailing list
XEmacs-Patches(a)xemacs.org
http://calypso.tux.org/cgi-bin/mailman/listinfo/xemacs-patches