You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
854 lines
24 KiB
854 lines
24 KiB
|
|
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
seclient.c
|
|
|
|
Abstract:
|
|
|
|
This module implements routines providing client impersonation to
|
|
communication session layers (such as LPC Ports).
|
|
|
|
WARNING: The following notes apply to the use of these services:
|
|
|
|
(1) No synchronization of operations to a security context block are
|
|
performed by these services. The caller of these services must
|
|
ensure that use of an individual security context block is
|
|
serialized to prevent simultaneous, incompatible updates.
|
|
|
|
(2) Any or all of these services may create, open, or operate on a
|
|
token object. This may result in a mutex being acquired at
|
|
MUTEXT_LEVEL_SE_TOKEN level. The caller must ensure that no
|
|
mutexes are held at levels that conflict with this action.
|
|
|
|
|
|
Author:
|
|
|
|
Jim Kelly (JimK) 1-August-1990
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
|
|
#pragma hdrstop
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
NTSTATUS
|
|
SepCreateClientSecurity(
|
|
IN PACCESS_TOKEN Token,
|
|
IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos,
|
|
IN BOOLEAN ServerIsRemote,
|
|
TOKEN_TYPE TokenType,
|
|
BOOLEAN ThreadEffectiveOnly,
|
|
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
|
|
OUT PSECURITY_CLIENT_CONTEXT ClientContext
|
|
);
|
|
#pragma alloc_text(PAGE,SepCreateClientSecurity)
|
|
#pragma alloc_text(PAGE,SeCreateClientSecurity)
|
|
#pragma alloc_text(PAGE,SeUpdateClientSecurity)
|
|
#pragma alloc_text(PAGE,SeImpersonateClient)
|
|
#pragma alloc_text(PAGE,SeImpersonateClientEx)
|
|
#pragma alloc_text(PAGE,SeCreateClientSecurityFromSubjectContext)
|
|
#endif
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Routines //
|
|
// //
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
NTSTATUS
|
|
SepCreateClientSecurity(
|
|
IN PACCESS_TOKEN Token,
|
|
IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos,
|
|
IN BOOLEAN ServerIsRemote,
|
|
TOKEN_TYPE TokenType,
|
|
BOOLEAN ThreadEffectiveOnly,
|
|
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
|
|
OUT PSECURITY_CLIENT_CONTEXT ClientContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
This routine creates a context block to represent the passed token. The token
|
|
is expected to be properly referenced when passed to the function. If the call
|
|
is unsuccessful, the caller is responsible to dereference the token. Also, if the
|
|
call succeeds but the caller requested SECURITY_STATIC_TRACKING, then we have duplicated
|
|
the token and the caller is again responsible to dereference the passed token.
|
|
|
|
Arguments
|
|
|
|
Token - The effective token for which the context is constructed.
|
|
|
|
ClientSecurityQos - Points to the security quality of service
|
|
parameters specified by the client for this communication
|
|
session.
|
|
|
|
ServerIsRemote - Provides an indication as to whether the session
|
|
this context block is being used for is an inter-system
|
|
session or intra-system session. This is reconciled with the
|
|
impersonation level of the client thread's token (in case the
|
|
client has a client of his own that didn't specify delegation).
|
|
|
|
TokenType - specifies the type of the passed token.
|
|
|
|
ThreadEffectiveOnly - if the token is an impersonation token, then this
|
|
is the thread's ImpersonationInfo->EffectiveOnly field value.
|
|
|
|
ImpersonationLevel - the impersonation level of the token.
|
|
|
|
ClientContext - Points to the client security context block to be
|
|
initialized.
|
|
|
|
Return Value
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PACCESS_TOKEN DuplicateToken;
|
|
|
|
PAGED_CODE();
|
|
|
|
if ( !VALID_IMPERSONATION_LEVEL(ClientSecurityQos->ImpersonationLevel) ) {
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Make sure the client is not trying to abuse use of a
|
|
// client of its own by attempting an invalid impersonation.
|
|
// Also set the ClientContext->DirectAccessEffectiveOnly flag
|
|
// appropriately if the impersonation is legitimate. The
|
|
// DirectAccessEffectiveOnly flag value will end up being ignored
|
|
// if STATIC mode is requested, but this is the most efficient
|
|
// place to calculate it, and we are optimizing for DYNAMIC mode.
|
|
//
|
|
|
|
if (TokenType == TokenImpersonation) {
|
|
|
|
if ( ClientSecurityQos->ImpersonationLevel > ImpersonationLevel) {
|
|
|
|
return STATUS_BAD_IMPERSONATION_LEVEL;
|
|
}
|
|
|
|
if ( SepBadImpersonationLevel(ImpersonationLevel,ServerIsRemote)) {
|
|
|
|
return STATUS_BAD_IMPERSONATION_LEVEL;
|
|
|
|
} else {
|
|
|
|
//
|
|
// TokenType is TokenImpersonation and the impersonation is legit.
|
|
// Set the DirectAccessEffectiveOnly flag to be the minimum of
|
|
// the current thread value and the caller specified value.
|
|
//
|
|
|
|
ClientContext->DirectAccessEffectiveOnly =
|
|
( (ThreadEffectiveOnly || (ClientSecurityQos->EffectiveOnly)) ?
|
|
TRUE : FALSE );
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// TokenType is TokenPrimary. In this case, the client specified
|
|
// EffectiveOnly value is always used.
|
|
//
|
|
|
|
ClientContext->DirectAccessEffectiveOnly =
|
|
ClientSecurityQos->EffectiveOnly;
|
|
}
|
|
|
|
//
|
|
// Copy the token if necessary (i.e., static tracking requested)
|
|
//
|
|
|
|
if (ClientSecurityQos->ContextTrackingMode == SECURITY_STATIC_TRACKING) {
|
|
|
|
ClientContext->DirectlyAccessClientToken = FALSE;
|
|
|
|
Status = SeCopyClientToken(
|
|
Token,
|
|
ClientSecurityQos->ImpersonationLevel,
|
|
KernelMode,
|
|
&DuplicateToken
|
|
);
|
|
|
|
Token = DuplicateToken;
|
|
|
|
//
|
|
// If there was an error, we're done.
|
|
//
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
} else {
|
|
|
|
ClientContext->DirectlyAccessClientToken = TRUE;
|
|
|
|
if (ServerIsRemote) {
|
|
//
|
|
// Get a copy of the client token's control information
|
|
// so that we can tell if it changes in the future.
|
|
//
|
|
|
|
SeGetTokenControlInformation( Token,
|
|
&ClientContext->ClientTokenControl
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ClientContext->SecurityQos.Length =
|
|
(ULONG)sizeof(SECURITY_QUALITY_OF_SERVICE);
|
|
|
|
ClientContext->SecurityQos.ImpersonationLevel =
|
|
ClientSecurityQos->ImpersonationLevel;
|
|
|
|
ClientContext->SecurityQos.ContextTrackingMode =
|
|
ClientSecurityQos->ContextTrackingMode;
|
|
|
|
ClientContext->SecurityQos.EffectiveOnly =
|
|
ClientSecurityQos->EffectiveOnly;
|
|
|
|
ClientContext->ServerIsRemote = ServerIsRemote;
|
|
|
|
ClientContext->ClientToken = Token;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
SeCreateClientSecurity (
|
|
IN PETHREAD ClientThread,
|
|
IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos,
|
|
IN BOOLEAN ServerIsRemote,
|
|
OUT PSECURITY_CLIENT_CONTEXT ClientContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service initializes a context block to represent a client's
|
|
security context. This may simply result in a reference to the
|
|
client's token, or may cause the client's token to be duplicated,
|
|
depending upon the security quality of service information specified.
|
|
|
|
NOTE
|
|
|
|
The code in this routine is optimized for DYNAMIC context
|
|
tracking. This is only mode in which direct access to a
|
|
caller's token is allowed, and the mode expected to be used
|
|
most often. STATIC context tracking always requires the
|
|
caller's token to be copied.
|
|
|
|
|
|
Arguments:
|
|
|
|
ClientThread - Points to the client's thread. This is used to
|
|
locate the client's security context (token).
|
|
|
|
ClientSecurityQos - Points to the security quality of service
|
|
parameters specified by the client for this communication
|
|
session.
|
|
|
|
ServerIsRemote - Provides an indication as to whether the session
|
|
this context block is being used for is an inter-system
|
|
session or intra-system session. This is reconciled with the
|
|
impersonation level of the client thread's token (in case the
|
|
client has a client of his own that didn't specify delegation).
|
|
|
|
ClientContext - Points to the client security context block to be
|
|
initialized.
|
|
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - The service completed successfully.
|
|
|
|
STATUS_BAD_IMPERSONATION_LEVEL - The client is currently
|
|
impersonating either an Anonymous or Identification level
|
|
token, which can not be passed on for use by another server.
|
|
This status may also be returned if the security context
|
|
block is for an inter-system communication session and the
|
|
client thread is impersonating a client of its own using
|
|
other than delegation impersonation level.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PACCESS_TOKEN Token;
|
|
TOKEN_TYPE TokenType;
|
|
BOOLEAN ThreadEffectiveOnly;
|
|
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
|
|
PACCESS_TOKEN DuplicateToken;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Gain access to the client thread's effective token
|
|
//
|
|
|
|
Token = PsReferenceEffectiveToken(
|
|
ClientThread,
|
|
&TokenType,
|
|
&ThreadEffectiveOnly,
|
|
&ImpersonationLevel
|
|
);
|
|
|
|
|
|
Status = SepCreateClientSecurity(
|
|
Token,
|
|
ClientSecurityQos,
|
|
ServerIsRemote,
|
|
TokenType,
|
|
ThreadEffectiveOnly,
|
|
ImpersonationLevel,
|
|
ClientContext );
|
|
|
|
//
|
|
// If failed, or if a token was copied internally, then deref our token.
|
|
//
|
|
|
|
if ((!NT_SUCCESS( Status )) || (ClientSecurityQos->ContextTrackingMode == SECURITY_STATIC_TRACKING)) {
|
|
|
|
ObDereferenceObject( Token );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
#if SAVE_FOR_PRODUCT_2
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
SeUpdateClientSecurity(
|
|
IN PETHREAD ClientThread,
|
|
IN OUT PSECURITY_CLIENT_CONTEXT ClientContext,
|
|
OUT PBOOLEAN ChangesMade,
|
|
OUT PBOOLEAN NewToken
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service is used to update a client security context block
|
|
based upon the client's current security context and the security
|
|
quality of service parameters specified when the security block
|
|
was created. If the SecurityContextTracking specified when the
|
|
context block was created indicated static tracking, then no
|
|
change will be made to the context block. Otherwise, a change may
|
|
be made.
|
|
|
|
|
|
An indication of whether any changes were made is returned to the
|
|
caller. This may be used by communication session layers
|
|
providing remote communications to decide whether or not to send
|
|
an updated security context to the remote server's node. It may
|
|
also be used by a server session layer to decide whether or not to
|
|
inform a server that a previously obtained handle to a token no
|
|
longer represents the current security context.
|
|
|
|
|
|
Arguments:
|
|
|
|
ClientThread - Points to the client's thread. This is used to
|
|
locate the security context to synchronize with.
|
|
|
|
ClientContext - Points to client security context block to be
|
|
updated.
|
|
|
|
ChangesMade - Receives an indication as to whether any changes to
|
|
the client's security context had been made since the last
|
|
time the security context block was synchronized. This will
|
|
always be FALSE if static security tracking is in effect.
|
|
|
|
NewToken - Receives an indication as to whether the same token
|
|
is used to represent the client's current context, or whether
|
|
the context now points to a new token. If the client's token
|
|
is directly referenced, then this indicates the client changed
|
|
tokens (and the new one is now referenced). If the client's token
|
|
isn't directly referenced, then this indicates it was necessary
|
|
to delete one token and create another one. This will always be
|
|
FALSE if static security tracking is in effect.
|
|
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - The service completed successfully.
|
|
|
|
STATUS_BAD_IMPERSONATION_LEVEL - The client is currently
|
|
impersonating either an Anonymous or Identification level
|
|
token, which can not be passed on for use by another server.
|
|
This status may also be returned if the security context
|
|
block is for an inter-system communication session and the
|
|
client thread is impersonating a client of its own using
|
|
other than delegation impersonation level.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PACCESS_TOKEN Token;
|
|
TOKEN_TYPE TokenType;
|
|
BOOLEAN ThreadEffectiveOnly;
|
|
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
|
|
PACCESS_TOKEN DuplicateToken;
|
|
TOKEN_CONTROL TokenControl;
|
|
|
|
PAGED_CODE();
|
|
|
|
if (ClientContext->SecurityQos.ContextTrackingMode ==
|
|
SECURITY_STATIC_TRACKING) {
|
|
|
|
(*NewToken) = FALSE;
|
|
(*ChangesMade) = FALSE;
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
// //
|
|
// Optimize for the directly accessed token //
|
|
// //
|
|
//////////////////////////////////////////////
|
|
|
|
|
|
|
|
//
|
|
// Gain access to the client thread's effective token
|
|
//
|
|
|
|
Token = PsReferenceEffectiveToken(
|
|
ClientThread,
|
|
&TokenType,
|
|
&ThreadEffectiveOnly,
|
|
&ImpersonationLevel
|
|
);
|
|
|
|
|
|
|
|
//
|
|
// See if the token is the same.
|
|
//
|
|
|
|
|
|
SeGetTokenControlInformation( Token, &TokenControl );
|
|
|
|
if ( SeSameToken( &TokenControl,
|
|
&ClientContext->ClientTokenControl) ) {
|
|
|
|
(*NewToken = FALSE);
|
|
|
|
|
|
//
|
|
// Same token.
|
|
// Is it unmodified?
|
|
//
|
|
|
|
if ( (TokenControl.ModifiedId.HighPart ==
|
|
ClientContext->ClientTokenControl.ModifiedId.HighPart) &&
|
|
(TokenControl.ModifiedId.LowPart ==
|
|
ClientContext->ClientTokenControl.ModifiedId.LowPart) ) {
|
|
|
|
//
|
|
// Yup. No changes necessary.
|
|
//
|
|
|
|
if (TokenType == TokenPrimary) {
|
|
PsDereferencePrimaryTokenEx(THREAD_TO_PROCESS(ClientThread), Token );
|
|
} else {
|
|
PsDereferenceImpersonationToken( Token );
|
|
}
|
|
|
|
(*ChangesMade) = FALSE;
|
|
return STATUS_SUCCESS;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Same token, but it has been modified.
|
|
// If we are directly accessing the token, then we can
|
|
// just indicate it has changed and return. Otherwise
|
|
// we have to actually update our copy of the token.
|
|
//
|
|
|
|
(*ChangesMade) = TRUE;
|
|
if (ClientContext->DirectlyAccessClientToken) {
|
|
|
|
if (TokenType == TokenPrimary) {
|
|
PsDereferencePrimaryTokenEx(THREAD_TO_PROCESS(ClientThread), Token);
|
|
} else {
|
|
PsDereferenceImpersonationToken (Token);
|
|
}
|
|
|
|
//
|
|
// Save the new modified count and whether or not
|
|
// the token is for effective use only
|
|
//
|
|
|
|
ClientContext->ClientTokenControl.ModifiedId =
|
|
TokenControl.ModifiedId;
|
|
ClientContext->DirectAccessEffectiveOnly =
|
|
( (ThreadEffectiveOnly || (ClientContext->SecurityQos.EffectiveOnly)) ?
|
|
TRUE : FALSE );
|
|
|
|
return STATUS_SUCCESS;
|
|
} else {
|
|
|
|
//
|
|
// There is a possibility for a fair performance gain here
|
|
// by just updating the existing token to match its origin.
|
|
// However, it isn't clear that this case is ever really
|
|
// used, so the effort and complexity is avoided at this time.
|
|
// If it is found that this case is used, then this code
|
|
// can be added.
|
|
//
|
|
// Instead, we just fall through to the case of completely
|
|
// different tokens below.
|
|
//
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Not the same token, or the same token has changed.
|
|
// In either case, we're going to create a new copy of the token
|
|
// and dump the old copy.
|
|
//
|
|
// Make sure the current impersonation situation is legitimate.
|
|
//
|
|
|
|
(*NewToken) = TRUE;
|
|
(*ChangesMade) = TRUE;
|
|
if (TokenType == TokenImpersonation) {
|
|
if ( SepBadImpersonationLevel(ImpersonationLevel,
|
|
ClientContext->ServerIsRemote)) {
|
|
|
|
PsDereferenceImpersonationToken(Token );
|
|
return STATUS_BAD_IMPERSONATION_LEVEL;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Copy the token
|
|
//
|
|
|
|
|
|
|
|
Status = SeCopyClientToken(
|
|
Token,
|
|
ClientContext->SecurityQos.ImpersonationLevel,
|
|
KernelMode,
|
|
&DuplicateToken
|
|
);
|
|
|
|
|
|
//
|
|
// No longer need the pointer to the client's effective token
|
|
//
|
|
|
|
if (TokenType == TokenPrimary) {
|
|
PsDereferencePrimaryToken( Token );
|
|
} else {
|
|
PsDereferenceImpersonationToken(Token );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// If there was an error, we're done.
|
|
//
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
|
|
//
|
|
// Otherwise, replace the current token with the new one.
|
|
//
|
|
|
|
Token = ClientContext->ClientToken;
|
|
ClientContext->ClientToken = DuplicateToken;
|
|
ClientContext->DirectlyAccessClientToken = FALSE;
|
|
|
|
if (SeTokenType( Token ) == TokenPrimary) {
|
|
PsDereferencePrimaryToken( Token );
|
|
} else {
|
|
PsDereferenceImpersonationToken( Token );
|
|
}
|
|
|
|
|
|
//
|
|
// Get a copy of the current token's control information
|
|
// so that we can tell if it changes in the future.
|
|
//
|
|
|
|
SeGetTokenControlInformation( DuplicateToken,
|
|
&ClientContext->ClientTokenControl
|
|
);
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
VOID
|
|
SeImpersonateClient(
|
|
IN PSECURITY_CLIENT_CONTEXT ClientContext,
|
|
IN PETHREAD ServerThread OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service is used to cause the calling thread to impersonate a
|
|
client. The client security context in ClientContext is assumed to
|
|
be up to date.
|
|
|
|
|
|
Arguments:
|
|
|
|
ClientContext - Points to client security context block.
|
|
|
|
ServerThread - (Optional) Specifies the thread which is to be made to
|
|
impersonate the client. If not specified, the calling thread is
|
|
used.
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
#if DBG
|
|
DbgPrint("SE: Obsolete call: SeImpersonateClient\n");
|
|
#endif
|
|
|
|
(VOID) SeImpersonateClientEx( ClientContext, ServerThread );
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SeImpersonateClientEx(
|
|
IN PSECURITY_CLIENT_CONTEXT ClientContext,
|
|
IN PETHREAD ServerThread OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service is used to cause the calling thread to impersonate a
|
|
client. The client security context in ClientContext is assumed to
|
|
be up to date.
|
|
|
|
|
|
Arguments:
|
|
|
|
ClientContext - Points to client security context block.
|
|
|
|
ServerThread - (Optional) Specifies the thread which is to be made to
|
|
impersonate the client. If not specified, the calling thread is
|
|
used.
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
|
|
BOOLEAN EffectiveValueToUse;
|
|
PETHREAD Thread;
|
|
NTSTATUS Status ;
|
|
|
|
PAGED_CODE();
|
|
|
|
if (ClientContext->DirectlyAccessClientToken) {
|
|
EffectiveValueToUse = ClientContext->DirectAccessEffectiveOnly;
|
|
} else {
|
|
EffectiveValueToUse = ClientContext->SecurityQos.EffectiveOnly;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// if a ServerThread wasn't specified, then default to the current
|
|
// thread.
|
|
//
|
|
|
|
if (!ARGUMENT_PRESENT(ServerThread)) {
|
|
Thread = PsGetCurrentThread();
|
|
} else {
|
|
Thread = ServerThread;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Assign the context to the calling thread
|
|
//
|
|
|
|
Status = PsImpersonateClient( Thread,
|
|
ClientContext->ClientToken,
|
|
TRUE,
|
|
EffectiveValueToUse,
|
|
ClientContext->SecurityQos.ImpersonationLevel
|
|
);
|
|
|
|
return Status ;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SeCreateClientSecurityFromSubjectContext (
|
|
IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
|
|
IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos,
|
|
IN BOOLEAN ServerIsRemote,
|
|
OUT PSECURITY_CLIENT_CONTEXT ClientContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service initializes a context block to represent a client's
|
|
security context. This may simply result in a reference to the
|
|
client's token, or may cause the client's token to be duplicated,
|
|
depending upon the security quality of service information specified.
|
|
|
|
NOTE
|
|
|
|
The code in this routine is optimized for DYNAMIC context
|
|
tracking. This is only mode in which direct access to a
|
|
caller's token is allowed, and the mode expected to be used
|
|
most often. STATIC context tracking always requires the
|
|
caller's token to be copied.
|
|
|
|
|
|
Arguments:
|
|
|
|
SubjectContext - Points to the SubjectContext that should serve
|
|
as the basis for this client context.
|
|
|
|
ClientSecurityQos - Points to the security quality of service
|
|
parameters specified by the client for this communication
|
|
session.
|
|
|
|
ServerIsRemote - Provides an indication as to whether the session
|
|
this context block is being used for is an inter-system
|
|
session or intra-system session. This is reconciled with the
|
|
impersonation level of the client thread's token (in case the
|
|
client has a client of his own that didn't specify delegation).
|
|
|
|
ClientContext - Points to the client security context block to be
|
|
initialized.
|
|
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - The service completed successfully.
|
|
|
|
STATUS_BAD_IMPERSONATION_LEVEL - The client is currently
|
|
impersonating either an Anonymous or Identification level
|
|
token, which can not be passed on for use by another server.
|
|
This status may also be returned if the security context
|
|
block is for an inter-system communication session and the
|
|
client thread is impersonating a client of its own using
|
|
other than delegation impersonation level.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PACCESS_TOKEN Token;
|
|
TOKEN_TYPE Type;
|
|
BOOLEAN ThreadEffectiveOnly;
|
|
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
|
|
PACCESS_TOKEN DuplicateToken;
|
|
|
|
PAGED_CODE();
|
|
|
|
Token = SeQuerySubjectContextToken(
|
|
SubjectContext
|
|
);
|
|
|
|
ObReferenceObject( Token );
|
|
|
|
if ( SubjectContext->ClientToken )
|
|
{
|
|
Type = TokenImpersonation ;
|
|
}
|
|
else
|
|
{
|
|
Type = TokenPrimary ;
|
|
}
|
|
|
|
Status = SepCreateClientSecurity(
|
|
Token,
|
|
ClientSecurityQos,
|
|
ServerIsRemote,
|
|
Type,
|
|
FALSE,
|
|
SubjectContext->ImpersonationLevel,
|
|
ClientContext
|
|
);
|
|
|
|
//
|
|
// If failed, or if a token was copied internally, then deref our token.
|
|
//
|
|
|
|
if ((!NT_SUCCESS( Status )) || (ClientSecurityQos->ContextTrackingMode == SECURITY_STATIC_TRACKING)) {
|
|
ObDereferenceObject( Token );
|
|
}
|
|
|
|
return Status ;
|
|
}
|
|
|