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