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