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
;
35 /* Save the unique ID */
36 SubjectContext
->ProcessAuditId
= Process
->UniqueProcessId
;
38 /* Check if we have a thread */
41 /* We don't, so no token */
42 SubjectContext
->ClientToken
= NULL
;
46 /* Get the impersonation token */
47 SubjectContext
->ClientToken
= PsReferenceImpersonationToken(Thread
,
50 &SubjectContext
->ImpersonationLevel
);
53 /* Get the primary token */
54 SubjectContext
->PrimaryToken
= PsReferencePrimaryToken(Process
);
62 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext
)
64 /* Call the extended API */
65 SeCaptureSubjectContextEx(PsGetCurrentThread(),
66 PsGetCurrentProcess(),
75 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
79 KeEnterCriticalRegion();
80 ExAcquireResourceExclusiveLite(&SepSubjectContextLock
, TRUE
);
88 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
92 ExReleaseResourceLite(&SepSubjectContextLock
);
93 KeLeaveCriticalRegion();
101 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
105 if (SubjectContext
->PrimaryToken
!= NULL
)
107 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, SubjectContext
->PrimaryToken
);
110 if (SubjectContext
->ClientToken
!= NULL
)
112 ObDereferenceObject(SubjectContext
->ClientToken
);
121 SeCreateAccessStateEx(IN PETHREAD Thread
,
122 IN PEPROCESS Process
,
123 IN OUT PACCESS_STATE AccessState
,
124 IN PAUX_ACCESS_DATA AuxData
,
125 IN ACCESS_MASK Access
,
126 IN PGENERIC_MAPPING GenericMapping
)
128 ACCESS_MASK AccessMask
= Access
;
132 /* Map the Generic Acess to Specific Access if we have a Mapping */
133 if ((Access
& GENERIC_ACCESS
) && (GenericMapping
))
135 RtlMapGenericMask(&AccessMask
, GenericMapping
);
138 /* Initialize the Access State */
139 RtlZeroMemory(AccessState
, sizeof(ACCESS_STATE
));
141 /* Capture the Subject Context */
142 SeCaptureSubjectContextEx(Thread
,
144 &AccessState
->SubjectSecurityContext
);
146 /* Set Access State Data */
147 AccessState
->AuxData
= AuxData
;
148 AccessState
->RemainingDesiredAccess
= AccessMask
;
149 AccessState
->OriginalDesiredAccess
= AccessMask
;
150 ExpAllocateLocallyUniqueId(&AccessState
->OperationID
);
152 /* Get the Token to use */
153 Token
= AccessState
->SubjectSecurityContext
.ClientToken
?
154 (PTOKEN
)&AccessState
->SubjectSecurityContext
.ClientToken
:
155 (PTOKEN
)&AccessState
->SubjectSecurityContext
.PrimaryToken
;
157 /* Check for Travers Privilege */
158 if (Token
->TokenFlags
& TOKEN_HAS_TRAVERSE_PRIVILEGE
)
160 /* Preserve the Traverse Privilege */
161 AccessState
->Flags
= TOKEN_HAS_TRAVERSE_PRIVILEGE
;
164 /* Set the Auxiliary Data */
165 AuxData
->PrivilegeSet
= (PPRIVILEGE_SET
)((ULONG_PTR
)AccessState
+
166 FIELD_OFFSET(ACCESS_STATE
,
168 if (GenericMapping
) AuxData
->GenericMapping
= *GenericMapping
;
171 return STATUS_SUCCESS
;
179 SeCreateAccessState(IN OUT PACCESS_STATE AccessState
,
180 IN PAUX_ACCESS_DATA AuxData
,
181 IN ACCESS_MASK Access
,
182 IN PGENERIC_MAPPING GenericMapping
)
186 /* Call the extended API */
187 return SeCreateAccessStateEx(PsGetCurrentThread(),
188 PsGetCurrentProcess(),
200 SeDeleteAccessState(IN PACCESS_STATE AccessState
)
202 PAUX_ACCESS_DATA AuxData
;
205 /* Get the Auxiliary Data */
206 AuxData
= AccessState
->AuxData
;
208 /* Deallocate Privileges */
209 if (AccessState
->PrivilegesAllocated
) ExFreePool(AuxData
->PrivilegeSet
);
211 /* Deallocate Name and Type Name */
212 if (AccessState
->ObjectName
.Buffer
)
214 ExFreePool(AccessState
->ObjectName
.Buffer
);
216 if (AccessState
->ObjectTypeName
.Buffer
)
218 ExFreePool(AccessState
->ObjectTypeName
.Buffer
);
221 /* Release the Subject Context */
222 SeReleaseSubjectContext(&AccessState
->SubjectSecurityContext
);
230 SeSetAccessStateGenericMapping(IN PACCESS_STATE AccessState
,
231 IN PGENERIC_MAPPING GenericMapping
)
235 /* Set the Generic Mapping */
236 ((PAUX_ACCESS_DATA
)AccessState
->AuxData
)->GenericMapping
= *GenericMapping
;
244 SeCreateClientSecurity(IN PETHREAD Thread
,
245 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
246 IN BOOLEAN RemoteClient
,
247 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
249 TOKEN_TYPE TokenType
;
250 BOOLEAN ThreadEffectiveOnly
;
251 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
254 PACCESS_TOKEN NewToken
;
257 Token
= PsReferenceEffectiveToken(Thread
,
259 &ThreadEffectiveOnly
,
260 &ImpersonationLevel
);
261 if (TokenType
!= TokenImpersonation
)
263 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
267 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
269 if (Token
) ObDereferenceObject(Token
);
270 return STATUS_BAD_IMPERSONATION_LEVEL
;
273 if ((ImpersonationLevel
== SecurityAnonymous
) ||
274 (ImpersonationLevel
== SecurityIdentification
) ||
275 ((RemoteClient
) && (ImpersonationLevel
!= SecurityDelegation
)))
277 if (Token
) ObDereferenceObject(Token
);
278 return STATUS_BAD_IMPERSONATION_LEVEL
;
281 ClientContext
->DirectAccessEffectiveOnly
= ((ThreadEffectiveOnly
) ||
282 (Qos
->EffectiveOnly
)) ?
286 if (Qos
->ContextTrackingMode
== SECURITY_STATIC_TRACKING
)
288 ClientContext
->DirectlyAccessClientToken
= FALSE
;
289 Status
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
290 if (!NT_SUCCESS(Status
)) return Status
;
294 ClientContext
->DirectlyAccessClientToken
= TRUE
;
295 if (RemoteClient
!= FALSE
)
298 SeGetTokenControlInformation(Token
,
299 &ClientContext
->ClientTokenControl
);
306 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
307 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
308 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
309 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
310 ClientContext
->ServerIsRemote
= RemoteClient
;
311 ClientContext
->ClientToken
= NewToken
;
312 return STATUS_SUCCESS
;
320 SeCreateClientSecurityFromSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
321 IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos
,
322 IN BOOLEAN ServerIsRemote
,
323 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
326 return STATUS_NOT_IMPLEMENTED
;
334 SeImpersonateClientEx(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
335 IN PETHREAD ServerThread OPTIONAL
)
338 return STATUS_NOT_IMPLEMENTED
;
346 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
347 IN PETHREAD ServerThread OPTIONAL
)
353 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
355 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
359 b
= ClientContext
->DirectAccessEffectiveOnly
;
361 if (ServerThread
== NULL
)
363 ServerThread
= PsGetCurrentThread();
365 PsImpersonateClient(ServerThread
,
366 ClientContext
->ClientToken
,
369 ClientContext
->SecurityQos
.ImpersonationLevel
);