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 // SecurityDescriptor.cpp: implementation of the CSecurityDescriptor class.
23 //
24 //////////////////////////////////////////////////////////////////////
25 
26 #include "ph.h"
27 #include "SecurityDescriptor.h"
28 
GetTextualSid(PSID pSid,LPTSTR TextualSid,LPDWORD lpdwBufferLen)29 BOOL GetTextualSid(
30     PSID pSid,            // binary Sid
31     LPTSTR TextualSid,    // buffer for Textual representation of Sid
32     LPDWORD lpdwBufferLen // required/provided TextualSid buffersize
33     )
34 {
35     PSID_IDENTIFIER_AUTHORITY psia;
36     DWORD dwSubAuthorities;
37     DWORD dwSidRev=SID_REVISION;
38     DWORD dwCounter;
39     DWORD dwSidSize;
40 
41     // Validate the binary SID.
42 
43     if(!IsValidSid(pSid)) return FALSE;
44 
45     // Get the identifier authority value from the SID.
46 
47     psia = GetSidIdentifierAuthority(pSid);
48 
49     // Get the number of subauthorities in the SID.
50 
51     dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
52 
53     // Compute the buffer length.
54     // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
55 
56     dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
57 
58     // Check input buffer length.
59     // If too small, indicate the proper size and set last error.
60 
61     if (*lpdwBufferLen < dwSidSize)
62     {
63         *lpdwBufferLen = dwSidSize;
64         SetLastError(ERROR_INSUFFICIENT_BUFFER);
65         return FALSE;
66     }
67 
68     // Add 'S' prefix and revision number to the string.
69 
70     dwSidSize=wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
71 
72     // Add SID identifier authority to the string.
73 
74     if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
75     {
76         dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
77                     TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
78                     (USHORT)psia->Value[0],
79                     (USHORT)psia->Value[1],
80                     (USHORT)psia->Value[2],
81                     (USHORT)psia->Value[3],
82                     (USHORT)psia->Value[4],
83                     (USHORT)psia->Value[5]);
84     }
85     else
86     {
87         dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
88                     TEXT("%lu"),
89                     (ULONG)(psia->Value[5]      )   +
90                     (ULONG)(psia->Value[4] <<  8)   +
91                     (ULONG)(psia->Value[3] << 16)   +
92                     (ULONG)(psia->Value[2] << 24)   );
93     }
94 
95     // Add SID subauthorities to the string.
96     //
97     for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
98     {
99         dwSidSize+=wsprintf(TextualSid + dwSidSize, TEXT("-%lu"),
100                     *GetSidSubAuthority(pSid, dwCounter) );
101     }
102 
103     return TRUE;
104 }
105 
GetSidTypeName(SID_NAME_USE Use)106 const TCHAR * GetSidTypeName(SID_NAME_USE Use)
107 {
108 	switch(Use)
109 	{
110 	case SidTypeUser:
111 		return _T("User SID");
112 	case SidTypeGroup:
113 		return _T("Group SID");
114 	case SidTypeDomain:
115 		return _T("Domain SID");
116 	case SidTypeAlias:
117 		return _T("Alias SID");
118 	case SidTypeWellKnownGroup:
119 		return _T("SID for a well-known group");
120 	case SidTypeDeletedAccount:
121 		return _T("SID for a deleted account");
122 	case SidTypeInvalid:
123 		return _T("Invalid SID");
124 	case SidTypeUnknown:
125 		return _T("Unknown SID type");
126 	default:
127 		return _T("Error. Cannot recognize SID type.");
128 	}
129 }
130 
131 //////////////////////////////////////////////////////////////////////
132 // Construction/Destruction
133 //////////////////////////////////////////////////////////////////////
134 
CSecurityDescriptor()135 CSecurityDescriptor::CSecurityDescriptor()
136 {
137 	m_pSecurityDescriptor = NULL;
138 	m_pCurrentACEHeader = NULL;
139 }
140 
~CSecurityDescriptor()141 CSecurityDescriptor::~CSecurityDescriptor()
142 {
143 }
144 
AssociateDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor)145 void CSecurityDescriptor::AssociateDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor)
146 {
147 	m_pSecurityDescriptor = pSecurityDescriptor;
148 }
149 
BeginDACLInteration()150 DWORD CSecurityDescriptor::BeginDACLInteration()
151 {
152 	if (!GetSecurityDescriptorDacl(m_pSecurityDescriptor,&m_blnDACLPresent,&m_pDACL,&m_blnDACLDefaulted))
153 	{
154 		throw GetLastError();
155 	}
156 	return ERROR_SUCCESS;
157 }
158 
DescriptorContainsDACL()159 BOOL CSecurityDescriptor::DescriptorContainsDACL()
160 {
161 	return m_blnDACLPresent;
162 }
163 
BeginSACLInteration()164 DWORD CSecurityDescriptor::BeginSACLInteration()
165 {
166 	if (!GetSecurityDescriptorSacl(m_pSecurityDescriptor,&m_blnSACLPresent,&m_pSACL,&m_blnSACLDefaulted))
167 		throw GetLastError();
168 	return ERROR_SUCCESS;
169 }
170 
DescriptorContainsSACL()171 BOOL CSecurityDescriptor::DescriptorContainsSACL()
172 {
173 	return m_blnSACLPresent;
174 }
175 
HasNULLDACL()176 BOOL CSecurityDescriptor::HasNULLDACL()
177 {
178 	ASSERT(m_blnDACLPresent);
179 	return (m_pDACL == NULL);
180 }
181 
HasValidDACL()182 BOOL CSecurityDescriptor::HasValidDACL()
183 {
184 	ASSERT(m_blnDACLPresent);
185 	ASSERT(m_pDACL != NULL);
186 	return IsValidAcl(m_pDACL);
187 }
188 
HasNULLSACL()189 BOOL CSecurityDescriptor::HasNULLSACL()
190 {
191 	ASSERT(m_blnSACLPresent);
192 	return (m_pSACL == NULL);
193 }
194 
HasValidSACL()195 BOOL CSecurityDescriptor::HasValidSACL()
196 {
197 	ASSERT(m_blnSACLPresent);
198 	ASSERT(m_pSACL != NULL);
199 	return IsValidAcl(m_pSACL);
200 }
201 
GetDACLEntriesCount()202 DWORD CSecurityDescriptor::GetDACLEntriesCount()
203 {
204 	ACL_SIZE_INFORMATION SizeInfo;
205 	if (!GetAclInformation(m_pDACL,&SizeInfo,sizeof(SizeInfo),AclSizeInformation))
206 		throw GetLastError();
207 	return SizeInfo.AceCount;
208 }
209 
GetSACLEntriesCount()210 DWORD CSecurityDescriptor::GetSACLEntriesCount()
211 {
212 	ACL_SIZE_INFORMATION SizeInfo;
213 	if (!GetAclInformation(m_pSACL,&SizeInfo,sizeof(SizeInfo),AclSizeInformation))
214 		throw GetLastError();
215 	return SizeInfo.AceCount;
216 }
217 
GetDACLEntry(DWORD nIndex)218 CSecurityDescriptor::ACEntryType CSecurityDescriptor::GetDACLEntry(DWORD nIndex)
219 {
220 	void *pACE;
221 	if (!GetAce(m_pDACL,nIndex,&pACE)) throw GetLastError();
222 	m_pCurrentACEHeader = (PACE_HEADER)pACE;
223 	if (m_pCurrentACEHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
224 	{
225 		return AccessAlowed;
226 	}
227 	if (m_pCurrentACEHeader->AceType == ACCESS_DENIED_ACE_TYPE)
228 	{
229 		return AccessDenied;
230 	}
231 	return Unknown;
232 }
233 
GetSACLEntry(DWORD nIndex,BOOL & blnFailedAccess,BOOL & blnSeccessfulAccess)234 CSecurityDescriptor::ACEntryType CSecurityDescriptor::GetSACLEntry(DWORD nIndex, BOOL& blnFailedAccess, BOOL& blnSeccessfulAccess)
235 {
236 	void *pACE;
237 	if (!GetAce(m_pSACL,nIndex,&pACE)) throw GetLastError();
238 	m_pCurrentACEHeader = (PACE_HEADER)pACE;
239 	if (m_pCurrentACEHeader->AceType == SYSTEM_AUDIT_ACE_TYPE)
240 	{
241 		blnFailedAccess = m_pCurrentACEHeader->AceFlags & FAILED_ACCESS_ACE_FLAG;
242 		blnSeccessfulAccess = m_pCurrentACEHeader->AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG;
243 		return SystemAudit;
244 	}
245 	return Unknown;
246 }
247 
GetCurrentACE_SID()248 PSID CSecurityDescriptor::GetCurrentACE_SID()
249 {
250 	ASSERT(m_pCurrentACEHeader != NULL);
251 	switch(m_pCurrentACEHeader->AceType)
252 	{
253 	case ACCESS_ALLOWED_ACE_TYPE:
254 		return ((PSID)&(((ACCESS_ALLOWED_ACE *)m_pCurrentACEHeader)->SidStart));
255 	case ACCESS_DENIED_ACE_TYPE:
256 		return ((PSID)&(((ACCESS_DENIED_ACE *)m_pCurrentACEHeader)->SidStart));
257 	case SYSTEM_AUDIT_ACE_TYPE:
258 		return ((PSID)&(((SYSTEM_AUDIT_ACE *)m_pCurrentACEHeader)->SidStart));
259 	default:
260 		ASSERT(FALSE);	// Do not call this function for unknown ACE types !!!
261 		return NULL;
262 	}
263 }
264 
GetCurrentACE_AccessMask(DWORD & dwMask)265 void CSecurityDescriptor::GetCurrentACE_AccessMask(DWORD& dwMask)
266 {
267 	ASSERT(m_pCurrentACEHeader != NULL);
268 	switch(m_pCurrentACEHeader->AceType)
269 	{
270 	case ACCESS_ALLOWED_ACE_TYPE:
271 		dwMask = (((ACCESS_ALLOWED_ACE *)m_pCurrentACEHeader)->Mask);
272 		return;
273 	case ACCESS_DENIED_ACE_TYPE:
274 		dwMask = (((ACCESS_DENIED_ACE *)m_pCurrentACEHeader)->Mask);
275 		return;
276 	case SYSTEM_AUDIT_ACE_TYPE:
277 		dwMask = (((SYSTEM_AUDIT_ACE *)m_pCurrentACEHeader)->Mask);
278 		return;
279 	default:
280 		ASSERT(FALSE);	// Do not call this function for unknown ACE types !!!
281 		return;
282 	}
283 }
284 
GetCurrentACE_Flags(BYTE & bFlags)285 void CSecurityDescriptor::GetCurrentACE_Flags(BYTE& bFlags)
286 {
287 	ASSERT(m_pCurrentACEHeader != NULL);
288   bFlags = m_pCurrentACEHeader->AceFlags;
289 }
290