|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1997.
//
// File: ctxtapi.c
//
// Contents: LSA Mode Context API
//
// Classes:
//
// Functions:
//
// History: 2-24-97 RichardW Created
//
//----------------------------------------------------------------------------
#include "xtcbpkg.h"
#include "md5.h"
typedef struct _XTCB_ATTR_MAP { ULONG Request ; ULONG Return ; } XTCB_ATTR_MAP ;
XTCB_ATTR_MAP AcceptMap[] = { { ASC_REQ_DELEGATE, ASC_RET_DELEGATE }, { ASC_REQ_MUTUAL_AUTH, ASC_RET_MUTUAL_AUTH }, { ASC_REQ_REPLAY_DETECT, ASC_RET_REPLAY_DETECT }, { ASC_REQ_SEQUENCE_DETECT, ASC_RET_SEQUENCE_DETECT }, { ASC_REQ_CONFIDENTIALITY, ASC_RET_CONFIDENTIALITY }, { ASC_REQ_ALLOCATE_MEMORY, ASC_RET_ALLOCATED_MEMORY }, { ASC_REQ_CONNECTION, ASC_RET_CONNECTION }, { ASC_REQ_INTEGRITY, ASC_RET_INTEGRITY } };
XTCB_ATTR_MAP InitMap[] = { { ISC_REQ_DELEGATE, ISC_RET_DELEGATE }, { ISC_REQ_MUTUAL_AUTH, ISC_RET_MUTUAL_AUTH }, { ISC_REQ_SEQUENCE_DETECT, ISC_RET_MUTUAL_AUTH }, { ISC_REQ_REPLAY_DETECT, ISC_RET_REPLAY_DETECT }, { ISC_REQ_CONFIDENTIALITY, ISC_RET_CONFIDENTIALITY }, { ISC_REQ_ALLOCATE_MEMORY, ISC_RET_ALLOCATED_MEMORY }, { ISC_REQ_INTEGRITY, ISC_RET_INTEGRITY } };
ULONG XtcbMapAttributes( ULONG Input, BOOL Init ) { int i; ULONG Result = 0 ;
if ( Init ) { for ( i = 0 ; i < sizeof( InitMap ) / sizeof( XTCB_ATTR_MAP ) ; i++ ) { if ( InitMap[i].Request & Input ) { Result |= InitMap[i].Return ; } } } else { for ( i = 0 ; i < sizeof( AcceptMap ) / sizeof( XTCB_ATTR_MAP ) ; i++ ) { if ( AcceptMap[i].Request & Input ) { Result |= AcceptMap[i].Return ; } } }
return Result ; }
//+---------------------------------------------------------------------------
//
// Function: XtcbGetState
//
// Synopsis: Translates handles to their structures, and pulls out the
// interesting bits of the input and output buffers
//
// Arguments: [dwCredHandle] --
// [dwCtxtHandle] --
// [pInput] --
// [pOutput] --
// [Client] --
// [pContext] --
// [pCredHandle] --
// [pInToken] --
// [pOutToken] --
//
// History: 3-05-97 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS XtcbGetState( LSA_SEC_HANDLE dwCredHandle, LSA_SEC_HANDLE dwCtxtHandle, PSecBufferDesc pInput, PSecBufferDesc pOutput, BOOL Client, PXTCB_CONTEXT * pContext, PXTCB_CRED_HANDLE * pCredHandle, PSecBuffer * pInToken, PSecBuffer * pOutToken) { SECURITY_STATUS scRet; PXTCB_CONTEXT Context ; PXTCB_CRED_HANDLE CredHandle ; PSecBuffer OutToken ; PSecBuffer InToken ; ULONG i;
if ( dwCtxtHandle ) { Context = (PXTCB_CONTEXT) dwCtxtHandle ;
if ( !XtcbRefContextRecord( Context ) ) { return SEC_E_INVALID_HANDLE ; }
CredHandle = (PXTCB_CRED_HANDLE) Context->CredHandle ; } else { CredHandle = (PXTCB_CRED_HANDLE) dwCredHandle ;
if ( !CredHandle ) { return SEC_E_INVALID_HANDLE ; }
Context = XtcbCreateContextRecord( (Client ? XtcbContextClient : XtcbContextServer), CredHandle );
if ( !Context ) { return SEC_E_INSUFFICIENT_MEMORY ; } }
//
// Find the output token buffer:
//
OutToken = NULL ;
for ( i = 0 ; i < pOutput->cBuffers ; i++ ) { if ( (pOutput->pBuffers[i].BufferType & (~SECBUFFER_ATTRMASK)) == SECBUFFER_TOKEN ) { OutToken = &pOutput->pBuffers[i] ; LsaTable->MapBuffer( OutToken, OutToken ); break; } }
//
// Find the input token buffer:
//
InToken = NULL ;
for ( i = 0 ; i < pInput->cBuffers ; i++ ) { if ( (pInput->pBuffers[i].BufferType & (~SECBUFFER_ATTRMASK)) == SECBUFFER_TOKEN ) { InToken = &pInput->pBuffers[i] ; LsaTable->MapBuffer( InToken, InToken ); break; } }
*pContext = Context ; *pCredHandle = CredHandle ; *pInToken = InToken ; *pOutToken = OutToken ;
return SEC_E_OK ; }
//+---------------------------------------------------------------------------
//
// Function: XtcbInitLsaModeContext
//
// Synopsis: Creates a client side context and blob
//
// Arguments: [dwCredHandle] --
// [dwCtxtHandle] --
// [pszTargetName] --
// [fContextReq] --
// [TargetDataRep] --
// [pInput] --
// [pdwNewContext] --
// [pOutput] --
// [pfContextAttr] --
// [ptsExpiry] --
// [pfMapContext] --
// [pContextData] --
//
// History: 8-15-98 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY XtcbInitLsaModeContext( LSA_SEC_HANDLE dwCredHandle, LSA_SEC_HANDLE dwCtxtHandle, PSECURITY_STRING TargetName, ULONG fContextReq, ULONG TargetDataRep, PSecBufferDesc pInput, PLSA_SEC_HANDLE pdwNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry, PBYTE pfMapContext, PSecBuffer pContextData) { SECURITY_STATUS scRet; PXTCB_CONTEXT Context ; PXTCB_CRED_HANDLE CredHandle ; PSecBuffer OutToken ; PSecBuffer InToken ; UCHAR GroupKey[ SEED_KEY_SIZE ]; UCHAR UniqueKey[ SEED_KEY_SIZE ]; UCHAR MyKey[ SEED_KEY_SIZE ]; PWSTR Target ; BOOL RealTarget = FALSE ; PUCHAR Buffer; ULONG BufferLen ; PUNICODE_STRING Group ;
DebugLog(( DEB_TRACE_CALLS, "InitLsaModeContext( %p, %p, %ws, ... )\n", dwCredHandle, dwCtxtHandle, (TargetName->Buffer ? TargetName->Buffer : L"<none>") ));
if ( fContextReq & ( ISC_REQ_PROMPT_FOR_CREDS | ISC_REQ_USE_SUPPLIED_CREDS | ISC_REQ_DATAGRAM | ISC_REQ_STREAM | ISC_REQ_NULL_SESSION | ISC_REQ_MANUAL_CRED_VALIDATION ) ) { return STATUS_INVALID_PARAMETER ; }
//
// Determine what kind of call this is (first or second)
//
scRet = XtcbGetState( dwCredHandle, dwCtxtHandle, pInput, pOutput, TRUE, &Context, &CredHandle, &InToken, &OutToken );
if ( FAILED( scRet ) ) { return scRet ; }
//
// Decide what to do:
//
if ( Context->Core.State == ContextFirstCall ) { if ( InToken ) { //
// Something there
//
scRet = SEC_E_INVALID_TOKEN ; } else {
if ( !OutToken ) { scRet = SEC_E_INVALID_TOKEN ; } else { //
// Examine the target name. See if we can handle it:
//
if ( MGroupParseTarget( TargetName->Buffer, &Target ) ) { //
// See if we have a group with that machine as a member:
//
if ( MGroupLocateKeys( Target, &Group, UniqueKey, GroupKey, MyKey ) ) { //
// We do have one! Calooh! Calay!
//
RealTarget = TRUE ;
}
}
if ( !RealTarget ) { //
// Not one of ours. Delete the context,
// clean up
//
scRet = SEC_E_TARGET_UNKNOWN ; }
}
if ( RealTarget ) { //
// We've got a live target. Fill in the context, and construct
// the blob
//
scRet = XtcbBuildInitialToken( CredHandle->Creds, Context, TargetName, Group, UniqueKey, GroupKey, MyKey, &Buffer, &BufferLen );
}
if ( NT_SUCCESS( scRet ) ) {
if ( fContextReq & ISC_REQ_ALLOCATE_MEMORY ) { OutToken->pvBuffer = Buffer ; OutToken->cbBuffer = BufferLen ; } else { if ( BufferLen <= OutToken->cbBuffer ) { RtlCopyMemory( OutToken->pvBuffer, Buffer, BufferLen );
OutToken->cbBuffer = BufferLen ; } else { scRet = SEC_E_INSUFFICIENT_MEMORY ; } }
}
if ( NT_SUCCESS( scRet ) ) {
Context->Core.State = ContextSecondCall ; Context->Core.Attributes = fContextReq ;
*pdwNewContext = (LSA_SEC_HANDLE) Context ; } else { XtcbDerefContextRecord( Context );
}
return scRet ; } } else { //
// Second round
//
}
return( scRet );
}
//+---------------------------------------------------------------------------
//
// Function: XtcbDeleteContext
//
// Synopsis: Deletes the LSA side of a context
//
// Arguments: [dwCtxtHandle] --
//
// History: 8-15-98 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY XtcbDeleteContext( LSA_SEC_HANDLE dwCtxtHandle ) { PXTCB_CONTEXT Context ;
DebugLog(( DEB_TRACE_CALLS, "DeleteContext( %x )\n", dwCtxtHandle ));
Context = (PXTCB_CONTEXT) dwCtxtHandle ;
if ( XtcbRefContextRecord( Context ) ) { XtcbDerefContextRecord( Context );
XtcbDerefContextRecord( Context );
return SEC_E_OK ; }
return( SEC_E_INVALID_HANDLE ); }
//+---------------------------------------------------------------------------
//
// Function: XtcbApplyControlToken
//
// Synopsis: Apply a control token to a context
//
// Effects: not supported
//
// Arguments: [dwCtxtHandle] --
// [pInput] --
//
// History: 8-15-98 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY XtcbApplyControlToken( LSA_SEC_HANDLE dwCtxtHandle, PSecBufferDesc pInput) { DebugLog(( DEB_TRACE_CALLS, "ApplyControlToken( %x )\n", dwCtxtHandle ));
return(SEC_E_UNSUPPORTED_FUNCTION); }
//+---------------------------------------------------------------------------
//
// Function: XtcbAcceptLsaModeContext
//
// Synopsis: Creates a server side context representing the user connecting
//
// Arguments: [dwCredHandle] --
// [dwCtxtHandle] --
// [pInput] --
// [fContextReq] --
// [TargetDataRep] --
// [pdwNewContext] --
// [pOutput] --
// [pfContextAttr] --
// [ptsExpiry] --
// [pfMapContext] --
// [pContextData] --
//
// History: 8-15-98 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY XtcbAcceptLsaModeContext( LSA_SEC_HANDLE dwCredHandle, LSA_SEC_HANDLE dwCtxtHandle, PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PLSA_SEC_HANDLE pdwNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry, PBYTE pfMapContext, PSecBuffer pContextData) { SECURITY_STATUS scRet; PXTCB_CONTEXT Context ; PXTCB_CRED_HANDLE CredHandle ; PSecBuffer OutToken ; PSecBuffer InToken ; HANDLE Token ; UNICODE_STRING Client; UNICODE_STRING Group ; UCHAR GroupKey[ SEED_KEY_SIZE ]; UCHAR UniqueKey[ SEED_KEY_SIZE ]; UCHAR MyKey[ SEED_KEY_SIZE ]; BOOL Success = FALSE ;
DebugLog(( DEB_TRACE_CALLS, "AcceptLsaModeContext( %x, %x, ... )\n", dwCredHandle, dwCtxtHandle ));
//
// Determine what kind of call this is (first or second)
//
*pfMapContext = FALSE ;
scRet = XtcbGetState( dwCredHandle, dwCtxtHandle, pInput, pOutput, FALSE, &Context, &CredHandle, &InToken, &OutToken );
if ( FAILED( scRet ) ) { return scRet ; }
//
// Decide what to do:
//
if ( Context->Core.State == ContextFirstCall ) { if ( !InToken ) { return SEC_E_INVALID_TOKEN ; }
if ( !XtcbParseInputToken( InToken->pvBuffer, InToken->cbBuffer, &Client, &Group ) ) { DebugLog((DEB_TRACE, "Unable to parse input token\n" ));
return SEC_E_INVALID_TOKEN ; }
Success = MGroupLocateInboundKey( &Group, &Client, UniqueKey, GroupKey, MyKey );
LocalFree( Client.Buffer ); LocalFree( Group.Buffer );
if ( Success ) { scRet = XtcbAuthenticateClient( Context, InToken->pvBuffer, InToken->cbBuffer, UniqueKey, GroupKey, MyKey );
} else { DebugLog(( DEB_TRACE, "Unable to find group entry for Group %ws, Client %ws\n", Group.Buffer, Client.Buffer ));
scRet = SEC_E_INVALID_TOKEN ; }
if ( NT_SUCCESS( scRet ) ) { scRet = XtcbBuildReplyToken( Context, fContextReq, OutToken ); }
if ( NT_SUCCESS( scRet ) ) {
Context->Core.State = ContextSecondCall ; //
// Ok, we've done the authentication. Now, we need to map
// the security context back to the client process
//
scRet = LsaTable->DuplicateHandle( Context->Token, &Token );
if ( NT_SUCCESS( scRet ) ) { Context->Core.CoreTokenHandle = HandleToUlong( Token );
*pfMapContext = TRUE ;
pContextData->BufferType = SECBUFFER_TOKEN ; pContextData->cbBuffer = sizeof( XTCB_CONTEXT_CORE ); pContextData->pvBuffer = &Context->Core ;
*pfContextAttr = ASC_RET_DELEGATE | ASC_RET_MUTUAL_AUTH | ASC_RET_REPLAY_DETECT | ASC_RET_SEQUENCE_DETECT | ASC_RET_CONFIDENTIALITY | ASC_ }
}
}
return( scRet ); }
//+---------------------------------------------------------------------------
//
// Function: XtcbQueryLsaModeContext
//
// Synopsis: Lifespan is thunked to LSA mode for demonstration purposes
//
// Arguments: [ContextHandle] --
// [ContextAttribute] --
// [pBuffer] --
//
// History: 3-30-97 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
NTSTATUS NTAPI XtcbQueryLsaModeContext( IN LSA_SEC_HANDLE ContextHandle, IN ULONG ContextAttribute, IN OUT PVOID pBuffer ) { PXTCB_CONTEXT Context ; NTSTATUS Status ;
Context = (PXTCB_CONTEXT) ContextHandle ;
if ( !XtcbRefContextRecord( Context )) { return SEC_E_INVALID_HANDLE ; }
Status = SEC_E_UNSUPPORTED_FUNCTION ;
XtcbDerefContextRecord( Context );
return( Status );
}
|