xref: /reactos/base/services/svchost/security.cxx (revision 9393fc32)
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