summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorapnadkarni <apnmbx-wits@yahoo.com>2023-03-07 12:28:40 (GMT)
committerapnadkarni <apnmbx-wits@yahoo.com>2023-03-07 12:28:40 (GMT)
commit4df874dd7fcd7292ca7110d27e0d26ad8b551360 (patch)
tree65b655fcfbf59abb25b99f16994b73ed887be8aa
parent01d6e026664f6e05a1cfbfc38cc14fdf6119b95d (diff)
parent1f6cec5ff3943450001a29bea3371dea9f23db7f (diff)
downloadtcl-4df874dd7fcd7292ca7110d27e0d26ad8b551360.zip
tcl-4df874dd7fcd7292ca7110d27e0d26ad8b551360.tar.gz
tcl-4df874dd7fcd7292ca7110d27e0d26ad8b551360.tar.bz2
Merge 8.6 - testchmod fixes
-rw-r--r--tests/fCmd.test18
-rw-r--r--tests/tcltest.test2
-rw-r--r--tests/winFCmd.test114
-rw-r--r--win/tclWinTest.c317
4 files changed, 241 insertions, 210 deletions
diff --git a/tests/fCmd.test b/tests/fCmd.test
index 246d65b..4c8e55c 100644
--- a/tests/fCmd.test
+++ b/tests/fCmd.test
@@ -1065,6 +1065,7 @@ test fCmd-10.3.1 {file copy: comprehensive: dir to new name} -setup {
file mkdir [file join td1 tdx]
file mkdir [file join td2 tdy]
testchmod 0o555 td2
+ testchmod 0o555 td2/tdy; # Above line removes inherited perms. So restore.
file copy td1 td3
file copy td2 td4
list [lsort [glob td*]] [glob -directory td3 t*] \
@@ -1086,10 +1087,19 @@ test fCmd-10.4 {file copy: comprehensive: file to existing file} -setup {
createfile tfd2
createfile tfd3
createfile tfd4
- testchmod 0o444 tfs3
- testchmod 0o444 tfs4
- testchmod 0o444 tfd2
- testchmod 0o444 tfd4
+ if {$::tcl_platform(platform) eq "windows"} {
+ # On Windows testchmode will attach an ACL which file copy cannot handle
+ # so use good old attributes which file copy does understand
+ file attribute tfs3 -readonly 1
+ file attribute tfs4 -readonly 1
+ file attribute tfd2 -readonly 1
+ file attribute tfd4 -readonly 1
+ } else {
+ testchmod 0o444 tfs3
+ testchmod 0o444 tfs4
+ testchmod 0o444 tfd2
+ testchmod 0o444 tfd4
+ }
set msg [list [catch {file copy tf1 tf2} msg] $msg]
file copy -force tfs1 tfd1
file copy -force tfs2 tfd2
diff --git a/tests/tcltest.test b/tests/tcltest.test
index 49f31d5..29d40e2 100644
--- a/tests/tcltest.test
+++ b/tests/tcltest.test
@@ -555,7 +555,7 @@ switch -- $::tcl_platform(platform) {
default {
# note in FAT/NTFS we won't be able to protect directory with read-only attribute...
catch {file attributes $notWriteableDir -readonly 1}
- catch {testchmod 0 $notWriteableDir}
+ catch {testchmod 0o444 $notWriteableDir}
}
}
test tcltest-8.3 {tcltest a.tcl -tmpdir notReadableDir} {
diff --git a/tests/winFCmd.test b/tests/winFCmd.test
index 43c7ced..5ebce10 100644
--- a/tests/winFCmd.test
+++ b/tests/winFCmd.test
@@ -45,15 +45,20 @@ proc contents {file} {
set r
}
+proc cleanupRecurse {args} {
+ # Assumes no loops via links!
+ # Need to change permissions BEFORE deletion
+ testchmod 0o777 {*}$args
+ foreach victim $args {
+ if {[file isdirectory $victim]} {
+ cleanupRecurse {*}[glob -nocomplain -directory $victim td* tf* Test*]
+ }
+ file delete -force $victim
+ }
+}
proc cleanup {args} {
- foreach p ". $args" {
- set x ""
- catch {
- set x [glob -directory $p tf* td*]
- }
- if {$x != ""} {
- catch {file delete -force -- {*}$x}
- }
+ foreach p [list [pwd] {*}$args] {
+ cleanupRecurse {*}[glob -nocomplain -directory $p tf* td*]
}
}
@@ -379,12 +384,12 @@ test winFCmd-1.38 {TclpRenameFile: check rename of conflicting inodes} -setup {
cleanup
} -constraints {win winNonZeroInodes knownMsvcBug notInCIenv} -body {
file mkdir td1
- foreach {a b} [MakeFiles td1] break
+ lassign [MakeFiles td1] a b
file rename -force $a $b
file exists $a
} -cleanup {
cleanup
-} -result {0}
+} -result 0
test winFCmd-2.1 {TclpCopyFile: errno: EACCES} -setup {
@@ -450,11 +455,11 @@ test winFCmd-2.12 {TclpCopyFile: CopyFile succeeds} -setup {
cleanup
} -constraints {win testfile} -body {
createfile tf1 tf1
- testchmod 0 tf1
+ file attribute tf1 -readonly 1
testfile cp tf1 tf2
list [contents tf2] [file writable tf2]
} -cleanup {
- catch {testchmod 0o666 tf1}
+ testchmod 0o660 tf1
cleanup
} -result {tf1 0}
test winFCmd-2.13 {TclpCopyFile: CopyFile fails} -setup {
@@ -496,11 +501,10 @@ test winFCmd-2.17 {TclpCopyFile: dst is readonly} -setup {
} -constraints {win testfile testchmod} -body {
createfile tf1 tf1
createfile tf2 tf2
- testchmod 0 tf2
+ file attribute tf2 -readonly 1
testfile cp tf1 tf2
list [file writable tf2] [contents tf2]
} -cleanup {
- catch {testchmod 0o666 tf2}
cleanup
} -result {1 tf1}
@@ -578,7 +582,6 @@ test winFCmd-3.11 {TclpDeleteFile: still can't remove path} -setup {
testfile rm tf1
} -cleanup {
close $fd
- catch {testchmod 0o666 tf1}
cleanup
} -returnCodes error -result EACCES
@@ -617,15 +620,18 @@ test winFCmd-5.1 {TclpCopyDirectory: calls TraverseWinTree} -setup {
test winFCmd-6.1 {TclpRemoveDirectory: errno: EACCES} -setup {
cleanup
-} -constraints {win testfile testchmod knownMsvcBug notInCIenv} -body {
- file mkdir td1
- testchmod 0 td1
- testfile rmdir td1
- file exists td1
+} -constraints {win testfile testchmod notInCIenv} -body {
+ # Parent's FILE_DELETE_CHILD setting permits deletion of subdir
+ # even when subdir DELETE mask is clear. So we need an intermediate
+ # parent td0 with FILE_DELETE_CHILD turned off while allowing R/W.
+ file mkdir td0/td1
+ testchmod 0o777 td0
+ testchmod 0 td0/td1
+ testfile rmdir td0/td1
+ file exists td0/td1
} -returnCodes error -cleanup {
- catch {testchmod 0o666 td1}
cleanup
-} -result {td1 EACCES}
+} -result {td0/td1 EACCES}
# This next test has a very hokey way of matching...
test winFCmd-6.2 {TclpRemoveDirectory: errno: EEXIST} -setup {
cleanup
@@ -633,7 +639,7 @@ test winFCmd-6.2 {TclpRemoveDirectory: errno: EEXIST} -setup {
file mkdir td1/td2
list [catch {testfile rmdir td1} msg] [file tail $msg]
} -result {1 {td1 EEXIST}}
-test winFCmd-6.3 {TclpRemoveDirectory: errno: EACCES} {win emptyTest} {
+test winFCmd-6.3 {TclpRemoveDirectory: errno: EACCES} {win emptyTest trashSystem} {
# can't test this w/o removing everything on your hard disk first!
# testfile rmdir /
} {}
@@ -669,17 +675,7 @@ test winFCmd-6.8 {TclpRemoveDirectory: RemoveDirectory fails} -setup {
createfile tf1
list [catch {testfile rmdir tf1} msg] [file tail $msg]
} -result {1 {tf1 ENOTDIR}}
-test winFCmd-6.9 {TclpRemoveDirectory: errno == EACCES} -setup {
- cleanup
-} -constraints {win testfile testchmod knownMsvcBug notInCIenv} -body {
- file mkdir td1
- testchmod 0 td1
- testfile rmdir td1
- file exists td1
-} -returnCodes error -cleanup {
- catch {testchmod 0o666 td1}
- cleanup
-} -result {td1 EACCES}
+# winFCmd-6.9 removed - was exact dup of winFCmd-6.1
test winFCmd-6.11 {TclpRemoveDirectory: attr == -1} -setup {
cleanup
} -constraints {win testfile notInCIenv} -body {
@@ -689,15 +685,19 @@ test winFCmd-6.11 {TclpRemoveDirectory: attr == -1} -setup {
} -returnCodes error -match regexp -result {^/ E(ACCES|EXIST)$}
test winFCmd-6.13 {TclpRemoveDirectory: write-protected} -setup {
cleanup
-} -constraints {win testfile testchmod knownMsvcBug notInCIenv} -body {
- file mkdir td1
- testchmod 0 td1
- testfile rmdir td1
- file exists td1
+} -constraints {win testfile testchmod notInCIenv} -body {
+ # Parent's FILE_DELETE_CHILD setting permits deletion of subdir
+ # even when subdir DELETE mask is clear. So we need an intermediate
+ # parent td0 with FILE_DELETE_CHILD turned off while allowing R/W.
+ file mkdir td0/td1
+ testchmod 0o770 td0
+ testchmod 0o444 td0/td1
+ testfile rmdir td0/td1
+ file exists td0/td1
} -cleanup {
- catch {testchmod 0o666 td1}
+ testchmod 0o770 td0/td1
cleanup
-} -returnCodes error -result {td1 EACCES}
+} -returnCodes error -result {td0/td1 EACCES}
# This next test has a very hokey way of matching...
test winFCmd-6.15 {TclpRemoveDirectory: !recursive} -setup {
cleanup
@@ -791,11 +791,12 @@ test winFCmd-7.11 {TraverseWinTree: call TraversalCopy: DOTREE_PRED} -setup {
} -constraints {win testfile testchmod} -body {
file mkdir td1
createfile td1/tf1 tf1
- testchmod 0 td1
+ testchmod 0o770 td1/tf1; # Else tf2 will have no ACL after td1 testchmod
+ testchmod 0o400 td1
testfile cpdir td1 td2
list [file exists td2] [file writable td2]
} -cleanup {
- catch {testchmod 0o666 td1}
+ testchmod 0o660 td1
cleanup
} -result {1 1}
test winFCmd-7.12 {TraverseWinTree: call TraversalDelete: DOTREE_PRED} -setup {
@@ -862,11 +863,12 @@ test winFCmd-7.19 {TraverseWinTree: call TraversalCopy: DOTREE_POSTD} -setup {
} -constraints {win testfile testchmod} -body {
file mkdir td1
createfile td1/tf1 tf1
- testchmod 0 td1
+ testchmod 0o770 td1/tf1; # Else tf2 will have no ACL after td1 testchmod
+ testchmod 0o400 td1
testfile cpdir td1 td2
list [file exists td2] [file writable td2]
} -cleanup {
- catch {testchmod 0o666 td1}
+ testchmod 0o660 td1
cleanup
} -result {1 1}
test winFCmd-7.20 {TraverseWinTree: call TraversalDelete: DOTREE_POSTD} -setup {
@@ -893,11 +895,12 @@ test winFCmd-8.2 {TraversalCopy: DOTREE_PRED} -setup {
cleanup
} -constraints {win testfile testchmod} -body {
file mkdir td1/td2
- testchmod 0 td1
+ testchmod 0o770 td1/td2; # Else td2 will have no ACL after td1 testchmod
+ testchmod 0o400 td1
testfile cpdir td1 td2
list [file writable td1] [file writable td1/td2]
} -cleanup {
- catch {testchmod 0o666 td1}
+ testchmod 0o660 td1
cleanup
} -result {0 1}
test winFCmd-8.3 {TraversalCopy: DOTREE_POSTD} -setup {
@@ -918,15 +921,19 @@ test winFCmd-9.1 {TraversalDelete: DOTREE_F} -setup {
} -result {}
test winFCmd-9.3 {TraversalDelete: DOTREE_PRED} -setup {
cleanup
-} -constraints {win testfile testchmod knownMsvcBug notInCIenv} -body {
- file mkdir td1/td2
- testchmod 0 td1
- testfile rmdir -force td1
+} -constraints {win testfile testchmod notInCIenv} -body {
+ # Parent's FILE_DELETE_CHILD setting permits deletion of subdir
+ # even when subdir DELETE mask is clear. So we need an intermediate
+ # parent td0 with FILE_DELETE_CHILD turned off while allowing R/W.
+ file mkdir td0/td1/td2
+ testchmod 0o770 td0
+ testchmod 0o400 td0/td1
+ testfile rmdir -force td0/td1
file exists td1
} -cleanup {
- catch {testchmod 0o666 td1}
+ testchmod 0o770 td0/td1
cleanup
-} -returnCodes error -result {td1 EACCES}
+} -returnCodes error -result {td0/td1 EACCES}
test winFCmd-9.4 {TraversalDelete: DOTREE_POSTD} -setup {
cleanup
} -constraints {win testfile} -body {
@@ -1417,7 +1424,6 @@ test winFCmd-19.9 {Windows devices path names} -constraints win -body {
# }
#}
-# cleanup
cleanup
::tcltest::cleanupTests
return
diff --git a/win/tclWinTest.c b/win/tclWinTest.c
index c910bc5..f6eb2b1 100644
--- a/win/tclWinTest.c
+++ b/win/tclWinTest.c
@@ -22,9 +22,8 @@
/*
* For TestplatformChmod on Windows
*/
-#ifdef _WIN32
#include <aclapi.h>
-#endif
+#include <sddl.h>
/*
* MinGW 3.4.2 does not define this.
@@ -414,176 +413,190 @@ TestExceptionCmd(
return TCL_OK;
}
+/*
+ * This "chmod" works sufficiently for test script purposes. Do not expect
+ * it to be exact emulation of Unix chmod (not sure if that's even possible)
+ */
static int
TestplatformChmod(
const char *nativePath,
int pmode)
{
- static const SECURITY_INFORMATION infoBits = OWNER_SECURITY_INFORMATION
- | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
- /* don't reset change permissions mask (WRITE_DAC, allow test-cases restore it to cleanup) */
- static const DWORD readOnlyMask = FILE_DELETE_CHILD | FILE_ADD_FILE
- | FILE_ADD_SUBDIRECTORY | FILE_WRITE_EA | FILE_APPEND_DATA
- | FILE_WRITE_DATA
- | DELETE;
-
- /*
- * References to security functions (only available on NT and later).
+ /*
+ * Note FILE_DELETE_CHILD missing from dirWriteMask because we do
+ * not want overriding of child's delete setting when testing
*/
-
- const BOOL set_readOnly = !(pmode & 0222);
- BOOL acl_readOnly_found = FALSE, curAclPresent, curAclDefaulted;
- SID_IDENTIFIER_AUTHORITY userSidAuthority = {
- SECURITY_WORLD_SID_AUTHORITY
- };
- BYTE *secDesc = 0;
- DWORD secDescLen, attr, newAclSize;
- ACL_SIZE_INFORMATION ACLSize;
- PACL curAcl, newAcl = 0;
- WORD j;
- SID *userSid = 0;
- char *userDomain = 0;
+ static const DWORD dirWriteMask =
+ FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA |
+ FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | STANDARD_RIGHTS_WRITE | DELETE |
+ SYNCHRONIZE;
+ static const DWORD dirReadMask =
+ FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_LIST_DIRECTORY |
+ STANDARD_RIGHTS_READ | SYNCHRONIZE;
+ /* Note - default user privileges allow ignoring TRAVERSE setting */
+ static const DWORD dirExecuteMask =
+ FILE_TRAVERSE | STANDARD_RIGHTS_READ | SYNCHRONIZE;
+
+ static const DWORD fileWriteMask =
+ FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_WRITE_DATA |
+ FILE_APPEND_DATA | STANDARD_RIGHTS_WRITE | DELETE | SYNCHRONIZE;
+ static const DWORD fileReadMask =
+ FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_READ_DATA |
+ STANDARD_RIGHTS_READ | SYNCHRONIZE;
+ static const DWORD fileExecuteMask =
+ FILE_EXECUTE | STANDARD_RIGHTS_READ | SYNCHRONIZE;
+
+ DWORD attr, newAclSize;
+ PACL newAcl = NULL;
int res = 0;
-
- /*
- * Process the chmod request.
- */
+ SID_IDENTIFIER_AUTHORITY worldAuthority = SECURITY_WORLD_SID_AUTHORITY;
+
+ HANDLE hToken = NULL;
+ int i;
+ int nSids = 0;
+ struct {
+ PSID pSid;
+ DWORD mask;
+ DWORD sidLen;
+ } aceEntry[3];
+ DWORD dw;
+ int isDir;
+ TOKEN_USER *pTokenUser = NULL;
+
+ res = -1; /* Assume failure */
attr = GetFileAttributesA(nativePath);
-
- /*
- * nativePath not found
- */
-
if (attr == 0xFFFFFFFF) {
- res = -1;
- goto done;
+ goto done; /* Not found */
}
- /*
- * If nativePath is not a directory, there is no special handling.
- */
+ isDir = (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
- if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
goto done;
}
-
- /*
- * Set the result to error, if the ACL change is successful it will be
- * reset to 0.
- */
-
- res = -1;
-
- /*
- * Read the security descriptor for the directory. Note the first call
- * obtains the size of the security descriptor.
- */
-
- if (!GetFileSecurityA(nativePath, infoBits, NULL, 0, &secDescLen)) {
- DWORD secDescLen2 = 0;
-
- if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- goto done;
- }
-
- secDesc = (BYTE *)ckalloc(secDescLen);
- if (!GetFileSecurityA(nativePath, infoBits,
- (PSECURITY_DESCRIPTOR) secDesc, secDescLen, &secDescLen2)
- || (secDescLen < secDescLen2)) {
- goto done;
- }
- }
-
- /*
- * Get the World SID.
- */
-
- userSid = (SID *)ckalloc(GetSidLengthRequired((UCHAR) 1));
- InitializeSid(userSid, &userSidAuthority, (BYTE) 1);
- *(GetSidSubAuthority(userSid, 0)) = SECURITY_WORLD_RID;
-
- /*
- * If curAclPresent == false then curAcl and curAclDefaulted not valid.
- */
-
- if (!GetSecurityDescriptorDacl((PSECURITY_DESCRIPTOR) secDesc,
- &curAclPresent, &curAcl, &curAclDefaulted)) {
+
+ /* Get process SID */
+ if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dw) &&
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
goto done;
}
- if (!curAclPresent || !curAcl) {
- ACLSize.AclBytesInUse = 0;
- ACLSize.AceCount = 0;
- } else if (!GetAclInformation(curAcl, &ACLSize, sizeof(ACLSize),
- AclSizeInformation)) {
+ pTokenUser = ckalloc(dw);
+ if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dw, &dw)) {
goto done;
}
-
- /*
- * Allocate memory for the new ACL.
- */
-
- newAclSize = ACLSize.AclBytesInUse + sizeof(ACCESS_DENIED_ACE)
- + GetLengthSid(userSid) - sizeof(DWORD);
- newAcl = (PACL) ckalloc(newAclSize);
-
- /*
- * Initialize the new ACL.
- */
-
- if (!InitializeAcl(newAcl, newAclSize, ACL_REVISION)) {
+ aceEntry[nSids].sidLen = GetLengthSid(pTokenUser->User.Sid);
+ aceEntry[nSids].pSid = ckalloc(aceEntry[nSids].sidLen);
+ if (!CopySid(aceEntry[nSids].sidLen,
+ aceEntry[nSids].pSid,
+ pTokenUser->User.Sid)) {
+ ckfree(aceEntry[nSids].pSid); /* Since we have not ++'ed nSids */
goto done;
}
-
- /*
- * Add denied to make readonly, this will be known as a "read-only tag".
+ /*
+ * Always include DACL modify rights so we don't get locked out
*/
-
- if (set_readOnly && !AddAccessDeniedAce(newAcl, ACL_REVISION,
- readOnlyMask, userSid)) {
- goto done;
+ aceEntry[nSids].mask = READ_CONTROL | WRITE_DAC | WRITE_OWNER | SYNCHRONIZE |
+ FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
+ if (pmode & 0700) {
+ /* Owner permissions. Assumes current process is owner */
+ if (pmode & 0400) {
+ aceEntry[nSids].mask |= isDir ? dirReadMask : fileReadMask;
+ }
+ if (pmode & 0200) {
+ aceEntry[nSids].mask |= isDir ? dirWriteMask : fileWriteMask;
+ }
+ if (pmode & 0100) {
+ aceEntry[nSids].mask |= isDir ? dirExecuteMask : fileExecuteMask;
+ }
}
+ ++nSids;
+
+ if (pmode & 0070) {
+ /* Group permissions. */
- acl_readOnly_found = FALSE;
- for (j = 0; j < ACLSize.AceCount; j++) {
- LPVOID pACE2;
- ACE_HEADER *phACE2;
+ TOKEN_PRIMARY_GROUP *pTokenGroup;
- if (!GetAce(curAcl, j, &pACE2)) {
+ /* Get primary group SID */
+ if (!GetTokenInformation(
+ hToken, TokenPrimaryGroup, NULL, 0, &dw) &&
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
goto done;
}
+ pTokenGroup = ckalloc(dw);
+ if (!GetTokenInformation(hToken, TokenPrimaryGroup, pTokenGroup, dw, &dw)) {
+ ckfree(pTokenGroup);
+ goto done;
+ }
+ aceEntry[nSids].sidLen = GetLengthSid(pTokenGroup->PrimaryGroup);
+ aceEntry[nSids].pSid = ckalloc(aceEntry[nSids].sidLen);
+ if (!CopySid(aceEntry[nSids].sidLen, aceEntry[nSids].pSid, pTokenGroup->PrimaryGroup)) {
+ ckfree(pTokenGroup);
+ ckfree(aceEntry[nSids].pSid); /* Since we have not ++'ed nSids */
+ goto done;
+ }
+ ckfree(pTokenGroup);
- phACE2 = (ACE_HEADER *) pACE2;
+ /* Generate mask for group ACL */
- /*
- * Do NOT propagate inherited ACEs.
- */
-
- if (phACE2->AceFlags & INHERITED_ACE) {
- continue;
+ aceEntry[nSids].mask = 0;
+ if (pmode & 0040) {
+ aceEntry[nSids].mask |= isDir ? dirReadMask : fileReadMask;
+ }
+ if (pmode & 0020) {
+ aceEntry[nSids].mask |= isDir ? dirWriteMask : fileWriteMask;
+ }
+ if (pmode & 0010) {
+ aceEntry[nSids].mask |= isDir ? dirExecuteMask : fileExecuteMask;
}
+ ++nSids;
+ }
- /*
- * Skip the "read-only tag" restriction (either added above, or it is
- * being removed).
- */
+ if (pmode & 0007) {
+ /* World permissions */
+ PSID pWorldSid;
+ if (!ConvertStringSidToSidA("S-1-1-0", &pWorldSid)) {
+ goto done;
+ }
+ aceEntry[nSids].sidLen = GetLengthSid(pWorldSid);
+ aceEntry[nSids].pSid = ckalloc(aceEntry[nSids].sidLen);
+ if (!CopySid(aceEntry[nSids].sidLen, aceEntry[nSids].pSid, pWorldSid)) {
+ LocalFree(pWorldSid);
+ ckfree(aceEntry[nSids].pSid); /* Since we have not ++'ed nSids */
+ goto done;
+ }
+ LocalFree(pWorldSid);
- if (phACE2->AceType == ACCESS_DENIED_ACE_TYPE) {
- ACCESS_DENIED_ACE *pACEd = (ACCESS_DENIED_ACE *) phACE2;
+ /* Generate mask for world ACL */
- if (pACEd->Mask == readOnlyMask
- && EqualSid(userSid, (PSID) &pACEd->SidStart)) {
- acl_readOnly_found = TRUE;
- continue;
- }
+ aceEntry[nSids].mask = 0;
+ if (pmode & 0004) {
+ aceEntry[nSids].mask |= isDir ? dirReadMask : fileReadMask;
}
+ if (pmode & 0002) {
+ aceEntry[nSids].mask |= isDir ? dirWriteMask : fileWriteMask;
+ }
+ if (pmode & 0001) {
+ aceEntry[nSids].mask |= isDir ? dirExecuteMask : fileExecuteMask;
+ }
+ ++nSids;
+ }
- /*
- * Copy the current ACE from the old to the new ACL.
- */
+ /* Allocate memory and initialize the new ACL. */
- if (!AddAce(newAcl, ACL_REVISION, MAXDWORD, (PACL *) pACE2,
- ((PACE_HEADER) pACE2)->AceSize)) {
+ newAclSize = sizeof(ACL);
+ /* Add in size required for each ACE entry in the ACL */
+ for (i = 0; i < nSids; ++i) {
+ newAclSize +=
+ offsetof(ACCESS_ALLOWED_ACE, SidStart) + aceEntry[i].sidLen;
+ }
+ newAcl = ckalloc(newAclSize);
+ if (!InitializeAcl(newAcl, newAclSize, ACL_REVISION)) {
+ goto done;
+ }
+
+ for (i = 0; i < nSids; ++i) {
+ if (!AddAccessAllowedAce(newAcl, ACL_REVISION, aceEntry[i].mask, aceEntry[i].pSid)) {
goto done;
}
}
@@ -593,36 +606,38 @@ TestplatformChmod(
* to remove inherited ACL (we need to overwrite the default ACL's in this case)
*/
- if (set_readOnly == acl_readOnly_found || SetNamedSecurityInfoA(
- (LPSTR) nativePath, SE_FILE_OBJECT,
- DACL_SECURITY_INFORMATION /*| PROTECTED_DACL_SECURITY_INFORMATION*/,
- NULL, NULL, newAcl, NULL) == ERROR_SUCCESS) {
+ if (SetNamedSecurityInfoA((LPSTR)nativePath,
+ SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION |
+ PROTECTED_DACL_SECURITY_INFORMATION,
+ NULL,
+ NULL,
+ newAcl,
+ NULL) == ERROR_SUCCESS) {
res = 0;
}
done:
- if (secDesc) {
- ckfree(secDesc);
+ if (pTokenUser) {
+ ckfree(pTokenUser);
+ }
+ if (hToken) {
+ CloseHandle(hToken);
}
if (newAcl) {
ckfree(newAcl);
}
- if (userSid) {
- ckfree(userSid);
- }
- if (userDomain) {
- ckfree(userDomain);
+ for (i = 0; i < nSids; ++i) {
+ ckfree(aceEntry[i].pSid);
}
if (res != 0) {
return res;
}
- /*
- * Run normal chmod command.
- */
-
+ /* Run normal chmod command */
return chmod(nativePath, pmode);
+
}
/*