1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Service Host
3c2c66affSColin Finck * LICENSE: BSD - See COPYING.ARM in the top level directory
4c2c66affSColin Finck * FILE: base/services/svchost/security.cxx
5c2c66affSColin Finck * PURPOSE: Initializes the COM Object Security Model and Parameters
6c2c66affSColin Finck * PROGRAMMERS: ReactOS Portable Systems Group
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck /* INCLUDES ******************************************************************/
10c2c66affSColin Finck
11c2c66affSColin Finck extern "C"
12c2c66affSColin Finck {
13c2c66affSColin Finck #include "svchost.h"
14c2c66affSColin Finck
15c2c66affSColin Finck #include <aclapi.h>
16c2c66affSColin Finck #include <objidl.h>
17c2c66affSColin Finck }
18c2c66affSColin Finck
19c2c66affSColin Finck /* GLOBALS *******************************************************************/
20c2c66affSColin Finck
21c2c66affSColin Finck SID NtSid = { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } };
22c2c66affSColin Finck
23c2c66affSColin Finck /* FUNCTIONS *****************************************************************/
24c2c66affSColin Finck
25c2c66affSColin Finck DWORD
26c2c66affSColin Finck WINAPI
DwInitializeSdFromThreadToken(_Out_ PVOID * ppSecurityDescriptor,_Out_ PACL * ppAcl)27c2c66affSColin Finck DwInitializeSdFromThreadToken (
28c2c66affSColin Finck _Out_ PVOID *ppSecurityDescriptor,
29c2c66affSColin Finck _Out_ PACL *ppAcl
30c2c66affSColin Finck )
31c2c66affSColin Finck {
32c2c66affSColin Finck HANDLE hToken;
33c2c66affSColin Finck DWORD dwGroupLength, dwUserLength, dwError, dwAlignLength;
34c2c66affSColin Finck PTOKEN_PRIMARY_GROUP pTokenGroup;
35c2c66affSColin Finck PTOKEN_USER pTokenUser;
36c2c66affSColin Finck EXPLICIT_ACCESS_W pListOfExplicitEntries;
37c2c66affSColin Finck PACL pAcl = NULL;
38c2c66affSColin Finck PISECURITY_DESCRIPTOR pSd;
39c2c66affSColin Finck
40c2c66affSColin Finck /* Assume failure */
41c2c66affSColin Finck *ppSecurityDescriptor = NULL;
42c2c66affSColin Finck *ppAcl = NULL;
43c2c66affSColin Finck
44c2c66affSColin Finck /* Open the token of the current thread */
45c2c66affSColin Finck if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, 0, &hToken) == FALSE)
46c2c66affSColin Finck {
47c2c66affSColin Finck /* The thread is not impersonating, use the process token */
48c2c66affSColin Finck if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) == FALSE)
49c2c66affSColin Finck {
50c2c66affSColin Finck /* No token could be queried, fail */
51c2c66affSColin Finck return GetLastError();
52c2c66affSColin Finck }
53c2c66affSColin Finck }
54c2c66affSColin Finck
55c2c66affSColin Finck /* Get the size of the token's user */
56*98bbe835SSerge Gautherie if ((GetTokenInformation(hToken, TokenUser, NULL, 0, &dwUserLength) != FALSE) ||
57c2c66affSColin Finck (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
58c2c66affSColin Finck {
59c2c66affSColin Finck return GetLastError();
60c2c66affSColin Finck }
61c2c66affSColin Finck
62c2c66affSColin Finck /* Get the size of the token's primary group */
63*98bbe835SSerge Gautherie if ((GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &dwGroupLength) != FALSE) ||
64c2c66affSColin Finck (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
65c2c66affSColin Finck {
66c2c66affSColin Finck return GetLastError();
67c2c66affSColin Finck }
68c2c66affSColin Finck
69c2c66affSColin Finck /* Allocate an SD large enough to hold the SIDs for the above */
70c2c66affSColin Finck dwAlignLength = ALIGN_UP(dwUserLength, ULONG);
71c2c66affSColin Finck pSd = (PISECURITY_DESCRIPTOR)MemAlloc(0,
72c2c66affSColin Finck dwAlignLength +
73c2c66affSColin Finck dwGroupLength +
74c2c66affSColin Finck sizeof(*pSd));
75c2c66affSColin Finck if (pSd == NULL) return ERROR_OUTOFMEMORY;
76c2c66affSColin Finck
77c2c66affSColin Finck /* Assume success for now */
78c2c66affSColin Finck dwError = ERROR_SUCCESS;
79c2c66affSColin Finck
80c2c66affSColin Finck /* We'll put them right after the SD itself */
81c2c66affSColin Finck pTokenUser = (PTOKEN_USER)(pSd + 1);
82c2c66affSColin Finck pTokenGroup = (PTOKEN_PRIMARY_GROUP)((ULONG_PTR)pTokenUser + dwAlignLength);
83c2c66affSColin Finck
84c2c66affSColin Finck /* Now initialize it */
85c2c66affSColin Finck if (InitializeSecurityDescriptor(pSd, SECURITY_DESCRIPTOR_REVISION) == FALSE)
86c2c66affSColin Finck {
87c2c66affSColin Finck dwError = GetLastError();
88c2c66affSColin Finck }
89c2c66affSColin Finck
90c2c66affSColin Finck /* And do the actual query for the user */
91c2c66affSColin Finck if (GetTokenInformation(hToken,
92c2c66affSColin Finck TokenUser,
93c2c66affSColin Finck pTokenUser,
94c2c66affSColin Finck dwUserLength,
95c2c66affSColin Finck &dwUserLength) == FALSE)
96c2c66affSColin Finck {
97c2c66affSColin Finck dwError = GetLastError();
98c2c66affSColin Finck }
99c2c66affSColin Finck
100c2c66affSColin Finck /* And then the actual query for the primary group */
101c2c66affSColin Finck if (GetTokenInformation(hToken,
102c2c66affSColin Finck TokenPrimaryGroup,
103c2c66affSColin Finck pTokenGroup,
104c2c66affSColin Finck dwGroupLength,
105c2c66affSColin Finck &dwGroupLength) == FALSE)
106c2c66affSColin Finck {
107c2c66affSColin Finck dwError = GetLastError();
108c2c66affSColin Finck }
109c2c66affSColin Finck
110c2c66affSColin Finck /* Set the user as owner */
111c2c66affSColin Finck if (SetSecurityDescriptorOwner(pSd, pTokenUser->User.Sid, FALSE) == FALSE)
112c2c66affSColin Finck {
113c2c66affSColin Finck dwError = GetLastError();
114c2c66affSColin Finck }
115c2c66affSColin Finck
116c2c66affSColin Finck /* Set the group as primary */
117c2c66affSColin Finck if (SetSecurityDescriptorGroup(pSd, pTokenGroup->PrimaryGroup, FALSE) == FALSE)
118c2c66affSColin Finck {
119c2c66affSColin Finck dwError = GetLastError();
120c2c66affSColin Finck }
121c2c66affSColin Finck
122c2c66affSColin Finck /* Did everything so far work out? */
123c2c66affSColin Finck if (dwError == ERROR_SUCCESS)
124c2c66affSColin Finck {
125c2c66affSColin Finck /* Yes, create an ACL granting the SYSTEM account access */
126c2c66affSColin Finck pListOfExplicitEntries.grfAccessMode = SET_ACCESS;
127c2c66affSColin Finck pListOfExplicitEntries.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
128c2c66affSColin Finck pListOfExplicitEntries.grfAccessPermissions = 1;
129c2c66affSColin Finck pListOfExplicitEntries.grfInheritance = 0;
130c2c66affSColin Finck pListOfExplicitEntries.Trustee.pMultipleTrustee = 0;
131c2c66affSColin Finck pListOfExplicitEntries.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
132c2c66affSColin Finck pListOfExplicitEntries.Trustee.TrusteeForm = TRUSTEE_IS_SID;
133c2c66affSColin Finck pListOfExplicitEntries.Trustee.ptstrName = (LPWSTR)&NtSid;
134c2c66affSColin Finck dwError = SetEntriesInAclW(1, &pListOfExplicitEntries, NULL, &pAcl);
135c2c66affSColin Finck if (dwError == ERROR_SUCCESS)
136c2c66affSColin Finck {
137c2c66affSColin Finck /* Make that ACL the DACL of the SD we just built */
138c2c66affSColin Finck if (SetSecurityDescriptorDacl(pSd, 1, pAcl, FALSE) == FALSE)
139c2c66affSColin Finck {
140c2c66affSColin Finck /* We failed, bail out */
141c2c66affSColin Finck LocalFree(pAcl);
142c2c66affSColin Finck dwError = GetLastError();
143c2c66affSColin Finck }
144c2c66affSColin Finck else
145c2c66affSColin Finck {
146c2c66affSColin Finck /* Now we have the SD and the ACL all ready to go */
147c2c66affSColin Finck *ppSecurityDescriptor = pSd;
148c2c66affSColin Finck *ppAcl = pAcl;
149c2c66affSColin Finck return ERROR_SUCCESS;
150c2c66affSColin Finck }
151c2c66affSColin Finck }
152c2c66affSColin Finck }
153c2c66affSColin Finck
154c2c66affSColin Finck /* Failure path, we'll free the SD since the caller can't use it */
155c2c66affSColin Finck MemFree(pSd);
156c2c66affSColin Finck return dwError;
157c2c66affSColin Finck }
158c2c66affSColin Finck
159c2c66affSColin Finck BOOL
160c2c66affSColin Finck WINAPI
InitializeSecurity(_In_ DWORD dwParam,_In_ DWORD dwAuthnLevel,_In_ DWORD dwImpLevel,_In_ DWORD dwCapabilities)161c2c66affSColin Finck InitializeSecurity (
162c2c66affSColin Finck _In_ DWORD dwParam,
163c2c66affSColin Finck _In_ DWORD dwAuthnLevel,
164c2c66affSColin Finck _In_ DWORD dwImpLevel,
165c2c66affSColin Finck _In_ DWORD dwCapabilities
166c2c66affSColin Finck )
167c2c66affSColin Finck {
168c2c66affSColin Finck HRESULT hr;
169c2c66affSColin Finck PACL pAcl;
170c2c66affSColin Finck PSECURITY_DESCRIPTOR pSecurityDescriptor;
171c2c66affSColin Finck IGlobalOptions *pGlobalOptions;
172c2c66affSColin Finck ASSERT(dwParam != 0);
173c2c66affSColin Finck
174c2c66affSColin Finck /* Create a valid SD and ACL based on the current thread's token */
175c2c66affSColin Finck if (DwInitializeSdFromThreadToken(&pSecurityDescriptor, &pAcl) == ERROR_SUCCESS)
176c2c66affSColin Finck {
177c2c66affSColin Finck /* It worked -- initialize COM without DDE support */
178c2c66affSColin Finck hr = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE);
179c2c66affSColin Finck }
180c2c66affSColin Finck else
181c2c66affSColin Finck {
182c2c66affSColin Finck /* Don't keep going if we don't have an SD */
183c2c66affSColin Finck hr = E_FAIL;
184c2c66affSColin Finck }
185c2c66affSColin Finck
186c2c66affSColin Finck /* Did we make it? */
187c2c66affSColin Finck if (SUCCEEDED(hr))
188c2c66affSColin Finck {
189c2c66affSColin Finck /* Indeed, initialize COM security now */
190c2c66affSColin Finck DBG_TRACE("Calling CoInitializeSecurity (dwAuthCapabilities = 0x%08x)\n",
191c2c66affSColin Finck dwCapabilities);
192c2c66affSColin Finck hr = CoInitializeSecurity(pSecurityDescriptor,
193c2c66affSColin Finck -1,
194c2c66affSColin Finck NULL,
195c2c66affSColin Finck NULL,
196c2c66affSColin Finck dwAuthnLevel,
197c2c66affSColin Finck dwImpLevel,
198c2c66affSColin Finck NULL,
199c2c66affSColin Finck dwCapabilities,
200c2c66affSColin Finck NULL);
201c2c66affSColin Finck if (FAILED(hr)) DBG_ERR("CoInitializeSecurity returned hr=0x%08x\n", hr);
202c2c66affSColin Finck }
203c2c66affSColin Finck
204c2c66affSColin Finck /* Free the SD and ACL since we no longer need it */
205c2c66affSColin Finck MemFree(pSecurityDescriptor);
206c2c66affSColin Finck LocalFree(pAcl);
207c2c66affSColin Finck
208c2c66affSColin Finck /* Did we initialize COM correctly? */
209c2c66affSColin Finck if (SUCCEEDED(hr))
210c2c66affSColin Finck {
211c2c66affSColin Finck /* Get the COM Global Options Interface */
212c2c66affSColin Finck hr = CoCreateInstance(CLSID_GlobalOptions,
213c2c66affSColin Finck NULL,
214c2c66affSColin Finck CLSCTX_INPROC_SERVER,
215c2c66affSColin Finck IID_IGlobalOptions,
216c2c66affSColin Finck (LPVOID*)&pGlobalOptions);
217c2c66affSColin Finck if (SUCCEEDED(hr))
218c2c66affSColin Finck {
219c2c66affSColin Finck /* Use it to disable COM exception handling */
220c2c66affSColin Finck hr = pGlobalOptions->Set(COMGLB_EXCEPTION_HANDLING,
221c2c66affSColin Finck COMGLB_EXCEPTION_DONOT_HANDLE);
222c2c66affSColin Finck pGlobalOptions->Release();
223c2c66affSColin Finck ASSERT(SUCCEEDED(hr));
224c2c66affSColin Finck }
225c2c66affSColin Finck }
226c2c66affSColin Finck
227c2c66affSColin Finck /* Return whether all COM calls were successful or not */
228c2c66affSColin Finck return SUCCEEDED(hr);
229c2c66affSColin Finck }
230