2 * PROJECT: ReactOS Service Host
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: base/services/svchost/security.c
5 * PURPOSE: Initializes the COM Object Security Model and Parameters
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES ******************************************************************/
19 /* GLOBALS *******************************************************************/
21 SID NtSid
= { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOCAL_SYSTEM_RID
} };
23 /* FUNCTIONS *****************************************************************/
27 DwInitializeSdFromThreadToken (
28 _Out_ PVOID
*ppSecurityDescriptor
,
33 DWORD dwGroupLength
, dwUserLength
, dwError
, dwAlignLength
;
34 PTOKEN_PRIMARY_GROUP pTokenGroup
;
35 PTOKEN_USER pTokenUser
;
36 EXPLICIT_ACCESS_W pListOfExplicitEntries
;
38 PISECURITY_DESCRIPTOR pSd
;
41 *ppSecurityDescriptor
= NULL
;
44 /* Open the token of the current thread */
45 if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY
, 0, &hToken
) == FALSE
)
47 /* The thread is not impersonating, use the process token */
48 if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
) == FALSE
)
50 /* No token could be queried, fail */
51 return GetLastError();
55 /* Get the size of the token's user */
56 if ((GetTokenInformation(hToken
, TokenUser
, NULL
, 0, &dwUserLength
) == FALSE
) ||
57 (GetLastError() != ERROR_INSUFFICIENT_BUFFER
))
59 return GetLastError();
62 /* Get the size of the token's primary group */
63 if ((GetTokenInformation(hToken
, TokenPrimaryGroup
, NULL
, 0, &dwGroupLength
) == FALSE
) ||
64 (GetLastError() != ERROR_INSUFFICIENT_BUFFER
))
66 return GetLastError();
69 /* Allocate an SD large enough to hold the SIDs for the above */
70 dwAlignLength
= ALIGN_UP(dwUserLength
, ULONG
);
71 pSd
= (PISECURITY_DESCRIPTOR
)MemAlloc(0,
75 if (pSd
== NULL
) return ERROR_OUTOFMEMORY
;
77 /* Assume success for now */
78 dwError
= ERROR_SUCCESS
;
80 /* We'll put them right after the SD itself */
81 pTokenUser
= (PTOKEN_USER
)(pSd
+ 1);
82 pTokenGroup
= (PTOKEN_PRIMARY_GROUP
)((ULONG_PTR
)pTokenUser
+ dwAlignLength
);
84 /* Now initialize it */
85 if (InitializeSecurityDescriptor(pSd
, SECURITY_DESCRIPTOR_REVISION
) == FALSE
)
87 dwError
= GetLastError();
90 /* And do the actual query for the user */
91 if (GetTokenInformation(hToken
,
95 &dwUserLength
) == FALSE
)
97 dwError
= GetLastError();
100 /* And then the actual query for the primary group */
101 if (GetTokenInformation(hToken
,
105 &dwGroupLength
) == FALSE
)
107 dwError
= GetLastError();
110 /* Set the user as owner */
111 if (SetSecurityDescriptorOwner(pSd
, pTokenUser
->User
.Sid
, FALSE
) == FALSE
)
113 dwError
= GetLastError();
116 /* Set the group as primary */
117 if (SetSecurityDescriptorGroup(pSd
, pTokenGroup
->PrimaryGroup
, FALSE
) == FALSE
)
119 dwError
= GetLastError();
122 /* Did everything so far work out? */
123 if (dwError
== ERROR_SUCCESS
)
125 /* Yes, create an ACL granting the SYSTEM account access */
126 pListOfExplicitEntries
.grfAccessMode
= SET_ACCESS
;
127 pListOfExplicitEntries
.Trustee
.TrusteeType
= TRUSTEE_IS_GROUP
;
128 pListOfExplicitEntries
.grfAccessPermissions
= 1;
129 pListOfExplicitEntries
.grfInheritance
= 0;
130 pListOfExplicitEntries
.Trustee
.pMultipleTrustee
= 0;
131 pListOfExplicitEntries
.Trustee
.MultipleTrusteeOperation
= NO_MULTIPLE_TRUSTEE
;
132 pListOfExplicitEntries
.Trustee
.TrusteeForm
= TRUSTEE_IS_SID
;
133 pListOfExplicitEntries
.Trustee
.ptstrName
= (LPWSTR
)&NtSid
;
134 dwError
= SetEntriesInAclW(1, &pListOfExplicitEntries
, NULL
, &pAcl
);
135 if (dwError
== ERROR_SUCCESS
)
137 /* Make that ACL the DACL of the SD we just built */
138 if (SetSecurityDescriptorDacl(pSd
, 1, pAcl
, FALSE
) == FALSE
)
140 /* We failed, bail out */
142 dwError
= GetLastError();
146 /* Now we have the SD and the ACL all ready to go */
147 *ppSecurityDescriptor
= pSd
;
149 return ERROR_SUCCESS
;
154 /* Failure path, we'll free the SD since the caller can't use it */
163 _In_ DWORD dwAuthnLevel
,
164 _In_ DWORD dwImpLevel
,
165 _In_ DWORD dwCapabilities
170 PSECURITY_DESCRIPTOR pSecurityDescriptor
;
171 IGlobalOptions
*pGlobalOptions
;
172 ASSERT(dwParam
!= 0);
174 /* Create a valid SD and ACL based on the current thread's token */
175 if (DwInitializeSdFromThreadToken(&pSecurityDescriptor
, &pAcl
) == ERROR_SUCCESS
)
177 /* It worked -- initialize COM without DDE support */
178 hr
= CoInitializeEx(NULL
, COINIT_DISABLE_OLE1DDE
);
182 /* Don't keep going if we don't have an SD */
186 /* Did we make it? */
189 /* Indeed, initialize COM security now */
190 DBG_TRACE("Calling CoInitializeSecurity (dwAuthCapabilities = 0x%08x)\n",
192 hr
= CoInitializeSecurity(pSecurityDescriptor
,
201 if (FAILED(hr
)) DBG_ERR("CoInitializeSecurity returned hr=0x%08x\n", hr
);
204 /* Free the SD and ACL since we no longer need it */
205 MemFree(pSecurityDescriptor
);
208 /* Did we initialize COM correctly? */
211 /* Get the COM Global Options Interface */
212 hr
= CoCreateInstance(CLSID_GlobalOptions
,
214 CLSCTX_INPROC_SERVER
,
216 (LPVOID
*)&pGlobalOptions
);
219 /* Use it to disable COM exception handling */
220 hr
= pGlobalOptions
->Set(COMGLB_EXCEPTION_HANDLING
,
221 COMGLB_EXCEPTION_DONOT_HANDLE
);
222 pGlobalOptions
->Release();
223 ASSERT(SUCCEEDED(hr
));
227 /* Return whether all COM calls were successful or not */
228 return SUCCEEDED(hr
);