1 /* $Id: ShellCommandSACL.cpp,v 1.1 2000/10/04 21:04:31 ea Exp $
3 * regexpl - Console Registry Explorer
5 * Copyright (c) 1999-2000 Nedko Arnaoudov <nedkohome@atia.com>
11 // ShellCommandSACL.cpp: implementation of the CShellCommandSACL class.
13 //////////////////////////////////////////////////////////////////////
16 #include "ShellCommandSACL.h"
17 #include "RegistryExplorer.h"
18 #include "SecurityDescriptor.h"
20 #define SACL_CMD _T("SACL")
21 #define SACL_CMD_LENGTH COMMAND_LENGTH(SACL_CMD)
22 #define SACL_CMD_SHORT_DESC SACL_CMD _T(" command is used to view")/*"/edit"*/_T(" key's SACL.\n")
24 //////////////////////////////////////////////////////////////////////
25 // Construction/Destruction
26 //////////////////////////////////////////////////////////////////////
28 CShellCommandSACL::CShellCommandSACL(CRegistryTree
& rTree
):m_rTree(rTree
)
33 CShellCommandSACL::~CShellCommandSACL()
38 BOOL
CShellCommandSACL::Match(const TCHAR
*pchCommand
)
40 if (_tcsicmp(pchCommand
,SACL_CMD
) == 0)
42 if (_tcsnicmp(pchCommand
,SACL_CMD
_T(".."),SACL_CMD_LENGTH
+2*sizeof(TCHAR
)) == 0)
44 if (_tcsnicmp(pchCommand
,SACL_CMD
_T("/") ,SACL_CMD_LENGTH
+1*sizeof(TCHAR
)) == 0)
46 if (_tcsnicmp(pchCommand
,SACL_CMD
_T("\\"),SACL_CMD_LENGTH
+1*sizeof(TCHAR
)) == 0)
51 int CShellCommandSACL::Execute(CConsole
&rConsole
, CArgumentParser
& rArguments
)
55 rArguments
.ResetArgumentIteration();
57 const TCHAR
*pchKey
= NULL
;
59 BOOL blnBadParameter
= FALSE
;
61 const TCHAR
*pchParameter
;
62 const TCHAR
*pchCommandItself
= rArguments
.GetNextArgument();
65 if ((_tcsnicmp(pchCommandItself
,SACL_CMD
_T(".."),SACL_CMD_LENGTH
+2*sizeof(TCHAR
)) == 0)||
66 (_tcsnicmp(pchCommandItself
,SACL_CMD
_T("\\"),SACL_CMD_LENGTH
+1*sizeof(TCHAR
)) == 0))
68 pchKey
= pchCommandItself
+ SACL_CMD_LENGTH
;
70 else if (_tcsnicmp(pchCommandItself
,SACL_CMD
_T("/"),SACL_CMD_LENGTH
+1*sizeof(TCHAR
)) == 0)
72 pchParameter
= pchCommandItself
+ SACL_CMD_LENGTH
;
73 goto CheckSACLArgument
;
76 while((pchParameter
= rArguments
.GetNextArgument()) != NULL
)
79 blnBadParameter
= FALSE
;
80 // Console.Write(_T("Processing parameter: \")");
81 // Console.Write(pchParameter);
82 // Console.Write(_T("\")\n");
83 if ((_tcsicmp(pchParameter
,_T("/?")) == 0)
84 ||(_tcsicmp(pchParameter
,_T("-?")) == 0))
87 blnDo
= pchKey
!= NULL
;
91 pchKey
= pchParameter
;
96 blnBadParameter
= TRUE
;
100 rConsole
.Write(_T("Bad parameter: "));
101 rConsole
.Write(pchParameter
);
102 rConsole
.Write(_T("\n"));
106 CRegistryTree
*pTree
= NULL
;
107 CRegistryKey
*pKey
= NULL
;
110 pTree
= new CRegistryTree(m_rTree
);
111 if ((_tcscmp(pTree
->GetCurrentPath(),m_rTree
.GetCurrentPath()) != 0)||(!pTree
->ChangeCurrentKey(pchKey
)))
113 rConsole
.Write(_T("Cannot open key "));
114 rConsole
.Write(pchKey
);
115 rConsole
.Write(_T("\n"));
121 pKey
= pTree
->GetCurrentKey();
126 pKey
= m_rTree
.GetCurrentKey();
131 rConsole
.Write(GetHelpString());
134 if (blnDo
&&blnHelp
) rConsole
.Write(_T("\n"));
141 throw (SACL_CMD COMMAND_NA_ON_ROOT
);
143 HANDLE hThreadToken
= INVALID_HANDLE_VALUE
;
144 if (!OpenThreadToken(GetCurrentThread(),TOKEN_ADJUST_PRIVILEGES
|TOKEN_QUERY
,FALSE
,&hThreadToken
))
145 { // OpenThreadToken fails
146 dwError
= GetLastError();
147 if (dwError
!= ERROR_NO_TOKEN
)
149 _stprintf(err_msg
,_T("\nCannot open thread token.\nOpenThreadToken fails with error: %u\n"),dwError
);
152 // If the thread does not have an access token, we'll examine the
153 // access token associated with the process.
154 if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES
|TOKEN_QUERY
,&hThreadToken
))
156 _stprintf(err_msg
,_T("\nCannot open process token.\nOpenProcessToken fails with error: %u\n"),GetLastError());
160 ASSERT(hThreadToken
!= INVALID_HANDLE_VALUE
);
161 TOKEN_PRIVILEGES priv
;
162 priv
.PrivilegeCount
= 1;
163 priv
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
164 if (!LookupPrivilegeValue(
165 NULL
, // lookup privilege on local system
166 SE_SECURITY_NAME
, // privilege to lookup
167 &(priv
.Privileges
[0].Luid
))) // receives LUID of privilege
169 _stprintf(err_msg
,_T("\nCannot retrieve the locally unique identifier for %s privilege.\nLookupPrivilegeValue error: %u\n"),SE_SECURITY_NAME
,GetLastError());
172 BOOL blnAdjRet
= AdjustTokenPrivileges(
176 sizeof(TOKEN_PRIVILEGES
),
177 (PTOKEN_PRIVILEGES
)NULL
,
179 dwError
= GetLastError();
182 _stprintf(err_msg
,_T("\nCannot enable %s privilege.\nAdjustTokenPrivileges fails with error: %u%s\n"),SE_SECURITY_NAME
,dwError
,(dwError
== 5)?_T(" (Access denied)"):_T(""));
185 if (dwError
!= ERROR_SUCCESS
)
187 if (dwError
== ERROR_NOT_ALL_ASSIGNED
)
189 _stprintf(err_msg
,_T("\nCannot enable %s privilege.\nThe token does not have the %s privilege\n"),SE_SECURITY_NAME
,SE_SECURITY_NAME
);
193 _stprintf(err_msg
,_T("\nCannot enable %s privilege.\nAdjustTokenPrivileges succeds with error: %u\n"),SE_SECURITY_NAME
,dwError
);
197 if (!pKey
->IsPredefined())
199 dwError
= pKey
->Open(m_rTree
.GetDesiredOpenKeyAccess()|ACCESS_SYSTEM_SECURITY
);
200 if (dwError
!= ERROR_SUCCESS
)
202 _stprintf(err_msg
,_T("\nCannot reopen current key.\nError %u%s\n"),dwError
,(dwError
== 5)?_T(" (Access denied)"):_T(""));
206 DWORD dwSecurityDescriptorLength
;
207 rConsole
.Write(_T("Key : "));
208 rConsole
.Write(_T("\\"));
209 rConsole
.Write(pTree
?pTree
->GetCurrentPath():m_rTree
.GetCurrentPath());
210 rConsole
.Write(_T("\n"));
211 dwError
= pKey
->GetSecurityDescriptorLength(&dwSecurityDescriptorLength
);
212 if (dwError
!= ERROR_SUCCESS
)
214 _stprintf(err_msg
,_T("\nCannot get security descriptor's length for current key.\nError: %u\n"),dwError
);
217 PSECURITY_DESCRIPTOR pSecurityDescriptor
= (PSECURITY_DESCRIPTOR
) new unsigned char [dwSecurityDescriptorLength
];
218 DWORD dwSecurityDescriptorLength1
= dwSecurityDescriptorLength
;
219 dwError
= pKey
->GetSecurityDescriptor((SECURITY_INFORMATION
)SACL_SECURITY_INFORMATION
,pSecurityDescriptor
,&dwSecurityDescriptorLength1
);
220 if (dwError
!= ERROR_SUCCESS
)
222 _stprintf(err_msg
,_T("\nCannot get security descriptor for current key.\nError: %u%s\n"),dwError
,(dwError
== 1314)?_T("(A required privilege is not held by the client.)\n"):_T(""));
225 CSecurityDescriptor sd
;
226 sd
.AssociateDescriptor(pSecurityDescriptor
);
227 sd
.BeginSACLInteration();
229 if ((!sd
.DescriptorContainsSACL())||(sd
.HasNULLSACL()))
231 throw _T("Key has not SACL.\n");
233 if (!sd
.HasValidSACL())
235 throw _T("Invalid SACL.\n");
237 DWORD nACECount
= sd
.GetSACLEntriesCount();
238 rConsole
.Write(_T("SACL has "));
240 rConsole
.Write(_itot(nACECount
,Buffer
,10));
241 rConsole
.Write(_T(" ACEs.\n"));
242 ASSERT(sizeof(ACL
) == 8);
243 rConsole
.Write(_T("\n"));
244 for (DWORD i
= 0 ; i
< nACECount
; i
++)
246 rConsole
.Write(_T("\n"));
247 rConsole
.Write(_T("\tACE Index: "));
248 rConsole
.Write(_itot(i
,Buffer
,10));
249 rConsole
.Write(_T("\n"));
250 rConsole
.Write(_T("\tAudit Type: "));
251 BOOL blnFailed
, blnSuccessful
;
252 if (sd
.GetSACLEntry(i
,blnFailed
,blnSuccessful
) != CSecurityDescriptor::SystemAudit
)
254 rConsole
.Write(_T("Unknown ACE type.\nCannot continue ACE list dump.\n"));
257 if (blnFailed
) rConsole
.Write(_T("Failed access"));
258 if (blnFailed
&& blnSuccessful
) rConsole
.Write(_T(" & "));
259 if (blnSuccessful
) rConsole
.Write(_T("Successful access"));
260 rConsole
.Write(_T("\n"));
261 PSID pSID
= sd
.GetCurrentACE_SID();
262 if ((pSID
== NULL
)||(!IsValidSid(pSID
)))
264 rConsole
.Write(_T("\tInvalid SID.\n"));
266 DWORD dwSIDStringSize
= 0;
267 BOOL blnRet
= GetTextualSid(pSID
,NULL
,&dwSIDStringSize
);
269 ASSERT(GetLastError() == ERROR_INSUFFICIENT_BUFFER
);
270 TCHAR
*pchSID
= new TCHAR
[dwSIDStringSize
];
271 if(!GetTextualSid(pSID
,pchSID
,&dwSIDStringSize
))
273 dwError
= GetLastError();
274 ASSERT(dwError
!= ERROR_INSUFFICIENT_BUFFER
);
275 rConsole
.Write(_T("Error "));
277 rConsole
.Write(_itot(dwError
,Buffer
,10));
278 rConsole
.Write(_T("\nGetting string representation of SID\n"));
282 rConsole
.Write(_T("\tSID: "));
283 rConsole
.Write(pchSID
);
284 rConsole
.Write(_T("\n"));
287 TCHAR
*pchName
, *pchDomainName
;
288 DWORD dwNameBufferLength
, dwDomainNameBufferLength
;
289 dwNameBufferLength
= 1024;
290 dwDomainNameBufferLength
= 1024;
291 pchName
= new TCHAR
[dwNameBufferLength
];
292 pchDomainName
= new TCHAR
[dwDomainNameBufferLength
];
293 DWORD dwNameLength
= dwNameBufferLength
, dwDomainNameLength
= dwDomainNameBufferLength
;
295 if (!LookupAccountSid(NULL
,pSID
,pchName
,&dwNameLength
,pchDomainName
,&dwDomainNameLength
,&Use
))
297 rConsole
.Write(_T("Error "));
299 rConsole
.Write(_itot(GetLastError(),Buffer
,10));
300 rConsole
.Write(_T("\n"));
304 rConsole
.Write(_T("\tTrustee Domain: "));
305 rConsole
.Write(pchDomainName
);
306 rConsole
.Write(_T("\n"));
307 rConsole
.Write(_T("\tTrustee Name: "));
308 rConsole
.Write(pchName
);
309 rConsole
.Write(_T("\n\tSID type: "));
310 rConsole
.Write(GetSidTypeName(Use
));
311 rConsole
.Write(_T("\n"));
314 sd
.GetCurrentACE_AccessMask(dwAccessMask
);
315 wsprintf(Buffer
,_T("\tAccess Mask: 0x%08lX\n"),dwAccessMask
);
316 rConsole
.Write(Buffer
);
317 if (dwAccessMask
& GENERIC_READ
)
319 rConsole
.Write(_T("\t\tGENERIC_READ\n"));
321 if (dwAccessMask
& GENERIC_WRITE
)
323 rConsole
.Write(_T("\t\tGENERIC_WRITE\n"));
325 if (dwAccessMask
& GENERIC_EXECUTE
)
327 rConsole
.Write(_T("\t\tGENERIC_EXECUTE\n"));
329 if (dwAccessMask
& GENERIC_ALL
)
331 rConsole
.Write(_T("\t\tGENERIC_ALL\n"));
333 if (dwAccessMask
& SYNCHRONIZE
)
335 rConsole
.Write(_T("\t\tSYNCHRONIZE\n"));
337 if (dwAccessMask
& WRITE_OWNER
)
339 rConsole
.Write(_T("\t\tWRITE_OWNER\n"));
341 if (dwAccessMask
& WRITE_DAC
)
343 rConsole
.Write(_T("\t\tWRITE_DAC\n"));
345 if (dwAccessMask
& READ_CONTROL
)
347 rConsole
.Write(_T("\t\tREAD_CONTROL\n"));
349 if (dwAccessMask
& DELETE
)
351 rConsole
.Write(_T("\t\tDELETE\n"));
353 if (dwAccessMask
& KEY_CREATE_LINK
)
355 rConsole
.Write(_T("\t\tKEY_CREATE_LINK\n"));
357 if (dwAccessMask
& KEY_NOTIFY
)
359 rConsole
.Write(_T("\t\tKEY_NOTIFY\n"));
361 if (dwAccessMask
& KEY_ENUMERATE_SUB_KEYS
)
363 rConsole
.Write(_T("\t\tKEY_ENUMERATE_SUB_KEYS\n"));
365 if (dwAccessMask
& KEY_CREATE_SUB_KEY
)
367 rConsole
.Write(_T("\t\tKEY_CREATE_SUB_KEY\n"));
369 if (dwAccessMask
& KEY_SET_VALUE
)
371 rConsole
.Write(_T("\t\tKEY_SET_VALUE\n"));
373 if (dwAccessMask
& KEY_QUERY_VALUE
)
375 rConsole
.Write(_T("\t\tKEY_QUERY_VALUE\n"));
379 delete pSecurityDescriptor
;
381 catch(TCHAR
*pchError
)
383 rConsole
.Write(pchError
);
390 const TCHAR
* CShellCommandSACL::GetHelpString()
392 return SACL_CMD_SHORT_DESC
393 _T("Syntax: ") SACL_CMD
_T(" [<KEY>] [/?]\n\n")
394 _T(" <KEY> - Optional relative path of desired key.\n")
395 _T(" /? - This help.\n\n")
396 _T("Without parameters, command displays SACL of current key.\n");
399 const TCHAR
* CShellCommandSACL::GetHelpShortDescriptionString()
401 return SACL_CMD_SHORT_DESC
;