2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/access.c
5 * PURPOSE: Access state functions
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) -
8 * Based on patch by Javier M. Mellid
11 /* INCLUDES *******************************************************************/
17 /* GLOBALS ********************************************************************/
19 ERESOURCE SepSubjectContextLock
;
21 /* FUNCTIONS ******************************************************************/
28 SeCaptureSubjectContextEx(IN PETHREAD Thread
,
30 OUT PSECURITY_SUBJECT_CONTEXT SubjectContext
)
32 BOOLEAN CopyOnOpen
, EffectiveOnly
;
36 /* Save the unique ID */
37 SubjectContext
->ProcessAuditId
= Process
->UniqueProcessId
;
39 /* Check if we have a thread */
42 /* We don't, so no token */
43 SubjectContext
->ClientToken
= NULL
;
47 /* Get the impersonation token */
48 SubjectContext
->ClientToken
= PsReferenceImpersonationToken(Thread
,
51 &SubjectContext
->ImpersonationLevel
);
54 /* Get the primary token */
55 SubjectContext
->PrimaryToken
= PsReferencePrimaryToken(Process
);
63 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext
)
65 /* Call the extended API */
66 SeCaptureSubjectContextEx(PsGetCurrentThread(),
67 PsGetCurrentProcess(),
76 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
80 KeEnterCriticalRegion();
81 ExAcquireResourceExclusiveLite(&SepSubjectContextLock
, TRUE
);
89 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
93 ExReleaseResourceLite(&SepSubjectContextLock
);
94 KeLeaveCriticalRegion();
102 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
106 if (SubjectContext
->PrimaryToken
!= NULL
)
108 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, SubjectContext
->PrimaryToken
);
111 if (SubjectContext
->ClientToken
!= NULL
)
113 ObDereferenceObject(SubjectContext
->ClientToken
);
122 SeCreateAccessStateEx(IN PETHREAD Thread
,
123 IN PEPROCESS Process
,
124 IN OUT PACCESS_STATE AccessState
,
125 IN PAUX_ACCESS_DATA AuxData
,
126 IN ACCESS_MASK Access
,
127 IN PGENERIC_MAPPING GenericMapping
)
129 ACCESS_MASK AccessMask
= Access
;
134 /* Map the Generic Acess to Specific Access if we have a Mapping */
135 if ((Access
& GENERIC_ACCESS
) && (GenericMapping
))
137 RtlMapGenericMask(&AccessMask
, GenericMapping
);
140 /* Initialize the Access State */
141 RtlZeroMemory(AccessState
, sizeof(ACCESS_STATE
));
143 /* Capture the Subject Context */
144 SeCaptureSubjectContextEx(Thread
,
146 &AccessState
->SubjectSecurityContext
);
148 /* Set Access State Data */
149 AccessState
->AuxData
= AuxData
;
150 AccessState
->RemainingDesiredAccess
= AccessMask
;
151 AccessState
->OriginalDesiredAccess
= AccessMask
;
152 ExpAllocateLocallyUniqueId(&AccessState
->OperationID
);
154 /* Get the Token to use */
155 Token
= AccessState
->SubjectSecurityContext
.ClientToken
?
156 (PTOKEN
)&AccessState
->SubjectSecurityContext
.ClientToken
:
157 (PTOKEN
)&AccessState
->SubjectSecurityContext
.PrimaryToken
;
159 /* Check for Travers Privilege */
160 if (Token
->TokenFlags
& TOKEN_HAS_TRAVERSE_PRIVILEGE
)
162 /* Preserve the Traverse Privilege */
163 AccessState
->Flags
= TOKEN_HAS_TRAVERSE_PRIVILEGE
;
166 /* Set the Auxiliary Data */
167 AuxData
->PrivilegeSet
= (PPRIVILEGE_SET
)((ULONG_PTR
)AccessState
+
168 FIELD_OFFSET(ACCESS_STATE
,
170 if (GenericMapping
) AuxData
->GenericMapping
= *GenericMapping
;
173 return STATUS_SUCCESS
;
181 SeCreateAccessState(IN OUT PACCESS_STATE AccessState
,
182 IN PAUX_ACCESS_DATA AuxData
,
183 IN ACCESS_MASK Access
,
184 IN PGENERIC_MAPPING GenericMapping
)
188 /* Call the extended API */
189 return SeCreateAccessStateEx(PsGetCurrentThread(),
190 PsGetCurrentProcess(),
202 SeDeleteAccessState(IN PACCESS_STATE AccessState
)
204 PAUX_ACCESS_DATA AuxData
;
208 /* Get the Auxiliary Data */
209 AuxData
= AccessState
->AuxData
;
211 /* Deallocate Privileges */
212 if (AccessState
->PrivilegesAllocated
) ExFreePool(AuxData
->PrivilegeSet
);
214 /* Deallocate Name and Type Name */
215 if (AccessState
->ObjectName
.Buffer
)
217 ExFreePool(AccessState
->ObjectName
.Buffer
);
220 if (AccessState
->ObjectTypeName
.Buffer
)
222 ExFreePool(AccessState
->ObjectTypeName
.Buffer
);
225 /* Release the Subject Context */
226 SeReleaseSubjectContext(&AccessState
->SubjectSecurityContext
);
234 SeSetAccessStateGenericMapping(IN PACCESS_STATE AccessState
,
235 IN PGENERIC_MAPPING GenericMapping
)
239 /* Set the Generic Mapping */
240 ((PAUX_ACCESS_DATA
)AccessState
->AuxData
)->GenericMapping
= *GenericMapping
;
248 SeCreateClientSecurity(IN PETHREAD Thread
,
249 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
250 IN BOOLEAN RemoteClient
,
251 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
253 TOKEN_TYPE TokenType
;
254 BOOLEAN ThreadEffectiveOnly
;
255 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
258 PACCESS_TOKEN NewToken
;
262 Token
= PsReferenceEffectiveToken(Thread
,
264 &ThreadEffectiveOnly
,
265 &ImpersonationLevel
);
266 if (TokenType
!= TokenImpersonation
)
268 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
272 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
274 if (Token
) ObDereferenceObject(Token
);
275 return STATUS_BAD_IMPERSONATION_LEVEL
;
278 if ((ImpersonationLevel
== SecurityAnonymous
) ||
279 (ImpersonationLevel
== SecurityIdentification
) ||
280 ((RemoteClient
) && (ImpersonationLevel
!= SecurityDelegation
)))
282 if (Token
) ObDereferenceObject(Token
);
283 return STATUS_BAD_IMPERSONATION_LEVEL
;
286 ClientContext
->DirectAccessEffectiveOnly
= ((ThreadEffectiveOnly
) ||
287 (Qos
->EffectiveOnly
)) ? TRUE
: FALSE
;
290 if (Qos
->ContextTrackingMode
== SECURITY_STATIC_TRACKING
)
292 ClientContext
->DirectlyAccessClientToken
= FALSE
;
293 Status
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
294 if (!NT_SUCCESS(Status
)) return Status
;
298 ClientContext
->DirectlyAccessClientToken
= TRUE
;
299 if (RemoteClient
!= FALSE
)
302 SeGetTokenControlInformation(Token
,
303 &ClientContext
->ClientTokenControl
);
310 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
311 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
312 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
313 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
314 ClientContext
->ServerIsRemote
= RemoteClient
;
315 ClientContext
->ClientToken
= NewToken
;
316 return STATUS_SUCCESS
;
324 SeCreateClientSecurityFromSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
325 IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos
,
326 IN BOOLEAN ServerIsRemote
,
327 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
330 return STATUS_NOT_IMPLEMENTED
;
338 SeImpersonateClientEx(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
339 IN PETHREAD ServerThread OPTIONAL
)
342 return STATUS_NOT_IMPLEMENTED
;
350 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
351 IN PETHREAD ServerThread OPTIONAL
)
357 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
359 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
363 b
= ClientContext
->DirectAccessEffectiveOnly
;
366 if (ServerThread
== NULL
)
368 ServerThread
= PsGetCurrentThread();
371 PsImpersonateClient(ServerThread
,
372 ClientContext
->ClientToken
,
375 ClientContext
->SecurityQos
.ImpersonationLevel
);