1 /* 2 * regexpl - Console Registry Explorer 3 * 4 * Copyright (C) 2000-2005 Nedko Arnaudov <nedko@users.sourceforge.net> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; see the file COPYING. If not, write to 18 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 * Boston, MA 02111-1307, USA. 20 */ 21 22 // ShellCommandDACL.cpp: implementation of the CShellCommandDACL class. 23 // 24 ////////////////////////////////////////////////////////////////////// 25 26 #include "ph.h" 27 #include "ShellCommandDACL.h" 28 #include "RegistryExplorer.h" 29 #include "SecurityDescriptor.h" 30 31 #define DACL_CMD _T("DACL") 32 #define DACL_CMD_LENGTH COMMAND_LENGTH(DACL_CMD) 33 #define DACL_CMD_SHORT_DESC DACL_CMD _T(" command is used to view")/*"/edit"*/_T(" key's DACL.\n") 34 35 ////////////////////////////////////////////////////////////////////// 36 // Construction/Destruction 37 ////////////////////////////////////////////////////////////////////// 38 39 CShellCommandDACL::CShellCommandDACL(CRegistryTree& rTree):m_rTree(rTree) 40 { 41 42 } 43 44 CShellCommandDACL::~CShellCommandDACL() 45 { 46 47 } 48 49 BOOL CShellCommandDACL::Match(const TCHAR *pchCommand) 50 { 51 if (_tcsicmp(pchCommand,DACL_CMD) == 0) 52 return TRUE; 53 if (_tcsnicmp(pchCommand,DACL_CMD _T(".."),DACL_CMD_LENGTH+2*sizeof(TCHAR)) == 0) 54 return TRUE; 55 if (_tcsnicmp(pchCommand,DACL_CMD _T("/") ,DACL_CMD_LENGTH+1*sizeof(TCHAR)) == 0) 56 return TRUE; 57 if (_tcsnicmp(pchCommand,DACL_CMD _T("\\"),DACL_CMD_LENGTH+1*sizeof(TCHAR)) == 0) 58 return TRUE; 59 return FALSE; 60 } 61 62 int CShellCommandDACL::Execute(CConsole &rConsole, CArgumentParser& rArguments) 63 { 64 rArguments.ResetArgumentIteration(); 65 66 const TCHAR *pszKey = NULL; 67 BOOL blnDo = TRUE; 68 BOOL blnBadParameter = FALSE; 69 BOOL blnHelp = FALSE; 70 const TCHAR *pchParameter; 71 const TCHAR *pchCommandItself = rArguments.GetNextArgument(); 72 LONG nError; 73 74 if ((_tcsnicmp(pchCommandItself,DACL_CMD _T(".."),DACL_CMD_LENGTH+2*sizeof(TCHAR)) == 0)|| 75 (_tcsnicmp(pchCommandItself,DACL_CMD _T("\\"),DACL_CMD_LENGTH+1*sizeof(TCHAR)) == 0)) 76 { 77 pszKey = pchCommandItself + DACL_CMD_LENGTH; 78 } 79 else if (_tcsnicmp(pchCommandItself,DACL_CMD _T("/"),DACL_CMD_LENGTH+1*sizeof(TCHAR)) == 0) 80 { 81 pchParameter = pchCommandItself + DACL_CMD_LENGTH; 82 goto CheckDACLArgument; 83 } 84 85 while((pchParameter = rArguments.GetNextArgument()) != NULL) 86 { 87 CheckDACLArgument: 88 blnBadParameter = FALSE; 89 if ((_tcsicmp(pchParameter,_T("/?")) == 0) 90 ||(_tcsicmp(pchParameter,_T("-?")) == 0)) 91 { 92 blnHelp = TRUE; 93 blnDo = pszKey != NULL; 94 } 95 else if (!pszKey) 96 { 97 pszKey = pchParameter; 98 blnDo = TRUE; 99 } 100 else 101 { 102 blnBadParameter = TRUE; 103 } 104 if (blnBadParameter) 105 { 106 rConsole.Write(_T("Bad parameter: ")); 107 rConsole.Write(pchParameter); 108 rConsole.Write(_T("\n")); 109 } 110 } 111 112 CRegistryKey Key; 113 114 if (!m_rTree.GetKey(pszKey?pszKey:_T("."),KEY_QUERY_VALUE|READ_CONTROL,Key)) 115 { 116 rConsole.Write(m_rTree.GetLastErrorDescription()); 117 blnDo = FALSE; 118 } 119 120 if (blnHelp) 121 { 122 rConsole.Write(GetHelpString()); 123 } 124 125 if (blnDo&&blnHelp) rConsole.Write(_T("\n")); 126 127 if (!blnDo) 128 return 0; 129 130 if (Key.IsRoot()) 131 { // root key 132 rConsole.Write(DACL_CMD COMMAND_NA_ON_ROOT); 133 return 0; 134 } 135 136 DWORD dwSecurityDescriptorLength; 137 rConsole.Write(_T("Key : ")); 138 rConsole.Write(_T("\\")); 139 rConsole.Write(Key.GetKeyName()); 140 rConsole.Write(_T("\n")); 141 PISECURITY_DESCRIPTOR pSecurityDescriptor = NULL; 142 TCHAR *pchName = NULL, *pchDomainName = NULL; 143 try 144 { 145 nError = Key.GetSecurityDescriptorLength(&dwSecurityDescriptorLength); 146 if (nError != ERROR_SUCCESS) 147 throw nError; 148 149 pSecurityDescriptor = (PISECURITY_DESCRIPTOR) new unsigned char [dwSecurityDescriptorLength]; 150 DWORD dwSecurityDescriptorLength1 = dwSecurityDescriptorLength; 151 nError = Key.GetSecurityDescriptor((SECURITY_INFORMATION)DACL_SECURITY_INFORMATION,pSecurityDescriptor,&dwSecurityDescriptorLength1); 152 if (nError != ERROR_SUCCESS) 153 throw nError; 154 CSecurityDescriptor sd; 155 sd.AssociateDescriptor(pSecurityDescriptor); 156 157 sd.BeginDACLInteration(); 158 ASSERT(sd.DescriptorContainsDACL()); 159 if (sd.HasNULLDACL()) 160 { 161 rConsole.Write(_T("Key has not DACL.\n(This allows all access)\n")); 162 } 163 else 164 { 165 if (!sd.HasValidDACL()) 166 { 167 rConsole.Write(_T("Invalid DACL.\n")); 168 } 169 else 170 { 171 DWORD nACECount = sd.GetDACLEntriesCount(); 172 rConsole.Write(_T("DACL has ")); 173 TCHAR Buffer[256]; 174 rConsole.Write(_itoa(nACECount,Buffer,10)); 175 rConsole.Write(_T(" ACEs.\n")); 176 if (nACECount == 0) 177 { 178 rConsole.Write(_T("(This denies all access)\n")); 179 } 180 else 181 { 182 for (DWORD i = 0 ; i < nACECount ; i++) 183 { 184 rConsole.Write(_T("\n")); 185 rConsole.Write(_T("\tACE Index: ")); 186 rConsole.Write(_itoa(i,Buffer,10)); 187 rConsole.Write(_T("\n")); 188 rConsole.Write(_T("\tACE Type: ")); 189 switch (sd.GetDACLEntry(i)) 190 { 191 case CSecurityDescriptor::AccessAlowed: 192 rConsole.Write(_T("Access-allowed\n")); 193 break; 194 case CSecurityDescriptor::AccessDenied: 195 rConsole.Write(_T("Access-denied\n")); 196 break; 197 default: 198 rConsole.Write(_T("Unknown.\nCannot continue dumping of the ACE list.\n")); 199 goto AbortDumpDACL; 200 } 201 PSID pSID = sd.GetCurrentACE_SID(); 202 if ((pSID == NULL)||(!IsValidSid(pSID))) 203 { 204 rConsole.Write(_T("\tInvalid SID.\n")); 205 } 206 else 207 { 208 DWORD dwSIDStringSize = 0; 209 BOOL blnRet = GetTextualSid(pSID,NULL,&dwSIDStringSize); 210 ASSERT(!blnRet); 211 ASSERT(GetLastError() == ERROR_INSUFFICIENT_BUFFER); 212 TCHAR *pchSID = new TCHAR[dwSIDStringSize]; 213 if(!GetTextualSid(pSID,pchSID,&dwSIDStringSize)) 214 { 215 DWORD dwError = GetLastError(); 216 ASSERT(dwError != ERROR_INSUFFICIENT_BUFFER); 217 rConsole.Write(_T("Error ")); 218 TCHAR Buffer[256]; 219 rConsole.Write(_itoa(dwError,Buffer,10)); 220 rConsole.Write(_T("\nGetting string representation of SID\n")); 221 } 222 else 223 { 224 rConsole.Write(_T("\tSID: ")); 225 rConsole.Write(pchSID); 226 rConsole.Write(_T("\n")); 227 } 228 delete[] pchSID; 229 DWORD dwNameBufferLength, dwDomainNameBufferLength; 230 dwNameBufferLength = 1024; 231 dwDomainNameBufferLength = 1024; 232 pchName = new TCHAR [dwNameBufferLength]; 233 pchDomainName = new TCHAR [dwDomainNameBufferLength]; 234 DWORD dwNameLength = dwNameBufferLength, dwDomainNameLength = dwDomainNameBufferLength; 235 SID_NAME_USE Use; 236 if (!LookupAccountSid(NULL,pSID,pchName,&dwNameLength,pchDomainName,&dwDomainNameLength,&Use)) 237 { 238 rConsole.Write(_T("Error ")); 239 TCHAR Buffer[256]; 240 rConsole.Write(_itoa(GetLastError(),Buffer,10)); 241 rConsole.Write(_T("\n")); 242 } 243 else 244 { 245 rConsole.Write(_T("\tTrustee Domain: ")); 246 rConsole.Write(pchDomainName); 247 rConsole.Write(_T("\n")); 248 rConsole.Write(_T("\tTrustee Name: ")); 249 rConsole.Write(pchName); 250 rConsole.Write(_T("\n\tSID type: ")); 251 rConsole.Write(GetSidTypeName(Use)); 252 rConsole.Write(_T("\n")); 253 } 254 delete [] pchName; 255 pchName = NULL; 256 delete [] pchDomainName; 257 pchDomainName = NULL; 258 } 259 260 BYTE bFlags; 261 sd.GetCurrentACE_Flags(bFlags); 262 wsprintf(Buffer,_T("\tFlags: 0x%02lX\n"),bFlags); 263 rConsole.Write(Buffer); 264 if (bFlags & CONTAINER_INHERIT_ACE) 265 { 266 rConsole.Write(_T("\t\tCONTAINER_INHERIT_ACE\n")); 267 } 268 if (bFlags & INHERIT_ONLY_ACE) 269 { 270 rConsole.Write(_T("\t\tINHERIT_ONLY_ACE\n")); 271 } 272 if (bFlags & INHERITED_ACE) 273 { 274 rConsole.Write(_T("\t\tINHERITED_ACE\n")); 275 } 276 if (bFlags & NO_PROPAGATE_INHERIT_ACE) 277 { 278 rConsole.Write(_T("\t\tNO_PROPAGATE_INHERIT_ACE\n")); 279 } 280 if (bFlags & OBJECT_INHERIT_ACE) 281 { 282 rConsole.Write(_T("\t\tOBJECT_INHERIT_ACE\n")); 283 } 284 285 DWORD dwAccessMask; 286 sd.GetCurrentACE_AccessMask(dwAccessMask); 287 wsprintf(Buffer,_T("\tAccess Mask: 0x%08lX\n"),dwAccessMask); 288 rConsole.Write(Buffer); 289 if (dwAccessMask & GENERIC_READ) 290 { 291 rConsole.Write(_T("\t\tGENERIC_READ\n")); 292 } 293 if (dwAccessMask & GENERIC_WRITE) 294 { 295 rConsole.Write(_T("\t\tGENERIC_WRITE\n")); 296 } 297 if (dwAccessMask & GENERIC_EXECUTE) 298 { 299 rConsole.Write(_T("\t\tGENERIC_EXECUTE\n")); 300 } 301 if (dwAccessMask & GENERIC_ALL) 302 { 303 rConsole.Write(_T("\t\tGENERIC_ALL\n")); 304 } 305 if (dwAccessMask & SYNCHRONIZE) 306 { 307 rConsole.Write(_T("\t\tSYNCHRONIZE\n")); 308 } 309 if (dwAccessMask & WRITE_OWNER) 310 { 311 rConsole.Write(_T("\t\tWRITE_OWNER\n")); 312 } 313 if (dwAccessMask & WRITE_DAC) 314 { 315 rConsole.Write(_T("\t\tWRITE_DAC\n")); 316 } 317 if (dwAccessMask & READ_CONTROL) 318 { 319 rConsole.Write(_T("\t\tREAD_CONTROL\n")); 320 } 321 if (dwAccessMask & DELETE) 322 { 323 rConsole.Write(_T("\t\tDELETE\n")); 324 } 325 if (dwAccessMask & KEY_CREATE_LINK) 326 { 327 rConsole.Write(_T("\t\tKEY_CREATE_LINK\n")); 328 } 329 if (dwAccessMask & KEY_NOTIFY) 330 { 331 rConsole.Write(_T("\t\tKEY_NOTIFY\n")); 332 } 333 if (dwAccessMask & KEY_ENUMERATE_SUB_KEYS) 334 { 335 rConsole.Write(_T("\t\tKEY_ENUMERATE_SUB_KEYS\n")); 336 } 337 if (dwAccessMask & KEY_CREATE_SUB_KEY) 338 { 339 rConsole.Write(_T("\t\tKEY_CREATE_SUB_KEY\n")); 340 } 341 if (dwAccessMask & KEY_SET_VALUE) 342 { 343 rConsole.Write(_T("\t\tKEY_SET_VALUE\n")); 344 } 345 if (dwAccessMask & KEY_QUERY_VALUE) 346 { 347 rConsole.Write(_T("\t\tKEY_QUERY_VALUE\n")); 348 } 349 } // for 350 } // else (nACECount == 0) 351 } // else (!sd.HasValidDACL()) 352 } // else (sd.HasNULLDACL()) 353 AbortDumpDACL: 354 delete [] pSecurityDescriptor; 355 } // try 356 catch (DWORD dwError) 357 { 358 rConsole.Write(_T("Error ")); 359 TCHAR Buffer[256]; 360 rConsole.Write(_itoa(dwError,Buffer,10)); 361 rConsole.Write(_T("\n")); 362 if (pchName) delete [] pchName; 363 if (pchDomainName) delete [] pchDomainName; 364 if (pSecurityDescriptor) delete [] pSecurityDescriptor; 365 } 366 367 return 0; 368 } 369 370 const TCHAR * CShellCommandDACL::GetHelpString() 371 { 372 return DACL_CMD_SHORT_DESC 373 _T("Syntax: ") DACL_CMD _T(" [<KEY>] [/?]\n\n") 374 _T(" <KEY> - Optional relative path of desired key.\n") 375 _T(" /? - This help.\n\n") 376 _T("Without parameters, command displays DACL of current key.\n"); 377 } 378 379 const TCHAR * CShellCommandDACL::GetHelpShortDescriptionString() 380 { 381 return DACL_CMD_SHORT_DESC; 382 } 383