windows-nt/Source/XPSP1/NT/ds/security/protocols/schannel/lsa/userctxt.c
2020-09-26 16:20:57 +08:00

376 lines
8.1 KiB
C

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: userctxt.c
//
// Contents:
//
// Classes:
//
// Functions:
//
// History: 10-10-96 RichardW Created
//
//----------------------------------------------------------------------------
#include "sslp.h"
#define SCHANNEL_USERLIST_COUNT (16) // count of lists
#define SCHANNEL_USERLIST_LOCK_COUNT (2) // count of locks
RTL_RESOURCE SslContextLock[ SCHANNEL_USERLIST_LOCK_COUNT ];
LIST_ENTRY SslContextList[ SCHANNEL_USERLIST_COUNT ] ;
ULONG
HandleToListIndex(
ULONG_PTR ContextHandle
);
ULONG
__inline
ListIndexToLockIndex(
ULONG ListIndex
);
//+---------------------------------------------------------------------------
//
// Function: SslInitContextManager
//
// Synopsis: Initializes the context manager controls
//
// History: 10-10-96 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL
SslInitContextManager(
VOID
)
{
ULONG Index;
NTSTATUS Status = STATUS_SUCCESS;
for( Index=0 ; Index < SCHANNEL_USERLIST_LOCK_COUNT ; Index++ )
{
__try {
RtlInitializeResource (&SslContextLock[Index]);
} __except(EXCEPTION_EXECUTE_HANDLER)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
}
if( !NT_SUCCESS(Status) )
{
DebugLog(( DEB_ERROR, "SslInitContextManager failed!\n" ));
return FALSE;
}
for( Index = 0 ; Index < SCHANNEL_USERLIST_COUNT ; Index++ )
{
InitializeListHead( &SslContextList[Index] );
}
return( TRUE );
}
#if 0
VOID
SslFreeUserContextElements(PSPContext pContext)
{
if(pContext->hReadKey)
{
if(!CryptDestroyKey(pContext->hReadKey))
{
SP_LOG_RESULT(GetLastError());
}
}
pContext->hReadKey = 0;
if(pContext->hReadMAC)
{
if(!CryptDestroyKey(pContext->hReadMAC))
{
SP_LOG_RESULT(GetLastError());
}
}
pContext->hReadMAC = 0;
if(pContext->hWriteKey)
{
if(!CryptDestroyKey(pContext->hWriteKey))
{
SP_LOG_RESULT(GetLastError());
}
}
pContext->hWriteKey = 0;
if(pContext->hWriteMAC)
{
if(!CryptDestroyKey(pContext->hWriteMAC))
{
SP_LOG_RESULT(GetLastError());
}
}
pContext->hWriteMAC = 0;
}
#endif
SECURITY_STATUS
SslAddUserContext(
IN LSA_SEC_HANDLE LsaHandle,
IN HANDLE Token, // optional
IN PSecBuffer ContextData,
IN BOOL fImportedContext)
{
DWORD Size;
PSSL_USER_CONTEXT Context ;
SP_STATUS Status ;
ULONG ListIndex;
ULONG LockIndex;
DebugLog(( DEB_TRACE, "SslAddUserContext: 0x%p\n", LsaHandle ));
if ( ContextData->cbBuffer < sizeof( SPPackedContext ) )
{
return( SEC_E_INVALID_TOKEN );
}
if(!fImportedContext)
{
Context = SslFindUserContext( LsaHandle );
if ( Context )
{
DebugLog(( DEB_TRACE, "Replacing existing context!\n" ));
// Destroy elements of existing context.
LsaContextDelete(Context->pContext);
SPExternalFree(Context->pContext);
Context->pContext = NULL;
Status = SPContextDeserialize( ContextData->pvBuffer,
&Context->pContext);
if(Status != PCT_ERR_OK)
{
return SP_LOG_RESULT(SEC_E_DECRYPT_FAILURE);
}
return( SEC_E_OK );
}
}
Context = LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT,
sizeof( SSL_USER_CONTEXT ));
if ( !Context )
{
return( SEC_E_INSUFFICIENT_MEMORY );
}
Status = SPContextDeserialize( ContextData->pvBuffer,
&Context->pContext);
if(Status != PCT_ERR_OK)
{
LocalFree(Context);
return SP_LOG_RESULT(SEC_E_DECRYPT_FAILURE);
}
if(ARGUMENT_PRESENT(Token))
{
Context->pContext->RipeZombie->hLocator = (HLOCATOR)Token;
}
Context->LsaHandle = LsaHandle ;
Context->Align = ContextData->cbBuffer ;
ListIndex = HandleToListIndex( LsaHandle );
LockIndex = ListIndexToLockIndex( ListIndex );
RtlAcquireResourceExclusive( &SslContextLock[LockIndex], TRUE );
InsertTailList( &SslContextList[ListIndex], &Context->List );
RtlReleaseResource( &SslContextLock[LockIndex] );
return( SEC_E_OK );
}
PSSL_USER_CONTEXT
SslReferenceUserContext(
IN LSA_SEC_HANDLE LsaHandle,
IN BOOLEAN Delete
)
{
PLIST_ENTRY List ;
PSSL_USER_CONTEXT Context = NULL ;
ULONG ListIndex;
ULONG LockIndex;
ListIndex = HandleToListIndex( LsaHandle );
LockIndex = ListIndexToLockIndex( ListIndex );
if( !Delete )
{
RtlAcquireResourceShared( &SslContextLock[LockIndex], TRUE );
} else {
RtlAcquireResourceExclusive( &SslContextLock[LockIndex], TRUE );
}
List = SslContextList[ListIndex].Flink ;
while ( List != &SslContextList[ListIndex] )
{
Context = CONTAINING_RECORD( List, SSL_USER_CONTEXT, List.Flink );
if ( Context->LsaHandle == LsaHandle )
{
if( Delete )
{
RemoveEntryList( &Context->List );
}
break;
}
Context = NULL ;
List = List->Flink ;
}
RtlReleaseResource( &SslContextLock[LockIndex] );
return( Context );
}
PSSL_USER_CONTEXT
SslFindUserContext(
IN LSA_SEC_HANDLE LsaHandle
)
{
return SslReferenceUserContext( LsaHandle, FALSE );
}
PSSL_USER_CONTEXT
SslFindUserContextEx(
IN PCRED_THUMBPRINT pThumbprint
)
{
PLIST_ENTRY List ;
PSSL_USER_CONTEXT Context = NULL ;
ULONG ListIndex;
ULONG LockIndex;
DebugLog(( DEB_TRACE, "SslFindUserContextEx: \n"));
for (ListIndex = 0 ; ListIndex < SCHANNEL_USERLIST_COUNT ; ListIndex++)
{
LockIndex = ListIndexToLockIndex( ListIndex );
RtlAcquireResourceShared( &SslContextLock[LockIndex], TRUE );
List = SslContextList[ListIndex].Flink ;
while ( List != &SslContextList[ListIndex] )
{
Context = CONTAINING_RECORD( List, SSL_USER_CONTEXT, List.Flink );
if(Context->pContext != NULL &&
IsSameThumbprint(pThumbprint, &Context->pContext->ContextThumbprint))
{
RtlReleaseResource( &SslContextLock[LockIndex] );
goto done;
}
List = List->Flink ;
}
RtlReleaseResource( &SslContextLock[LockIndex] );
}
Context = NULL ;
done:
return( Context );
}
VOID
SslDeleteUserContext(
IN LSA_SEC_HANDLE LsaHandle
)
{
PSSL_USER_CONTEXT Context ;
Context = SslReferenceUserContext( LsaHandle, TRUE );
if ( Context )
{
DebugLog(( DEB_TRACE, "Deleting user mode context %x, handle = %x\n",
Context, LsaHandle ));
LsaContextDelete(Context->pContext);
SPExternalFree(Context->pContext);
LocalFree( Context );
}
else
{
DebugLog(( DEB_TRACE, "No context found for handle %x\n", LsaHandle ));
}
}
ULONG
HandleToListIndex(
ULONG_PTR ContextHandle
)
{
ULONG Number ;
ULONG Hash;
ULONG HashFinal;
ASSERT( (SCHANNEL_USERLIST_COUNT != 0) );
ASSERT( (SCHANNEL_USERLIST_COUNT & 1) == 0 );
Number = (ULONG)ContextHandle;
Hash = Number;
Hash += Number >> 8;
Hash += Number >> 16;
Hash += Number >> 24;
HashFinal = Hash;
HashFinal += Hash >> 4;
//
// insure power of two if not one.
//
return ( HashFinal & (SCHANNEL_USERLIST_COUNT-1) ) ;
}
ULONG
__inline
ListIndexToLockIndex(
ULONG ListIndex
)
{
ASSERT( (SCHANNEL_USERLIST_LOCK_COUNT) != 0 );
ASSERT( (SCHANNEL_USERLIST_LOCK_COUNT & 1) == 0 );
//
// insure power of two if not one.
//
return ( ListIndex & (SCHANNEL_USERLIST_LOCK_COUNT-1) );
}