1<?php 2error_reporting(E_ALL); 3define('PHPT_ACL_READ', 1 << 1); 4define('PHPT_ACL_WRITE', 1 << 2); 5define('PHPT_ACL_EXEC', 1 << 3); 6define('PHPT_ACL_NONE', 1 << 4); 7define('PHPT_ACL_FULL', 1 << 5); 8 9define('PHPT_ACL_GRANT', 1); 10define('PHPT_ACL_DENY', 2); 11 12function skipif() { 13 if(substr(PHP_OS, 0, 3) != 'WIN' ) { 14 die('skip windows only test'); 15 } 16 if(stripos(php_uname(), 'XP') !== FALSE) { 17 die('skip windows 2003 or newer only test'); 18 } 19 if (getenv('GITHUB_ACTIONS')) { 20 // bug44859_4.phpt test fails on the 1st run 21 // other ACL tests cannot be run twice 22 die('skip failing on Github Actions'); 23 } 24} 25 26function get_username(){ 27 $user = getenv('USERNAME'); 28 29 if (!$user) { 30 $user = get_current_user(); 31 } 32 33 if (!$user) { 34 $user = exec('echo %USERNAME%'); 35 } 36 37 return $user; 38} 39 40function get_domainname() 41{ 42 $domain = getenv('USERDOMAIN'); 43 44 return $domain; 45} 46 47function get_icacls() 48{ 49 $sysroot = exec('echo %SYSTEMROOT%'); 50 51 return "$sysroot\\System32\\icacls.exe"; 52} 53 54function fix_acls() { 55 $user = get_username(); 56 /* Current user needs to be owner of the test files. As well 57 all the other users having acls on the files must loose them. 58 The following fixes this just partially, as dynamically reading 59 all the users having acls on a file could be sophisticated. */ 60 exec(get_icacls() . ' ' . __DIR__ . ' /setowner ' . escapeshellarg($user) . ' /T /L /Q /C > nul 2>&1'); 61 exec(get_icacls() . ' ' . __DIR__ . ' /remove:g Administrators /T /L /Q /C > nul 2>&1'); 62} 63 64function icacls_set($path, $mode, $perm) { 65 $icacls = get_icacls(); 66 $user = get_username(); 67 $path_escaped = '"' . $path . '"'; 68 $perm_entry = array(); 69 70 if ($perm & PHPT_ACL_READ) $perm_entry[] = 'R'; 71 if ($perm & PHPT_ACL_WRITE) $perm_entry[] = 'W'; 72 if ($perm & PHPT_ACL_EXEC) $perm_entry[] = 'RX'; 73 if ($perm & PHPT_ACL_FULL) $perm_entry[] = 'F'; 74 75 // Deny all 76 $cmd = $icacls . ' ' . $path_escaped . ' /inheritance:r /deny ' . $user . ':(F,M,R,RX,W)'; 77 exec($cmd); 78 79 if ($perm & PHPT_ACL_NONE) { 80 /* 81 This is required to remove all the previously denied 82 permission for the USER. Just granting permission doesn't 83 remove the previously denied permission. 84 */ 85 $cmd = $icacls . ' ' . $path_escaped . ' /remove:d ' . $user; 86 exec($cmd); 87 $cmd = $icacls . ' ' . $path_escaped . ' /remove:g ' . $user; 88 exec($cmd); 89 return; 90 } 91 92 if ($mode == PHPT_ACL_GRANT) { 93 $mode = 'grant'; 94 } else { 95 $mode = 'deny'; 96 } 97 98 99 // Deny all 100 $cmd = $icacls . ' ' . $path_escaped . ' /deny ' . $user . ':(F,M,R,RX,W)'; 101 exec($cmd); 102 103 /* 104 This is required to remove all the previously denied 105 permission for the USER. Just granting permission doesn't 106 remove the previously denied permission. 107 */ 108 $cmd = $icacls . ' ' . $path_escaped . ' /remove:d ' . $user; 109 exec($cmd); 110 $cmd = $icacls . ' ' . $path_escaped . ' /remove:g ' . $user; 111 exec($cmd); 112 113 114 /* 115 Required to set no permission and check that is_readable() 116 returns false. If the $perm_entry contains 'N' skip this step. 117 This will make the file/dir with NO aceess. 118 */ 119 if (!in_array('N', $perm_entry)) { 120 /* 121 This is required to remove all the previously denied 122 permission for the USER. Just granting permission doesn't 123 remove the previously denied permission. 124 */ 125 $cmd = $icacls . ' ' . $path_escaped . ' /remove:d ' . $user; 126 exec($cmd); 127 $cmd = $icacls . ' ' . $path_escaped . ' /remove:g ' . $user; 128 exec($cmd); 129 130 $cmd = $icacls . ' ' . $path_escaped . ' /' . $mode . ' ' . $user; 131 $cmd .= ':' . '(' . implode(',', $perm_entry) . ')'; 132 exec($cmd); 133 } 134} 135 136function create_dir($name, $perms) { 137 if (empty($name)) { 138 echo "create_dir: Empty name is not allowed\n"; 139 return; 140 } 141 142 mkdir($name); 143 $dst = realpath($name); 144 icacls_set($name, PHPT_ACL_GRANT, $perms); 145} 146 147function create_file($name, $perms) { 148 if (empty($name)) { 149 echo "create_file: Empty name is not allowed\n"; 150 return; 151 } 152 153 touch($name); 154 icacls_set($name, PHPT_ACL_GRANT, $perms); 155} 156 157function delete_file($path) { 158 icacls_set($path, PHPT_ACL_GRANT, PHPT_ACL_FULL); 159 if (is_file($path)) { 160 unlink($path); 161 } else { 162 echo "delete_file: '$path' is not a file\n"; 163 return; 164 } 165} 166 167function delete_dir($path) { 168 if (is_dir($path)) { 169 icacls_set($path, PHPT_ACL_GRANT, PHPT_ACL_FULL); 170 rmdir($path); 171 } else { 172 echo "delete_dir: '$path' is not a directory\n"; 173 return; 174 } 175} 176