//+--------------------------------------------------------------------------- // // 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) { 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) ); }