summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TSRM/tsrm_win32.c285
-rw-r--r--win32/ioutil.c32
-rw-r--r--win32/ioutil.h7
3 files changed, 165 insertions, 159 deletions
diff --git a/TSRM/tsrm_win32.c b/TSRM/tsrm_win32.c
index 039fef7cc2..43d9f8e572 100644
--- a/TSRM/tsrm_win32.c
+++ b/TSRM/tsrm_win32.c
@@ -209,190 +209,175 @@ TSRM_API int tsrm_win32_access(const char *pathname, int mode)
realpath_cache_bucket * bucket = NULL;
char * real_path = NULL;
+ if(!IS_ABSOLUTE_PATH(pathname, strlen(pathname)+1)) {
+ real_path = (char *)malloc(MAXPATHLEN);
+ if(tsrm_realpath(pathname, real_path) == NULL) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_FILE_NOT_FOUND);
+ return -1;
+ }
+ pathname = real_path;
+ }
+
PHP_WIN32_IOUTIL_INIT_W(pathname)
if (!pathw) {
+ free(real_path);
return -1;
}
- if (mode == 1 /*X_OK*/) {
- DWORD type;
- int ret;
-
- ret = GetBinaryTypeW(pathw, &type) ? 0 : -1;
-
+ /* Either access call failed, or the mode was asking for a specific check.*/
+ int ret = php_win32_ioutil_access_w(pathw, mode);
+ if (0 > ret || X_OK == mode || F_OK == mode) {
PHP_WIN32_IOUTIL_CLEANUP_W()
-
+ free(real_path);
return ret;
- } else {
- if(!IS_ABSOLUTE_PATH(pathname, strlen(pathname)+1)) {
- real_path = (char *)malloc(MAXPATHLEN);
- if(tsrm_realpath(pathname, real_path) == NULL) {
- goto Finished;
- }
- pathname = real_path;
- PHP_WIN32_IOUTIL_REINIT_W(pathname);
- }
-
- if(php_win32_ioutil_access(pathname, mode)) {
- PHP_WIN32_IOUTIL_CLEANUP_W()
- free(real_path);
- return errno;
- }
-
- /* If only existence check is made, return now */
- if (mode == 0) {
- PHP_WIN32_IOUTIL_CLEANUP_W()
- free(real_path);
- return 0;
- }
+ }
/* Only in NTS when impersonate==1 (aka FastCGI) */
- /*
- AccessCheck() requires an impersonation token. We first get a primary
- token and then create a duplicate impersonation token. The
- impersonation token is not actually assigned to the thread, but is
- used in the call to AccessCheck. Thus, this function itself never
- impersonates, but does use the identity of the thread. If the thread
- was impersonating already, this function uses that impersonation context.
- */
- if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &thread_token)) {
- if (GetLastError() == ERROR_NO_TOKEN) {
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &thread_token)) {
- TWG(impersonation_token) = NULL;
- goto Finished;
- }
- }
+ /*
+ AccessCheck() requires an impersonation token. We first get a primary
+ token and then create a duplicate impersonation token. The
+ impersonation token is not actually assigned to the thread, but is
+ used in the call to AccessCheck. Thus, this function itself never
+ impersonates, but does use the identity of the thread. If the thread
+ was impersonating already, this function uses that impersonation context.
+ */
+ if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &thread_token)) {
+ if (GetLastError() == ERROR_NO_TOKEN) {
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &thread_token)) {
+ TWG(impersonation_token) = NULL;
+ goto Finished;
+ }
}
+ }
- /* token_sid will be freed in tsrmwin32_dtor */
- token_sid = tsrm_win32_get_token_sid(thread_token);
- if (!token_sid) {
- if (TWG(impersonation_token_sid)) {
- free(TWG(impersonation_token_sid));
- }
- TWG(impersonation_token_sid) = NULL;
- goto Finished;
+ /* token_sid will be freed in tsrmwin32_dtor */
+ token_sid = tsrm_win32_get_token_sid(thread_token);
+ if (!token_sid) {
+ if (TWG(impersonation_token_sid)) {
+ free(TWG(impersonation_token_sid));
}
+ TWG(impersonation_token_sid) = NULL;
+ goto Finished;
+ }
- /* Different identity, we need a new impersontated token as well */
- if (!TWG(impersonation_token_sid) || !EqualSid(token_sid, TWG(impersonation_token_sid))) {
- if (TWG(impersonation_token_sid)) {
- free(TWG(impersonation_token_sid));
- }
- TWG(impersonation_token_sid) = token_sid;
-
- /* Duplicate the token as impersonated token */
- if (!DuplicateToken(thread_token, SecurityImpersonation, &TWG(impersonation_token))) {
- goto Finished;
- }
- } else {
- /* we already have it, free it then */
- free(token_sid);
+ /* Different identity, we need a new impersontated token as well */
+ if (!TWG(impersonation_token_sid) || !EqualSid(token_sid, TWG(impersonation_token_sid))) {
+ if (TWG(impersonation_token_sid)) {
+ free(TWG(impersonation_token_sid));
}
+ TWG(impersonation_token_sid) = token_sid;
- if (CWDG(realpath_cache_size_limit)) {
- t = time(0);
- bucket = realpath_cache_lookup(pathname, strlen(pathname), t);
- if(bucket == NULL && real_path == NULL) {
- /* We used the pathname directly. Call tsrm_realpath */
- /* so that entry is created in realpath cache */
- real_path = (char *)malloc(MAXPATHLEN);
- if(tsrm_realpath(pathname, real_path) != NULL) {
- pathname = real_path;
- bucket = realpath_cache_lookup(pathname, strlen(pathname), t);
- PHP_WIN32_IOUTIL_REINIT_W(pathname);
- }
- }
- }
+ /* Duplicate the token as impersonated token */
+ if (!DuplicateToken(thread_token, SecurityImpersonation, &TWG(impersonation_token))) {
+ goto Finished;
+ }
+ } else {
+ /* we already have it, free it then */
+ free(token_sid);
+ }
- /* Do a full access check because access() will only check read-only attribute */
- if(mode == 0 || mode > 6) {
- if(bucket != NULL && bucket->is_rvalid) {
- fAccess = bucket->is_readable;
- goto Finished;
- }
- desired_access = FILE_GENERIC_READ;
- } else if(mode <= 2) {
- if(bucket != NULL && bucket->is_wvalid) {
- fAccess = bucket->is_writable;
- goto Finished;
- }
- desired_access = FILE_GENERIC_WRITE;
- } else if(mode <= 4) {
- if(bucket != NULL && bucket->is_rvalid) {
- fAccess = bucket->is_readable;
- goto Finished;
- }
- desired_access = FILE_GENERIC_READ|FILE_FLAG_BACKUP_SEMANTICS;
- } else { // if(mode <= 6)
- if(bucket != NULL && bucket->is_rvalid && bucket->is_wvalid) {
- fAccess = bucket->is_readable & bucket->is_writable;
- goto Finished;
+ if (CWDG(realpath_cache_size_limit)) {
+ t = time(0);
+ bucket = realpath_cache_lookup(pathname, strlen(pathname), t);
+ if(bucket == NULL && real_path == NULL) {
+ /* We used the pathname directly. Call tsrm_realpath */
+ /* so that entry is created in realpath cache */
+ real_path = (char *)malloc(MAXPATHLEN);
+ if(tsrm_realpath(pathname, real_path) != NULL) {
+ pathname = real_path;
+ bucket = realpath_cache_lookup(pathname, strlen(pathname), t);
+ PHP_WIN32_IOUTIL_REINIT_W(pathname);
}
- desired_access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
- }
+ }
+ }
- if(TWG(impersonation_token) == NULL) {
+ /* Do a full access check because access() will only check read-only attribute */
+ if(mode == 0 || mode > 6) {
+ if(bucket != NULL && bucket->is_rvalid) {
+ fAccess = bucket->is_readable;
goto Finished;
}
-
- /* Get size of security buffer. Call is expected to fail */
- if(GetFileSecurityW(pathw, sec_info, NULL, 0, &sec_desc_length)) {
+ desired_access = FILE_GENERIC_READ;
+ } else if(mode <= 2) {
+ if(bucket != NULL && bucket->is_wvalid) {
+ fAccess = bucket->is_writable;
goto Finished;
}
-
- psec_desc = (BYTE *)malloc(sec_desc_length);
- if(psec_desc == NULL ||
- !GetFileSecurityW(pathw, sec_info, (PSECURITY_DESCRIPTOR)psec_desc, sec_desc_length, &sec_desc_length)) {
+ desired_access = FILE_GENERIC_WRITE;
+ } else if(mode <= 4) {
+ if(bucket != NULL && bucket->is_rvalid) {
+ fAccess = bucket->is_readable;
+ goto Finished;
+ }
+ desired_access = FILE_GENERIC_READ|FILE_FLAG_BACKUP_SEMANTICS;
+ } else { // if(mode <= 6)
+ if(bucket != NULL && bucket->is_rvalid && bucket->is_wvalid) {
+ fAccess = bucket->is_readable & bucket->is_writable;
goto Finished;
}
+ desired_access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
+ }
- MapGenericMask(&desired_access, &gen_map);
+ if(TWG(impersonation_token) == NULL) {
+ goto Finished;
+ }
- if(!AccessCheck((PSECURITY_DESCRIPTOR)psec_desc, TWG(impersonation_token), desired_access, &gen_map, &privilege_set, &priv_set_length, &granted_access, &fAccess)) {
- goto Finished_Impersonate;
- }
+ /* Get size of security buffer. Call is expected to fail */
+ if(GetFileSecurityW(pathw, sec_info, NULL, 0, &sec_desc_length)) {
+ goto Finished;
+ }
- /* Keep the result in realpath_cache */
- if(bucket != NULL) {
- if(desired_access == (FILE_GENERIC_READ|FILE_FLAG_BACKUP_SEMANTICS)) {
- bucket->is_rvalid = 1;
- bucket->is_readable = fAccess;
- }
- else if(desired_access == FILE_GENERIC_WRITE) {
- bucket->is_wvalid = 1;
- bucket->is_writable = fAccess;
- } else if (desired_access == (FILE_GENERIC_READ | FILE_GENERIC_WRITE)) {
- bucket->is_rvalid = 1;
- bucket->is_readable = fAccess;
- bucket->is_wvalid = 1;
- bucket->is_writable = fAccess;
- }
+ psec_desc = (BYTE *)malloc(sec_desc_length);
+ if(psec_desc == NULL ||
+ !GetFileSecurityW(pathw, sec_info, (PSECURITY_DESCRIPTOR)psec_desc, sec_desc_length, &sec_desc_length)) {
+ goto Finished;
+ }
+
+ MapGenericMask(&desired_access, &gen_map);
+
+ if(!AccessCheck((PSECURITY_DESCRIPTOR)psec_desc, TWG(impersonation_token), desired_access, &gen_map, &privilege_set, &priv_set_length, &granted_access, &fAccess)) {
+ goto Finished_Impersonate;
+ }
+
+ /* Keep the result in realpath_cache */
+ if(bucket != NULL) {
+ if(desired_access == (FILE_GENERIC_READ|FILE_FLAG_BACKUP_SEMANTICS)) {
+ bucket->is_rvalid = 1;
+ bucket->is_readable = fAccess;
}
+ else if(desired_access == FILE_GENERIC_WRITE) {
+ bucket->is_wvalid = 1;
+ bucket->is_writable = fAccess;
+ } else if (desired_access == (FILE_GENERIC_READ | FILE_GENERIC_WRITE)) {
+ bucket->is_rvalid = 1;
+ bucket->is_readable = fAccess;
+ bucket->is_wvalid = 1;
+ bucket->is_writable = fAccess;
+ }
+ }
Finished_Impersonate:
- if(psec_desc != NULL) {
- free(psec_desc);
- psec_desc = NULL;
- }
+ if(psec_desc != NULL) {
+ free(psec_desc);
+ psec_desc = NULL;
+ }
Finished:
- if(thread_token != NULL) {
- CloseHandle(thread_token);
- }
- if(real_path != NULL) {
- free(real_path);
- real_path = NULL;
- }
+ if(thread_token != NULL) {
+ CloseHandle(thread_token);
+ }
+ if(real_path != NULL) {
+ free(real_path);
+ real_path = NULL;
+ }
- PHP_WIN32_IOUTIL_CLEANUP_W()
- if(fAccess == FALSE) {
- errno = EACCES;
- return errno;
- } else {
- return 0;
- }
+ PHP_WIN32_IOUTIL_CLEANUP_W()
+ if(fAccess == FALSE) {
+ errno = EACCES;
+ return errno;
+ } else {
+ return 0;
}
}/*}}}*/
diff --git a/win32/ioutil.c b/win32/ioutil.c
index 7f1f758456..4c4e60d5d1 100644
--- a/win32/ioutil.c
+++ b/win32/ioutil.c
@@ -655,13 +655,33 @@ BOOL php_win32_ioutil_init(void)
return TRUE;
}/*}}}*/
-/* an extended version could be implemented, for now direct functions can be used. */
-#if 0
PW32IO int php_win32_ioutil_access_w(const wchar_t *path, mode_t mode)
-{
- return _waccess(path, mode);
-}
-#endif
+{/*{{{*/
+ DWORD attr, err;
+
+ if ((mode & X_OK) == X_OK) {
+ DWORD type;
+ return GetBinaryTypeW(path, &type) ? 0 : -1;
+ }
+
+ attr = GetFileAttributesW(path);
+ if (attr == INVALID_FILE_ATTRIBUTES) {
+ err = GetLastError();
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return -1;
+ }
+
+ if (F_OK == mode) {
+ return 0;
+ }
+
+ if ((mode &W_OK) == W_OK && (attr & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_ACCESS_DENIED);
+ return -1;
+ }
+
+ return 0;
+}/*}}}*/
#if 0
PW32IO HANDLE php_win32_ioutil_findfirstfile_w(char *path, WIN32_FIND_DATA *data)
diff --git a/win32/ioutil.h b/win32/ioutil.h
index 5d06fd1940..5e661fc096 100644
--- a/win32/ioutil.h
+++ b/win32/ioutil.h
@@ -242,6 +242,7 @@ PW32IO int php_win32_ioutil_chdir_w(const wchar_t *path);
PW32IO int php_win32_ioutil_rename_w(const wchar_t *oldname, const wchar_t *newname);
PW32IO wchar_t *php_win32_ioutil_getcwd_w(wchar_t *buf, size_t len);
PW32IO int php_win32_ioutil_unlink_w(const wchar_t *path);
+PW32IO int php_win32_ioutil_access_w(const wchar_t *path, mode_t mode);
#if 0
PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode);
@@ -264,14 +265,14 @@ __forceinline static int php_win32_ioutil_access(const char *path, mode_t mode)
PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1, 1)
- ret = _waccess(pathw, mode);
+ ret = php_win32_ioutil_access_w(pathw, mode);
if (0 > ret) {
- _get_errno(&err);
+ err = GetLastError();
}
PHP_WIN32_IOUTIL_CLEANUP_W()
if (0 > ret) {
- _set_errno(err);
+ SET_ERRNO_FROM_WIN32_CODE(err);
}
return ret;