5411 lines
134 KiB
C++
5411 lines
134 KiB
C++
//+-----------------------------------------------------------------------
|
||
//
|
||
// Microsoft Windows
|
||
//
|
||
// Copyright (c) Microsoft Corporation 1991 - 1992
|
||
//
|
||
// File: KLPCSTUB.CXX
|
||
//
|
||
// Contents: LPC Support for the KSEC device driver
|
||
// API Dispatcher
|
||
// (Un)Marshalling code
|
||
//
|
||
//
|
||
// Functions: GetClientString
|
||
// LpcAcquireCreds
|
||
// LpcInitContext
|
||
// LpcAcceptContext
|
||
//
|
||
// DispatchAPI
|
||
//
|
||
// History: 20 May 92 RichardW Created
|
||
// 11 Mar 94 MikeSw Renamed from klpc2.c
|
||
//
|
||
//------------------------------------------------------------------------
|
||
|
||
#include <lsapch.hxx>
|
||
extern "C"
|
||
{
|
||
#include "klpcstub.h"
|
||
#include <efsstruc.h>
|
||
#include "efssrv.hxx"
|
||
#include "sphelp.h"
|
||
}
|
||
ULONG LsapPageSize ;
|
||
LONG InternalMessageId ;
|
||
PLSAP_API_LOG InternalApiLog ;
|
||
//
|
||
// Maximum size of a string. This is the max size of
|
||
// a short, less the null terminator
|
||
//
|
||
#define LSAP_MAX_STRING_LENGTH (0xfffc)
|
||
|
||
//#define LSAP_CATCH_BAD_VM
|
||
|
||
static EfsSessionKeySent = FALSE;
|
||
|
||
extern "C" BOOLEAN EfsPersonalVer;
|
||
|
||
extern "C" BOOLEAN EfsDisabled;
|
||
|
||
#if DBG
|
||
char * SessionStatLabels[] = { "<Disconnect>",
|
||
"<Connect>",
|
||
"LsaLookupPackage",
|
||
"LsaLogonUser",
|
||
"LsaCallPackage",
|
||
"LsaDeregisterLogonProcess",
|
||
"<empty>",
|
||
"(I) GetBinding",
|
||
"(I) SetSession",
|
||
"(I) FindPackage",
|
||
"EnumeratePackages",
|
||
"AcquireCredentialHandle",
|
||
"EstablishCredentials",
|
||
"FreeCredentialHandle",
|
||
"InitializeSecurityContext",
|
||
"AcceptSecurityContext",
|
||
"ApplyControlToken",
|
||
"DeleteSecurityContext",
|
||
"QueryPackage",
|
||
"GetUserInfo",
|
||
"GetCredentials",
|
||
"SaveCredentials",
|
||
"DeleteCredentials",
|
||
"QueryCredAttributes",
|
||
"AddPackage",
|
||
"DeletePackage",
|
||
"GenerateKey",
|
||
"GenerateDirEfs",
|
||
"DecryptFek",
|
||
"GenerateSessionKey",
|
||
"Callback",
|
||
"QueryContextAttributes",
|
||
"PolicyChangeNotify",
|
||
"GetUserName",
|
||
"AddCredentials",
|
||
"EnumLogonSessions",
|
||
"GetLogonSessionData",
|
||
"SetContextAttribute",
|
||
"LookupAccountName",
|
||
"LookupAccountSid",
|
||
"<empty>" };
|
||
#define ApiLabel(x) (((x+2) < sizeof(SessionStatLabels) / sizeof(char *)) ? \
|
||
SessionStatLabels[(x+2)] : "[Illegal API Number!]")
|
||
#endif
|
||
|
||
|
||
|
||
PLSA_DISPATCH_FN DllCallbackHandler ;
|
||
//
|
||
// Function orders after LsapAuMaxApiNumber must match SPM_API and
|
||
// SPM_API_NUMBER defined in ..\h\spmlpc.h
|
||
//
|
||
PLSA_DISPATCH_FN LpcDispatchTable[ SPMAPI_MaxApiNumber ] =
|
||
{
|
||
LpcLsaLookupPackage,
|
||
LpcLsaLogonUser,
|
||
LpcLsaCallPackage,
|
||
LpcLsaDeregisterLogonProcess,
|
||
NULL, // LsapAuMaxApiNumber
|
||
LpcGetBinding,
|
||
LpcSetSession,
|
||
LpcFindPackage,
|
||
LpcEnumPackages,
|
||
LpcAcquireCreds,
|
||
LpcEstablishCreds,
|
||
LpcFreeCredHandle,
|
||
LpcInitContext,
|
||
LpcAcceptContext,
|
||
LpcApplyToken,
|
||
LpcDeleteContext,
|
||
LpcQueryPackage,
|
||
LpcGetUserInfo,
|
||
LpcGetCreds,
|
||
LpcSaveCreds,
|
||
LpcDeleteCreds,
|
||
LpcQueryCredAttributes,
|
||
LpcAddPackage,
|
||
LpcDeletePackage,
|
||
LpcEfsGenerateKey,
|
||
LpcEfsGenerateDirEfs,
|
||
LpcEfsDecryptFek,
|
||
LpcEfsGenerateSessionKey,
|
||
LpcCallback,
|
||
LpcQueryContextAttributes,
|
||
LpcLsaPolicyChangeNotify,
|
||
LpcGetUserName,
|
||
LpcAddCredentials,
|
||
LpcEnumLogonSessions,
|
||
LpcGetLogonSessionData,
|
||
LpcSetContextAttributes,
|
||
LpcLookupAccountName,
|
||
LpcLookupAccountSid
|
||
};
|
||
|
||
NTSTATUS
|
||
MapTokenBuffer(
|
||
PSecBufferDesc pInput,
|
||
BOOLEAN fDoClientCopy
|
||
);
|
||
|
||
#define KLPC_FLAG_RESET (~(SPMAPI_FLAG_ERROR_RET | \
|
||
SPMAPI_FLAG_MEMORY | SPMAPI_FLAG_PREPACK | \
|
||
SPMAPI_FLAG_EXEC_NOW ) )
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: AbortLpcContext
|
||
//
|
||
// Synopsis: Aborts a security context if something goes wrong.
|
||
//
|
||
// Effects: Calls a DeleteContext() on the context.
|
||
//
|
||
// Arguments: [phContext] -- Context to abort
|
||
//
|
||
// History: 6-29-93 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
void
|
||
AbortLpcContext(
|
||
PCtxtHandle phContext
|
||
)
|
||
{
|
||
PSession pSession ;
|
||
NTSTATUS scRet;
|
||
PLSA_CALL_INFO CallInfo ;
|
||
|
||
pSession = GetCurrentSession();
|
||
|
||
CallInfo = LsapGetCurrentCall();
|
||
|
||
CallInfo->Flags |= CALL_FLAG_NO_HANDLE_CHK ;
|
||
|
||
DebugLog((DEB_WARN, "[%x] Aborting context %p:%p\n",
|
||
pSession->dwProcessID, phContext->dwUpper,
|
||
phContext->dwLower));
|
||
|
||
|
||
scRet = WLsaDeleteContext( phContext );
|
||
|
||
if (FAILED(scRet))
|
||
{
|
||
DebugLog((DEB_WARN, "[%x] DeleteContext failed (%x) on context %p:%p\n",
|
||
pSession->dwProcessID, scRet, phContext->dwUpper,
|
||
phContext->dwLower));
|
||
|
||
}
|
||
|
||
CallInfo->Flags &= (~(CALL_FLAG_NO_HANDLE_CHK));
|
||
|
||
}
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: GetClientString
|
||
//
|
||
// Synopsis: Get a string from client memory
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
GetClientString(
|
||
PUNICODE_STRING pssSource,
|
||
PUNICODE_STRING pssDest,
|
||
PSPM_LPC_MESSAGE pMessage,
|
||
PUCHAR * Where
|
||
)
|
||
{
|
||
NTSTATUS scRet = S_OK;
|
||
PLSA_CALL_INFO CallInfo = LsapGetCurrentCall();
|
||
|
||
*pssDest = *pssSource;
|
||
|
||
|
||
if ( pssDest->Length > LSAP_MAX_STRING_LENGTH )
|
||
{
|
||
return STATUS_INVALID_PARAMETER ;
|
||
}
|
||
|
||
if ( CallInfo->Flags & CALL_FLAG_KERNEL_POOL )
|
||
{
|
||
if ((ULONG_PTR) pssSource->Buffer >= (ULONG_PTR) sizeof( SPM_LPC_MESSAGE ) )
|
||
{
|
||
*pssDest = *pssSource ;
|
||
if ( pssDest->Length < pssDest->MaximumLength )
|
||
{
|
||
pssDest->Buffer[ pssDest->Length / sizeof( WCHAR )] = L'\0';
|
||
|
||
}
|
||
return STATUS_SUCCESS ;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
pssDest->Buffer = (LPWSTR) LsapAllocatePrivateHeap(pssDest->Length+sizeof(WCHAR));
|
||
if (pssDest->Buffer)
|
||
{
|
||
pssDest->MaximumLength = pssDest->Length+sizeof(WCHAR);
|
||
|
||
if (pssSource->Length != 0)
|
||
{
|
||
if ((ULONG_PTR) pssSource->Buffer >= (ULONG_PTR) sizeof( SPM_LPC_MESSAGE ) )
|
||
{
|
||
scRet = LsapCopyFromClient( pssSource->Buffer,
|
||
pssDest->Buffer,
|
||
pssDest->Length);
|
||
if (FAILED(scRet))
|
||
{
|
||
LsapFreePrivateHeap(pssDest->Buffer);
|
||
pssDest->Buffer = NULL;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// prepacked buffers
|
||
//
|
||
|
||
if ( pssSource->Length > CBPREPACK )
|
||
{
|
||
LsapFreePrivateHeap( pssDest->Buffer );
|
||
|
||
pssDest->Buffer = NULL ;
|
||
|
||
return STATUS_INVALID_PARAMETER ;
|
||
}
|
||
|
||
*Where = (PUCHAR) (pMessage) + (ULONG_PTR) pssSource->Buffer ;
|
||
|
||
if (*Where == NULL)
|
||
{
|
||
*Where = pMessage->ApiMessage.bData;
|
||
}
|
||
|
||
RtlCopyMemory(
|
||
pssDest->Buffer,
|
||
*Where,
|
||
pssDest->Length);
|
||
|
||
*Where += pssDest->Length;
|
||
|
||
}
|
||
}
|
||
|
||
return(scRet);
|
||
}
|
||
return(SEC_E_INSUFFICIENT_MEMORY);
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: PutClientString
|
||
//
|
||
// Synopsis: Get a string from client memory
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
PutClientString(
|
||
PUNICODE_STRING pssSource,
|
||
PUNICODE_STRING pssDest
|
||
)
|
||
{
|
||
NTSTATUS scRet;
|
||
|
||
pssDest->Length = pssSource->Length;
|
||
|
||
//
|
||
// If the destination buffer isn't allocated yet, allocate it.
|
||
//
|
||
|
||
if (!pssDest->Buffer)
|
||
{
|
||
pssDest->Buffer = (LPWSTR) LsapClientAllocate(pssDest->Length+sizeof(WCHAR));
|
||
pssDest->MaximumLength = pssDest->Length+sizeof(WCHAR);
|
||
}
|
||
|
||
if (pssDest->Buffer)
|
||
{
|
||
scRet = LsapCopyToClient( pssSource->Buffer,
|
||
pssDest->Buffer,
|
||
pssDest->Length);
|
||
if (FAILED(scRet))
|
||
{
|
||
LsapClientFree(pssDest->Buffer);
|
||
pssDest->Buffer = NULL;
|
||
}
|
||
|
||
return(scRet);
|
||
}
|
||
return(SEC_E_INSUFFICIENT_MEMORY);
|
||
}
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: MapTokenBuffer
|
||
//
|
||
// Synopsis: Maps the security token buffer into local memory
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
MapTokenBuffer(
|
||
PSecBufferDesc pInput,
|
||
BOOLEAN fDoClientCopy
|
||
)
|
||
{
|
||
ULONG i;
|
||
NTSTATUS scRet = STATUS_SUCCESS;
|
||
PLSA_CALL_INFO CallInfo = LsapGetCurrentCall();
|
||
|
||
//
|
||
// Mark all buffers as unmapped in case of failure
|
||
//
|
||
|
||
for (i = 0; i < pInput->cBuffers ; i++ )
|
||
{
|
||
pInput->pBuffers[i].BufferType |= SECBUFFER_UNMAPPED;
|
||
}
|
||
|
||
for (i = 0; i < pInput->cBuffers ; i++ )
|
||
{
|
||
|
||
//
|
||
// Always map the security token - it is assumed that this
|
||
// is always wanted by all packages
|
||
//
|
||
|
||
if ((pInput->pBuffers[i].BufferType & ~SECBUFFER_ATTRMASK) == SECBUFFER_TOKEN)
|
||
{
|
||
if (fDoClientCopy)
|
||
{
|
||
scRet = LsapMapClientBuffer( &pInput->pBuffers[i],
|
||
&pInput->pBuffers[i] );
|
||
}
|
||
else
|
||
{
|
||
pInput->pBuffers[i].pvBuffer = LsapAllocateLsaHeap(pInput->pBuffers[i].cbBuffer);
|
||
if (!pInput->pBuffers[i].pvBuffer)
|
||
{
|
||
scRet = SEC_E_INSUFFICIENT_MEMORY;
|
||
}
|
||
pInput->pBuffers[i].BufferType &= ~SECBUFFER_UNMAPPED;
|
||
}
|
||
if (FAILED(scRet))
|
||
{
|
||
return(scRet);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
NOTHING ;
|
||
|
||
}
|
||
|
||
|
||
}
|
||
return(S_OK);
|
||
}
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: AllocateClientBuffers
|
||
//
|
||
// Synopsis: Allocate space in the client process for TOKEN type buffers
|
||
//
|
||
// Arguments: [pOutput] --
|
||
// [pClientOutput] --
|
||
// [pFlags] --
|
||
//
|
||
// History: 8-14-98 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
AllocateClientBuffers(
|
||
PSecBufferDesc pOutput,
|
||
PSecBufferDesc pClientOutput,
|
||
PUSHORT pFlags)
|
||
{
|
||
ULONG i;
|
||
|
||
|
||
DsysAssert(pOutput->cBuffers <= MAX_SECBUFFERS);
|
||
if (pOutput->cBuffers > MAX_SECBUFFERS)
|
||
{
|
||
return(SEC_E_INVALID_TOKEN);
|
||
}
|
||
|
||
for (i = 0; i < pOutput->cBuffers ; i++ )
|
||
{
|
||
pClientOutput->pBuffers[i] = pOutput->pBuffers[i];
|
||
if (((pOutput->pBuffers[i].BufferType & ~SECBUFFER_ATTRMASK) == SECBUFFER_TOKEN)
|
||
&& (pOutput->pBuffers[i].cbBuffer))
|
||
{
|
||
pClientOutput->pBuffers[i].pvBuffer =
|
||
LsapClientAllocate(pOutput->pBuffers[i].cbBuffer);
|
||
|
||
if (!pClientOutput->pBuffers[i].pvBuffer)
|
||
{
|
||
return( SEC_E_INSUFFICIENT_MEMORY );
|
||
}
|
||
|
||
*pFlags |= SPMAPI_FLAG_MEMORY;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
return(S_OK);
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: CopyClientBuffers
|
||
//
|
||
// Synopsis: Copies any mapped buffers over to the client's address
|
||
// space. The length is also copies for those buffers.
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
CopyClientBuffers(
|
||
PSecBufferDesc pSource,
|
||
PSecBufferDesc pDest)
|
||
{
|
||
ULONG i;
|
||
NTSTATUS scRet;
|
||
|
||
for (i = 0; i < pSource->cBuffers ; i++ )
|
||
{
|
||
//
|
||
// Only copy it if the buffer exists and is unmapped -
|
||
// otherwise nothing changed or there is nothing and it is
|
||
// a waste of time.
|
||
//
|
||
|
||
|
||
if (pSource->pBuffers[i].pvBuffer &&
|
||
!(pSource->pBuffers[i].BufferType & SECBUFFER_UNMAPPED))
|
||
{
|
||
DsysAssert(pSource->pBuffers[i].cbBuffer <= pDest->pBuffers[i].cbBuffer);
|
||
|
||
scRet = LsapCopyToClient( pSource->pBuffers[i].pvBuffer,
|
||
pDest->pBuffers[i].pvBuffer,
|
||
pSource->pBuffers[i].cbBuffer );
|
||
|
||
if (FAILED(scRet))
|
||
{
|
||
//
|
||
// Again, we have a real problem when this fails. We
|
||
// abort the context and return an error.
|
||
//
|
||
|
||
return(SEC_E_INSUFFICIENT_MEMORY);
|
||
|
||
|
||
|
||
}
|
||
|
||
//
|
||
// Copy the length over also
|
||
//
|
||
|
||
pDest->pBuffers[i].cbBuffer = pSource->pBuffers[i].cbBuffer;
|
||
pDest->pBuffers[i].BufferType = pSource->pBuffers[i].BufferType &
|
||
(~SECBUFFER_ATTRMASK) ;
|
||
}
|
||
}
|
||
return(S_OK);
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: GetClientBuffer
|
||
//
|
||
// Synopsis: Maps a client's SecBuffer into the caller's address space or
|
||
// from prepacked area
|
||
//
|
||
// Effects: Clears the SECBUFFER_UNMAPPED field of the BufferType of
|
||
// the return SecBuffer
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes: Doesn't modify pOutput until the end, so it is o.k. to pass
|
||
// the same thing for pInput and pOutput.
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
GetClientBuffer(
|
||
IN PSecBuffer pInput,
|
||
OUT PSecBuffer pOutput,
|
||
IN PSPM_LPC_MESSAGE pMessage,
|
||
IN OUT PUCHAR * Where
|
||
)
|
||
{
|
||
NTSTATUS hrRet = STATUS_SUCCESS;
|
||
SecBuffer Output;
|
||
Output = *pInput;
|
||
|
||
//
|
||
// If the buffer is already mapped or it doesn't exist (is NULL) we
|
||
// are done.
|
||
//
|
||
|
||
if (!(pInput->BufferType & SECBUFFER_UNMAPPED) ||
|
||
!pInput->pvBuffer)
|
||
{
|
||
return(S_OK);
|
||
}
|
||
|
||
Output.BufferType &= ~SECBUFFER_UNMAPPED;
|
||
Output.pvBuffer = LsapAllocateLsaHeap(pInput->cbBuffer);
|
||
if (!(Output.pvBuffer))
|
||
{
|
||
return(SEC_E_INSUFFICIENT_MEMORY);
|
||
}
|
||
|
||
if (pInput->pvBuffer != (PVOID) SEC_PACKED_BUFFER_VALUE)
|
||
{
|
||
hrRet = LsapCopyFromClient( pInput->pvBuffer,
|
||
Output.pvBuffer,
|
||
Output.cbBuffer );
|
||
}
|
||
else
|
||
{
|
||
if (*Where == NULL)
|
||
{
|
||
*Where = pMessage->ApiMessage.bData;
|
||
}
|
||
RtlCopyMemory( Output.pvBuffer, *Where, Output.cbBuffer);
|
||
*Where += Output.cbBuffer;
|
||
}
|
||
if (FAILED(hrRet))
|
||
{
|
||
LsapFreeLsaHeap(Output.pvBuffer);
|
||
}
|
||
else
|
||
{
|
||
*pOutput = Output;
|
||
}
|
||
return(hrRet);
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LsapWriteClientBuffer
|
||
//
|
||
// Synopsis: Allocates and copies a buffer out to the client
|
||
//
|
||
// Arguments: [LsaBuffer] --
|
||
// [ClientBuffer] --
|
||
//
|
||
// History: 4-11-97 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LsapWriteClientBuffer(
|
||
IN PSecBuffer LsaBuffer,
|
||
OUT PSecBuffer ClientBuffer
|
||
)
|
||
{
|
||
NTSTATUS Status ;
|
||
PVOID Client ;
|
||
|
||
Status = LsapAllocateClientBuffer( NULL,
|
||
LsaBuffer->cbBuffer,
|
||
&Client );
|
||
|
||
if ( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = LsapCopyToClientBuffer( NULL,
|
||
LsaBuffer->cbBuffer,
|
||
Client,
|
||
LsaBuffer->pvBuffer );
|
||
|
||
if ( NT_SUCCESS( Status ) )
|
||
{
|
||
ClientBuffer->BufferType = LsaBuffer->BufferType ;
|
||
ClientBuffer->cbBuffer = LsaBuffer->cbBuffer ;
|
||
ClientBuffer->pvBuffer = Client ;
|
||
}
|
||
else
|
||
{
|
||
LsapFreeClientBuffer( NULL, Client );
|
||
}
|
||
}
|
||
|
||
return Status ;
|
||
}
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LsapChangeHandle
|
||
//
|
||
// Synopsis: Changes a handle, based on the current API, session
|
||
//
|
||
// Arguments: [HandleOp] --
|
||
// [OldHandle] --
|
||
// [NewHandle] --
|
||
//
|
||
// History: 9-20-96 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
BOOL
|
||
LsapChangeHandle(
|
||
SECHANDLE_OPS HandleOp,
|
||
PSecHandle OldHandle,
|
||
PSecHandle NewHandle
|
||
)
|
||
{
|
||
PLSA_CALL_INFO CallInfo ;
|
||
PSPM_LPC_MESSAGE pMessage;
|
||
SPMAcquireCredsAPI *pAcquireCreds;
|
||
SPMInitContextAPI * pInitContext;
|
||
SPMAcceptContextAPI *pAcceptContext;
|
||
BOOL ContextHandle ;
|
||
PSession pSession ;
|
||
SecHandle RemoveHandle = { 0 };
|
||
PVOID Key ;
|
||
|
||
|
||
CallInfo = LsapGetCurrentCall();
|
||
|
||
if ( !CallInfo )
|
||
{
|
||
return FALSE ;
|
||
}
|
||
|
||
pMessage = CallInfo->Message ;
|
||
|
||
pSession = CallInfo->Session ;
|
||
|
||
|
||
ContextHandle = TRUE ;
|
||
|
||
if ( HandleOp == HandleRemoveReplace )
|
||
{
|
||
RemoveHandle = *OldHandle ;
|
||
}
|
||
|
||
switch ( pMessage->ApiMessage.dwAPI )
|
||
{
|
||
case SPMAPI_AcquireCreds:
|
||
pAcquireCreds = LPC_MESSAGE_ARGSP( pMessage, AcquireCreds );
|
||
|
||
if ( HandleOp == HandleReplace )
|
||
{
|
||
RemoveHandle = pAcquireCreds->hCredential ;
|
||
}
|
||
|
||
DebugLog((DEB_TRACE, "[%x] Changing Handle %p : %p to %p : %p\n",
|
||
pSession->dwProcessID,
|
||
pAcquireCreds->hCredential.dwUpper, pAcquireCreds->hCredential.dwLower,
|
||
NewHandle->dwUpper, NewHandle->dwLower ));
|
||
|
||
pAcquireCreds->hCredential = *NewHandle ;
|
||
|
||
ContextHandle = FALSE ;
|
||
|
||
break;
|
||
|
||
case SPMAPI_InitContext:
|
||
pInitContext = LPC_MESSAGE_ARGSP( pMessage, InitContext );
|
||
|
||
if ( HandleOp == HandleReplace )
|
||
{
|
||
RemoveHandle = pInitContext->hContext ;
|
||
}
|
||
|
||
DebugLog((DEB_TRACE, "[%x] Changing Handle %p : %p to %p : %p\n",
|
||
pSession->dwProcessID,
|
||
pInitContext->hContext.dwUpper, pInitContext->hContext.dwLower,
|
||
NewHandle->dwUpper, NewHandle->dwLower ));
|
||
|
||
pInitContext->hNewContext = *NewHandle ;
|
||
|
||
break;
|
||
|
||
case SPMAPI_AcceptContext:
|
||
pAcceptContext = LPC_MESSAGE_ARGSP( pMessage, AcceptContext );
|
||
|
||
if ( HandleOp == HandleReplace )
|
||
{
|
||
RemoveHandle = pAcceptContext->hContext ;
|
||
}
|
||
|
||
DebugLog((DEB_TRACE, "[%x] Changing Handle %p : %p to %p : %p\n",
|
||
pSession->dwProcessID,
|
||
pAcceptContext->hNewContext.dwUpper, pAcceptContext->hNewContext.dwLower,
|
||
NewHandle->dwUpper, NewHandle->dwLower ));
|
||
|
||
pAcceptContext->hNewContext = *NewHandle ;
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
return( FALSE );
|
||
}
|
||
|
||
pMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_HANDLE_CHG ;
|
||
|
||
//
|
||
// Clean up the handle references. The old handle is dereferenced,
|
||
// the new handle is referenced once (to make up for it).
|
||
//
|
||
|
||
if ( ContextHandle )
|
||
{
|
||
if ( HandleOp != HandleSet )
|
||
{
|
||
DebugLog(( DEB_TRACE, "[%x] Deleting old context handle %p : %p\n",
|
||
pSession->dwProcessID,
|
||
RemoveHandle.dwUpper, RemoveHandle.dwLower ));
|
||
|
||
ValidateAndDerefContextHandle( pSession, &RemoveHandle );
|
||
|
||
// ValidateContextHandle( pSession, NewHandle, &Key );
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
if ( HandleOp != HandleSet )
|
||
{
|
||
DebugLog(( DEB_TRACE, "[%x] Deleting old credential handle %p : %p\n",
|
||
pSession->dwProcessID,
|
||
RemoveHandle.dwUpper, RemoveHandle.dwLower ));
|
||
|
||
ValidateAndDerefCredHandle( pSession, &RemoveHandle );
|
||
|
||
// ValidateCredHandle( pSession, NewHandle, &Key );
|
||
}
|
||
|
||
}
|
||
|
||
return( TRUE );
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
LsapFixupAuthIdentity(
|
||
PKSEC_LSA_MEMORY_HEADER KMap,
|
||
PVOID AuthIdentity
|
||
)
|
||
{
|
||
PSEC_WINNT_AUTH_IDENTITY_EX AuthEx ;
|
||
NTSTATUS Status = STATUS_SUCCESS ;
|
||
ULONG_PTR PoolBase = (ULONG_PTR) -1 ;
|
||
USHORT i ;
|
||
|
||
AuthEx = (PSEC_WINNT_AUTH_IDENTITY_EX) AuthIdentity ;
|
||
|
||
DsysAssert( AuthEx->Version == SEC_WINNT_AUTH_IDENTITY_VERSION );
|
||
|
||
for ( i = 0 ; i < KMap->MapCount ; i++ )
|
||
{
|
||
if ( (PUCHAR) KMap + KMap->PoolMap[ i ].Offset == (PUCHAR) AuthIdentity )
|
||
{
|
||
PoolBase = (ULONG_PTR) KMap->PoolMap[ i ].Pool ;
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
if ( AuthEx->User )
|
||
{
|
||
if ( (ULONG_PTR) AuthEx->User > PoolBase)
|
||
{
|
||
AuthEx->User = (PWSTR) ( (ULONG_PTR) AuthEx->User - PoolBase );
|
||
|
||
}
|
||
if ( (ULONG_PTR) AuthEx->User < 0x10000 )
|
||
{
|
||
AuthEx->User = (PWSTR) ((ULONG_PTR)AuthEx->User + (PUCHAR) AuthIdentity);
|
||
|
||
}
|
||
else
|
||
{
|
||
if ( !LsapIsBlockInKMap( KMap, AuthEx->User ) )
|
||
{
|
||
Status = STATUS_ACCESS_VIOLATION ;
|
||
}
|
||
}
|
||
|
||
}
|
||
if ( AuthEx->Domain )
|
||
{
|
||
if ( (ULONG_PTR) AuthEx->Domain > PoolBase)
|
||
{
|
||
AuthEx->Domain = (PWSTR) ( (ULONG_PTR) AuthEx->Domain - PoolBase );
|
||
|
||
}
|
||
if ( (ULONG_PTR) AuthEx->Domain < 0x10000 )
|
||
{
|
||
AuthEx->Domain = (PWSTR) ((ULONG_PTR)AuthEx->Domain + (PUCHAR) AuthIdentity);
|
||
|
||
}
|
||
else
|
||
{
|
||
if ( !LsapIsBlockInKMap( KMap, AuthEx->Domain ) )
|
||
{
|
||
Status = STATUS_ACCESS_VIOLATION ;
|
||
}
|
||
}
|
||
|
||
}
|
||
if ( AuthEx->Password )
|
||
{
|
||
if ( (ULONG_PTR) AuthEx->Password > PoolBase)
|
||
{
|
||
AuthEx->Password = (PWSTR) ( (ULONG_PTR) AuthEx->Password - PoolBase );
|
||
|
||
}
|
||
if ( (ULONG_PTR) AuthEx->Password < 0x10000 )
|
||
{
|
||
AuthEx->Password = (PWSTR) ((ULONG_PTR)AuthEx->Password + (PUCHAR) AuthIdentity);
|
||
|
||
}
|
||
else
|
||
{
|
||
if ( !LsapIsBlockInKMap( KMap, AuthEx->Password ) )
|
||
{
|
||
Status = STATUS_ACCESS_VIOLATION ;
|
||
}
|
||
}
|
||
|
||
}
|
||
if ( AuthEx->PackageList )
|
||
{
|
||
if ( (ULONG_PTR) AuthEx->PackageList > PoolBase)
|
||
{
|
||
AuthEx->PackageList = (PWSTR) ( (ULONG_PTR) AuthEx->PackageList - PoolBase );
|
||
|
||
}
|
||
if ( (ULONG_PTR) AuthEx->PackageList < 0x10000 )
|
||
{
|
||
AuthEx->PackageList = (PWSTR) ((ULONG_PTR)AuthEx->PackageList + (PUCHAR) AuthIdentity);
|
||
|
||
}
|
||
else
|
||
{
|
||
if ( !LsapIsBlockInKMap( KMap, AuthEx->PackageList ) )
|
||
{
|
||
Status = STATUS_ACCESS_VIOLATION ;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
return Status ;
|
||
}
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcAcquireCreds()
|
||
//
|
||
// Synopsis: Lpc stub for AcquireCredHandle
|
||
//
|
||
// Effects: Calls the WLsaAcquire function
|
||
//
|
||
// Arguments: pApiMessage - Input message
|
||
// pApiMessage - Output message
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcAcquireCreds(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
UNICODE_STRING ssPrincipalName;
|
||
UNICODE_STRING ssPackageName;
|
||
NTSTATUS scApiRet;
|
||
NTSTATUS scRet;
|
||
SPMAcquireCredsAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.AcquireCreds;
|
||
|
||
PSession pSession ;
|
||
PLSA_CALL_INFO CallInfo ;
|
||
PUCHAR Where = NULL;
|
||
|
||
pSession = GetCurrentSession();
|
||
CallInfo = LsapGetCurrentCall();
|
||
|
||
DebugLog((DEB_TRACE, "[%x] LpcAcquireCreds()\n", pSession->dwProcessID));
|
||
|
||
ssPrincipalName.Buffer = NULL;
|
||
ssPackageName.Buffer = NULL;
|
||
|
||
if (pArgs->ssPrincipal.Buffer )
|
||
{
|
||
scRet = GetClientString(&pArgs->ssPrincipal,
|
||
&ssPrincipalName,
|
||
pApiMessage,
|
||
&Where);
|
||
if (FAILED(scRet))
|
||
{
|
||
DebugLog((DEB_ERROR, "GetClientString failed to get principal name 0x%08x\n", scRet));
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
return(scRet);
|
||
}
|
||
|
||
} else {
|
||
ssPrincipalName.MaximumLength = 0;
|
||
ssPrincipalName.Length = 0;
|
||
ssPrincipalName.Buffer = NULL;
|
||
}
|
||
|
||
scRet = GetClientString(&pArgs->ssSecPackage,
|
||
&ssPackageName,
|
||
pApiMessage,
|
||
&Where);
|
||
|
||
if (FAILED(scRet))
|
||
{
|
||
LsapFreePrivateHeap(ssPrincipalName.Buffer);
|
||
DebugLog((DEB_ERROR, "GetClientString failed to get package name 0x%08x\n", scRet));
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
return(scRet);
|
||
}
|
||
|
||
if ( CallInfo->Flags & CALL_FLAG_KERNEL_POOL )
|
||
{
|
||
scRet = LsapFixupAuthIdentity( CallInfo->KMap, pArgs->pvAuthData );
|
||
if ( !NT_SUCCESS( scRet ) )
|
||
{
|
||
LsapFreePrivateHeap(ssPrincipalName.Buffer);
|
||
LsapFreePrivateHeap(ssPackageName.Buffer);
|
||
DebugLog((DEB_ERROR, "AuthData in KMap not formatted correctly\n" ));
|
||
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
return(scRet);
|
||
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
scApiRet = WLsaAcquireCredHandle( (PSECURITY_STRING) &ssPrincipalName,
|
||
(PSECURITY_STRING) &ssPackageName,
|
||
pArgs->fCredentialUse,
|
||
&pArgs->LogonID,
|
||
(PVOID) pArgs->pvAuthData,
|
||
(PVOID) pArgs->pvGetKeyFn,
|
||
(PVOID) pArgs->ulGetKeyArgument,
|
||
&pArgs->hCredential,
|
||
&pArgs->tsExpiry);
|
||
|
||
|
||
//
|
||
// Reset the reply flags:
|
||
//
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
|
||
DebugLog((DEB_TRACE_VERB, "[%x] WLsaAcquire returned %x\n", pSession->dwProcessID, scRet));
|
||
|
||
LsapFreePrivateHeap(ssPackageName.Buffer);
|
||
|
||
LsapFreePrivateHeap(ssPrincipalName.Buffer);
|
||
|
||
pApiMessage->ApiMessage.scRet = scApiRet;
|
||
if (FAILED(pApiMessage->ApiMessage.scRet))
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
}
|
||
return(S_OK);
|
||
|
||
}
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcFreeCredHandle
|
||
//
|
||
// Synopsis: Free a credential handle
|
||
//
|
||
// Arguments: [pApiMessage] --
|
||
//
|
||
// History: 8-14-98 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcFreeCredHandle(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS hrApiRet;
|
||
PSession pSession ;
|
||
|
||
pSession = GetCurrentSession();
|
||
|
||
DebugLog((DEB_TRACE, "[%x] LpcFreeCreds\n", pSession->dwProcessID));
|
||
|
||
hrApiRet = WLsaFreeCredHandle(&pApiMessage->ApiMessage.Args.SpmArguments.API.FreeCredHandle.hCredential);
|
||
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
pApiMessage->ApiMessage.scRet = hrApiRet;
|
||
|
||
if (FAILED(hrApiRet))
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
}
|
||
|
||
return(S_OK);
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LsapCaptureBuffers
|
||
//
|
||
// Synopsis: Capture client buffers and counts to local memory, validating
|
||
// as we go.
|
||
//
|
||
// Arguments: [InputBuffers] --
|
||
// [MappedBuffers] --
|
||
// [MapTokenBuffer] --
|
||
//
|
||
// History: 8-14-98 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LsapCaptureBuffers(
|
||
IN PUCHAR Base,
|
||
IN PSecBufferDesc InputBuffers,
|
||
OUT PSecBufferDesc MappedBuffers,
|
||
OUT PVOID * CapturedBuffers,
|
||
IN BOOLEAN MapTokenBuffers
|
||
)
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS ;
|
||
PSecBuffer LocalCopy ;
|
||
PSecBufferDesc Capture ;
|
||
ULONG i ;
|
||
|
||
//
|
||
// Initialize them first:
|
||
//
|
||
|
||
*CapturedBuffers = NULL ;
|
||
|
||
RtlZeroMemory(
|
||
MappedBuffers->pBuffers,
|
||
MappedBuffers->cBuffers * sizeof( SecBuffer ) );
|
||
|
||
for (i = 0 ; i < MappedBuffers->cBuffers ; i++ )
|
||
{
|
||
MappedBuffers->pBuffers[ i ].BufferType = SECBUFFER_UNMAPPED ;
|
||
}
|
||
|
||
if ( InputBuffers->cBuffers > MappedBuffers->cBuffers )
|
||
{
|
||
return STATUS_INVALID_PARAMETER ;
|
||
}
|
||
|
||
|
||
//
|
||
// Sizewise, we're safe to copy now:
|
||
//
|
||
|
||
|
||
if ( (ULONG_PTR) InputBuffers->pBuffers < PORT_MAXIMUM_MESSAGE_LENGTH )
|
||
{
|
||
if ( InputBuffers->cBuffers * sizeof( SecBuffer ) > CBPREPACK )
|
||
{
|
||
return STATUS_INVALID_PARAMETER ;
|
||
}
|
||
|
||
LocalCopy = (PSecBuffer) (Base +
|
||
(ULONG_PTR) InputBuffers->pBuffers );
|
||
|
||
RtlCopyMemory(
|
||
MappedBuffers->pBuffers,
|
||
LocalCopy,
|
||
InputBuffers->cBuffers * sizeof( SecBuffer ) );
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// They were too big to fit. Copy them directly from the client
|
||
// process:
|
||
//
|
||
|
||
|
||
Capture = (PSecBufferDesc) LsapAllocatePrivateHeap( sizeof( SecBufferDesc ) +
|
||
sizeof( SecBuffer ) * InputBuffers->cBuffers );
|
||
|
||
if ( Capture == NULL )
|
||
{
|
||
Status = SEC_E_INSUFFICIENT_MEMORY ;
|
||
}
|
||
else
|
||
{
|
||
Capture->pBuffers = (PSecBuffer) (Capture + 1);
|
||
Capture->cBuffers = InputBuffers->cBuffers ;
|
||
Capture->ulVersion = SECBUFFER_VERSION ;
|
||
|
||
Status = LsapCopyFromClient(
|
||
InputBuffers->pBuffers,
|
||
MappedBuffers->pBuffers,
|
||
InputBuffers->cBuffers * sizeof( SecBuffer ) );
|
||
|
||
if ( NT_SUCCESS( Status ) )
|
||
{
|
||
RtlCopyMemory(
|
||
Capture->pBuffers,
|
||
MappedBuffers->pBuffers,
|
||
InputBuffers->cBuffers * sizeof( SecBuffer ) );
|
||
|
||
*CapturedBuffers = Capture ;
|
||
}
|
||
else
|
||
{
|
||
LsapFreePrivateHeap( Capture );
|
||
}
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
if ( !NT_SUCCESS( Status ) )
|
||
{
|
||
for ( i = 0 ; i < MappedBuffers->cBuffers ; i++ )
|
||
{
|
||
MappedBuffers->pBuffers[ i ].BufferType = SECBUFFER_UNMAPPED ;
|
||
}
|
||
return Status ;
|
||
}
|
||
|
||
//
|
||
// Touch up the mapped buffers so that the count is correct
|
||
//
|
||
|
||
MappedBuffers->cBuffers = InputBuffers->cBuffers ;
|
||
|
||
//
|
||
// try to map the security blob one:
|
||
//
|
||
|
||
if ( MapTokenBuffers )
|
||
{
|
||
Status = MapTokenBuffer(
|
||
MappedBuffers,
|
||
TRUE );
|
||
}
|
||
else
|
||
{
|
||
Status = STATUS_SUCCESS ;
|
||
}
|
||
|
||
|
||
return Status ;
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
LsapResetKsecBuffer(
|
||
PKSEC_LSA_MEMORY_HEADER Header
|
||
)
|
||
{
|
||
Header->Consumed = Header->Preserve ;
|
||
Header->MapCount = 0 ;
|
||
RtlZeroMemory( Header->PoolMap, sizeof( KSEC_LSA_POOL_MAP ) * KSEC_LSA_MAX_MAPS );
|
||
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LsapCreateKsecBuffer
|
||
//
|
||
// Synopsis: Creates a kmap buffer to return to ksecdd
|
||
//
|
||
// Arguments: [InitialSize] -- Minimum size of the buffer
|
||
//
|
||
// History: 2-9-01 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
PKSEC_LSA_MEMORY_HEADER
|
||
LsapCreateKsecBuffer(
|
||
SIZE_T InitialSize
|
||
)
|
||
{
|
||
PKSEC_LSA_MEMORY_HEADER Header = NULL ;
|
||
NTSTATUS Status ;
|
||
SIZE_T Size = LSA_MAX_KMAP_SIZE ;
|
||
|
||
|
||
InitialSize += sizeof( KSEC_LSA_MEMORY_HEADER );
|
||
|
||
DsysAssert( InitialSize < Size );
|
||
|
||
Status = NtAllocateVirtualMemory(
|
||
NtCurrentProcess(),
|
||
(PVOID *) &Header,
|
||
0,
|
||
&Size,
|
||
MEM_RESERVE,
|
||
PAGE_READWRITE );
|
||
|
||
if ( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = NtAllocateVirtualMemory(
|
||
NtCurrentProcess(),
|
||
(PVOID *) &Header,
|
||
0,
|
||
&InitialSize,
|
||
MEM_COMMIT,
|
||
PAGE_READWRITE );
|
||
|
||
if ( NT_SUCCESS( Status ) )
|
||
{
|
||
Header->Size = LSA_MAX_KMAP_SIZE ;
|
||
Header->Commit = (ULONG) InitialSize ;
|
||
Header->Preserve = sizeof( KSEC_LSA_MEMORY_HEADER );
|
||
|
||
LsapResetKsecBuffer( Header );
|
||
|
||
}
|
||
else
|
||
{
|
||
NtFreeVirtualMemory(
|
||
NtCurrentProcess(),
|
||
(PVOID *) &Header,
|
||
0,
|
||
MEM_RELEASE );
|
||
|
||
Header = NULL ;
|
||
}
|
||
}
|
||
|
||
return Header ;
|
||
|
||
|
||
}
|
||
|
||
|
||
PVOID
|
||
LsapAllocateFromKsecBuffer(
|
||
PKSEC_LSA_MEMORY_HEADER Header,
|
||
ULONG Size
|
||
)
|
||
{
|
||
|
||
SIZE_T DesiredSize ;
|
||
NTSTATUS Status ;
|
||
PVOID Block ;
|
||
PVOID Page ;
|
||
|
||
|
||
Size = ROUND_UP_COUNT( Size, ALIGN_LPVOID );
|
||
|
||
if ( Header->Consumed + Size > Header->Commit )
|
||
{
|
||
DesiredSize = Header->Commit - Header->Consumed + Size ;
|
||
|
||
DesiredSize = ROUND_UP_COUNT( DesiredSize, LsapPageSize );
|
||
|
||
Page = (PUCHAR) Header + Header->Commit ;
|
||
|
||
Status = NtAllocateVirtualMemory(
|
||
NtCurrentProcess(),
|
||
&Page,
|
||
0,
|
||
&DesiredSize,
|
||
MEM_COMMIT,
|
||
PAGE_READWRITE );
|
||
|
||
if ( NT_SUCCESS( Status ) )
|
||
{
|
||
Header->Commit += (ULONG) DesiredSize ;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
if ( Header->Consumed + Size <= Header->Commit )
|
||
{
|
||
Block = (PVOID) ((PUCHAR) Header + Header->Consumed) ;
|
||
|
||
Header->Consumed += Size ;
|
||
|
||
}
|
||
else
|
||
{
|
||
|
||
Block = NULL ;
|
||
}
|
||
|
||
return Block ;
|
||
}
|
||
|
||
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LsapUncaptureBuffers
|
||
//
|
||
// Synopsis: Return all the buffers to the client process.
|
||
//
|
||
// Arguments: [Base] -- Base address of message
|
||
// [CapturedBuffers]-- Captured buffer descriptions
|
||
// [InputBuffers] -- Buffers supplied by the client
|
||
// [MappedBuffers] -- Mapped buffers
|
||
// [AllocateMemory] -- Allocate memory for
|
||
//
|
||
// History: 8-14-98 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LsapUncaptureBuffers(
|
||
IN PUCHAR Base,
|
||
IN OUT PVOID * CapturedBuffers,
|
||
IN OUT PSecBufferDesc InputBuffers,
|
||
IN OUT PSecBufferDesc MappedBuffers,
|
||
IN BOOL AllocateMemory,
|
||
IN BOOL CopyBack,
|
||
OUT PULONG pFlags
|
||
)
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS ;
|
||
PSecBuffer Buffers ;
|
||
PSecBufferDesc Capture ;
|
||
ULONG i ;
|
||
PVOID Scratch ;
|
||
PVOID ScratchBuffers[ MAX_SECBUFFERS ];
|
||
PSecBufferDesc Input;
|
||
SecBufferDesc InputFixup ;
|
||
PLSA_CALL_INFO CallInfo = LsapGetCurrentCall();
|
||
|
||
DebugLog(( DEB_TRACE_SPECIAL, "LsapUncaptureBuffers:\n" ));
|
||
|
||
RtlZeroMemory( ScratchBuffers, sizeof( ScratchBuffers ) );
|
||
|
||
Capture = (PSecBufferDesc) *CapturedBuffers ;
|
||
|
||
if ( InputBuffers )
|
||
{
|
||
|
||
|
||
if ( Capture )
|
||
{
|
||
DebugLog(( DEB_TRACE_SPECIAL, " using captured buffers\n" ));
|
||
Input = Capture ;
|
||
}
|
||
else
|
||
{
|
||
if ( (ULONG_PTR) InputBuffers->pBuffers < PORT_MAXIMUM_MESSAGE_LENGTH )
|
||
{
|
||
//
|
||
// Time to fix up:
|
||
//
|
||
|
||
InputFixup.pBuffers = (PSecBuffer) (Base + (ULONG_PTR) InputBuffers->pBuffers );
|
||
InputFixup.cBuffers = InputBuffers->cBuffers ;
|
||
InputFixup.ulVersion = SECBUFFER_VERSION ;
|
||
|
||
Input = &InputFixup ;
|
||
DebugLog(( DEB_TRACE_SPECIAL, " using buffers in message\n" ));
|
||
}
|
||
else
|
||
{
|
||
Input = InputBuffers ;
|
||
DebugLog(( DEB_TRACE_SPECIAL, " using buffers from caller\n" ));
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// First, handle the map back to the client process
|
||
//
|
||
|
||
for ( i = 0 ; i < MappedBuffers->cBuffers ; i++ )
|
||
{
|
||
|
||
//
|
||
// If this is a read only buffer, or it was not mapped across,
|
||
// skip it. There is no change that will go back to the client.
|
||
//
|
||
|
||
DebugLog(( DEB_TRACE_SPECIAL, " Processing buffer %d, <t=%x [%c%c%c],cb=%x,pv=%p>\n",
|
||
i,
|
||
MappedBuffers->pBuffers[ i ].BufferType & ~SECBUFFER_ATTRMASK,
|
||
(MappedBuffers->pBuffers[ i ].BufferType & SECBUFFER_READONLY ? 'R' : ' '),
|
||
(MappedBuffers->pBuffers[ i ].BufferType & SECBUFFER_UNMAPPED ? 'U' : ' '),
|
||
(MappedBuffers->pBuffers[ i ].BufferType & SECBUFFER_KERNEL_MAP ? 'K' : ' '),
|
||
MappedBuffers->pBuffers[ i ].cbBuffer,
|
||
MappedBuffers->pBuffers[ i ].pvBuffer ));
|
||
|
||
//
|
||
// For readonly or untouched buffers, skip them.
|
||
//
|
||
|
||
if ( ( MappedBuffers->pBuffers[ i ].BufferType & SECBUFFER_ATTRMASK ) ==
|
||
( SECBUFFER_READONLY | SECBUFFER_UNMAPPED ) )
|
||
{
|
||
DebugLog(( DEB_TRACE_SPECIAL, " Buffer %d: skipped\n", i ));
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// If this is a SSPI security blob (aka a token), decide what
|
||
// needs to be done:
|
||
//
|
||
if ( ( MappedBuffers->pBuffers[ i ].BufferType & (~SECBUFFER_ATTRMASK) )
|
||
== SECBUFFER_TOKEN )
|
||
{
|
||
if ( ( MappedBuffers->pBuffers[ i ].cbBuffer > 0 ) &&
|
||
( CopyBack ) )
|
||
{
|
||
DebugLog(( DEB_TRACE_SPECIAL, " Copying back buffer %d\n", i ));
|
||
|
||
if ( CallInfo->Flags & CALL_FLAG_KMAP_USED )
|
||
{
|
||
//
|
||
// KMap case:
|
||
//
|
||
|
||
Scratch = LsapAllocateFromKsecBuffer(
|
||
CallInfo->KMap,
|
||
MappedBuffers->pBuffers[ i ].cbBuffer
|
||
);
|
||
|
||
if ( !Scratch )
|
||
{
|
||
Status = SEC_E_INSUFFICIENT_MEMORY ;
|
||
break;
|
||
|
||
}
|
||
|
||
*pFlags |= SPMAPI_FLAG_KMAP_MEM ;
|
||
|
||
}
|
||
else if ( AllocateMemory )
|
||
{
|
||
Scratch = LsapClientAllocate(
|
||
MappedBuffers->pBuffers[ i ].cbBuffer
|
||
);
|
||
|
||
//
|
||
// Allocation failed, break out of the loop with a failure
|
||
// status code, and handle the failure there:
|
||
//
|
||
|
||
if ( !Scratch )
|
||
{
|
||
Status = SEC_E_INSUFFICIENT_MEMORY ;
|
||
break;
|
||
}
|
||
|
||
*pFlags |= SPMAPI_FLAG_MEMORY;
|
||
}
|
||
else
|
||
{
|
||
|
||
Scratch = Input->pBuffers[ i ].pvBuffer ;
|
||
if ( Input->pBuffers[ i ].cbBuffer <
|
||
MappedBuffers->pBuffers[ i ].cbBuffer )
|
||
{
|
||
//
|
||
// Buffer too small. Break out and return the failure
|
||
//
|
||
|
||
Status = STATUS_BUFFER_TOO_SMALL ;
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Copy the buffer back to the client address space
|
||
//
|
||
|
||
ScratchBuffers[ i ] = Scratch ;
|
||
|
||
if ( CallInfo->Flags & CALL_FLAG_KMAP_USED )
|
||
{
|
||
DebugLog(( DEB_TRACE_SPECIAL, " Copying %x bytes from %p to %p [KMap]\n",
|
||
MappedBuffers->pBuffers[ i ].cbBuffer,
|
||
MappedBuffers->pBuffers[ i ].pvBuffer,
|
||
Scratch ));
|
||
|
||
RtlCopyMemory(
|
||
Scratch,
|
||
MappedBuffers->pBuffers[ i ].pvBuffer,
|
||
MappedBuffers->pBuffers[ i ].cbBuffer );
|
||
|
||
Status = STATUS_SUCCESS ;
|
||
|
||
}
|
||
else
|
||
{
|
||
DebugLog(( DEB_TRACE_SPECIAL, " Copying %x bytes from %p to %p\n",
|
||
MappedBuffers->pBuffers[ i ].cbBuffer,
|
||
MappedBuffers->pBuffers[ i ].pvBuffer,
|
||
Scratch ));
|
||
|
||
Status = LsapCopyToClient(
|
||
MappedBuffers->pBuffers[ i ].pvBuffer,
|
||
Scratch,
|
||
MappedBuffers->pBuffers[ i ].cbBuffer
|
||
);
|
||
|
||
}
|
||
|
||
if ( !NT_SUCCESS( Status ) )
|
||
{
|
||
break;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// For zero length buffers that appear to be mapped, set scratch
|
||
// equal to the original input value.
|
||
//
|
||
|
||
DebugLog(( DEB_TRACE_SPECIAL, " Zero length buffer\n" ));
|
||
|
||
ScratchBuffers[ i ] = Input->pBuffers[ i ].pvBuffer ;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// This is not a token buffer, it is a EXTRA, or PADDING, or
|
||
// one of those. Turn off the mapping bit, and copy out
|
||
// the buffer value.
|
||
//
|
||
DebugLog(( DEB_TRACE_SPECIAL, " Special buffer [%p] passed back\n",
|
||
Input->pBuffers[ i ].pvBuffer ));
|
||
|
||
ScratchBuffers[ i ] = Input->pBuffers[ i ].pvBuffer ;
|
||
}
|
||
|
||
}
|
||
}
|
||
else
|
||
{
|
||
|
||
DebugLog(( DEB_TRACE_SPECIAL, "InputBuffers is NULL, just walking and freeing\n" ));
|
||
}
|
||
|
||
//
|
||
// Now go through and free any allocated memory
|
||
//
|
||
|
||
for ( i = 0 ; i < MappedBuffers->cBuffers ; i++ )
|
||
{
|
||
if ( (MappedBuffers->pBuffers[ i ].BufferType & SECBUFFER_UNMAPPED) == 0 )
|
||
{
|
||
//
|
||
// This buffer was mapped in. Free it.
|
||
//
|
||
|
||
if ( !LsapIsBlockInKMap( CallInfo->KMap, MappedBuffers->pBuffers[ i ].pvBuffer ) )
|
||
{
|
||
LsapFreeLsaHeap( MappedBuffers->pBuffers[ i ].pvBuffer );
|
||
|
||
}
|
||
else
|
||
{
|
||
DebugLog(( DEB_TRACE_SPECIAL, "Buffer at %p is in KMap\n", MappedBuffers->pBuffers[ i ].pvBuffer ));
|
||
}
|
||
}
|
||
|
||
//
|
||
// Turn off our bit
|
||
//
|
||
|
||
MappedBuffers->pBuffers[ i ].BufferType &= ~(SECBUFFER_UNMAPPED);
|
||
|
||
//
|
||
// If we allocated a new buffer (here or in the client), it's
|
||
// been stored away in the scratch array, and we copy it in
|
||
//
|
||
|
||
|
||
if ( ScratchBuffers[ i ] )
|
||
{
|
||
MappedBuffers->pBuffers[ i ].pvBuffer = ScratchBuffers[ i ];
|
||
}
|
||
}
|
||
|
||
if ( InputBuffers )
|
||
{
|
||
if ( NT_SUCCESS( Status ) )
|
||
{
|
||
//
|
||
// Now, copy back the buffer descriptors. Note that in the normal (optimal)
|
||
// case, this will fit into the LPC message. Otherwise, we have to copy
|
||
|
||
if ( (ULONG_PTR) InputBuffers->pBuffers < PORT_MAXIMUM_MESSAGE_LENGTH )
|
||
{
|
||
Buffers = (PSecBuffer) (Base + (ULONG_PTR) InputBuffers->pBuffers );
|
||
|
||
RtlCopyMemory(
|
||
Buffers,
|
||
MappedBuffers->pBuffers,
|
||
MappedBuffers->cBuffers * sizeof( SecBuffer ) );
|
||
}
|
||
else
|
||
{
|
||
Status = LsapCopyToClient(
|
||
MappedBuffers->pBuffers,
|
||
InputBuffers->pBuffers,
|
||
MappedBuffers->cBuffers * sizeof( SecBuffer ) );
|
||
}
|
||
|
||
InputBuffers->cBuffers = MappedBuffers->cBuffers ;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
if ( Capture )
|
||
{
|
||
LsapFreePrivateHeap( Capture );
|
||
*CapturedBuffers = NULL ;
|
||
}
|
||
|
||
return Status ;
|
||
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LsapChangeBuffer
|
||
//
|
||
// Synopsis: Switches a buffer around. If the old one needs to be freed,
|
||
// it is cleaned up.
|
||
//
|
||
// Arguments: [Old] --
|
||
// [New] --
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
LsapChangeBuffer(
|
||
PSecBuffer Old,
|
||
PSecBuffer New
|
||
)
|
||
{
|
||
if ( ( Old->BufferType & SECBUFFER_KERNEL_MAP ) == 0 )
|
||
{
|
||
if ( ( Old->BufferType & SECBUFFER_UNMAPPED ) == 0 )
|
||
{
|
||
LsapFreeLsaHeap( Old->pvBuffer );
|
||
}
|
||
|
||
}
|
||
|
||
*Old = *New ;
|
||
|
||
return STATUS_SUCCESS ;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LsapCheckMarshalledTargetInfo(
|
||
IN PUNICODE_STRING TargetServerName
|
||
)
|
||
{
|
||
PWSTR Candidate;
|
||
ULONG CandidateSize;
|
||
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
//
|
||
// if target info wasn't supplied, or the length doesn't look like it
|
||
// includes the marshalled version, do nothing.
|
||
//
|
||
|
||
if( (TargetServerName == NULL) ||
|
||
(TargetServerName->Buffer == NULL) ||
|
||
(TargetServerName->Length < (sizeof( CREDENTIAL_TARGET_INFORMATIONW ) / (sizeof(ULONG_PTR)/2)) )
|
||
)
|
||
{
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
RtlCopyMemory(
|
||
&CandidateSize,
|
||
(PBYTE)TargetServerName->Buffer + TargetServerName->Length - sizeof(ULONG),
|
||
sizeof( CandidateSize )
|
||
);
|
||
|
||
if( TargetServerName->Length <= CandidateSize )
|
||
{
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
Candidate = (PWSTR)(
|
||
(PBYTE)TargetServerName->Buffer + TargetServerName->Length - CandidateSize
|
||
);
|
||
|
||
Status = CredUnmarshalTargetInfo (
|
||
Candidate,
|
||
CandidateSize,
|
||
NULL
|
||
);
|
||
|
||
if( !NT_SUCCESS(Status) )
|
||
{
|
||
if( Status == STATUS_INVALID_PARAMETER )
|
||
{
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
} else {
|
||
|
||
//
|
||
// marshalled information was found. adjust the Length to
|
||
// represent the non-marshalled content, and MaximumLength to
|
||
// include non-marshalled+marshalled content. This allows legacy
|
||
// packages to continue to handle the TargetServerName string properly.
|
||
//
|
||
|
||
TargetServerName->MaximumLength = TargetServerName->Length;
|
||
TargetServerName->Length -= (USHORT)CandidateSize;
|
||
}
|
||
|
||
return Status ;
|
||
}
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcInitContext()
|
||
//
|
||
// Synopsis: LPC Serverside InitializeSecurityContext
|
||
//
|
||
// Notes: OutputBuffers and LocalOutput are the local copy of the
|
||
// output buffers. The secbuffers in the ApiMessage point
|
||
// to client addresses.
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcInitContext(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
|
||
{
|
||
UNICODE_STRING ssTarget = {0,0,NULL};
|
||
NTSTATUS scApiRet;
|
||
NTSTATUS scRet;
|
||
ULONG i;
|
||
PSecBufferDesc pOutput = NULL;
|
||
PSecBufferDesc pInput = NULL;
|
||
PVOID CapturedInput = NULL ;
|
||
PVOID CapturedOutput = NULL ;
|
||
SecBufferDesc LocalOutput;
|
||
SecBufferDesc LocalInput ;
|
||
SPMInitContextAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.InitContext;
|
||
PUCHAR Where = NULL;
|
||
SecBuffer ContextData = {0,0,NULL};
|
||
SecBuffer OutputBuffers[MAX_SECBUFFERS];
|
||
SecBuffer InputBuffers[MAX_SECBUFFERS];
|
||
PSession pSession ;
|
||
BOOLEAN MappedOutput = FALSE;
|
||
BOOLEAN FirstCall ;
|
||
DWORD Flags ;
|
||
PLSA_CALL_INFO CallInfo = LsapGetCurrentCall();
|
||
|
||
|
||
pSession = GetCurrentSession();
|
||
|
||
|
||
DebugLog((DEB_TRACE, "[%x] LpcInitContext()\n", pSession->dwProcessID));
|
||
|
||
DebugLog((DEB_TRACE_VERB, " hCredentials = %d:%d\n",
|
||
pArgs->hCredential.dwUpper,
|
||
pArgs->hCredential.dwLower));
|
||
|
||
|
||
|
||
//
|
||
// Copy target string to local space:
|
||
//
|
||
|
||
|
||
scRet = GetClientString(&pArgs->ssTarget,
|
||
&ssTarget,
|
||
pApiMessage,
|
||
&Where);
|
||
if (FAILED(scRet))
|
||
{
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
DebugLog((DEB_ERROR, "LpcInitContext, no target, error %x\n", scRet));
|
||
return(scRet);
|
||
}
|
||
|
||
//
|
||
// check if the caller supplied marshalled target info.
|
||
// this will update the Length and MaximumLength fields
|
||
// if marshalled info was present.
|
||
//
|
||
|
||
LsapCheckMarshalledTargetInfo( &ssTarget );
|
||
|
||
//
|
||
// Set all the SecBuffer's to be unmapped, but map the Security token
|
||
//
|
||
|
||
LocalInput.pBuffers = InputBuffers ;
|
||
LocalInput.ulVersion = SECBUFFER_VERSION ;
|
||
|
||
if (pArgs->sbdInput.cBuffers)
|
||
{
|
||
|
||
pInput = &pArgs->sbdInput;
|
||
|
||
//
|
||
// If there is a buffer, reset the pointer and
|
||
// map it
|
||
//
|
||
|
||
LocalInput.cBuffers = MAX_SECBUFFERS ;
|
||
|
||
scRet = LsapCaptureBuffers(
|
||
(PUCHAR) pArgs,
|
||
pInput,
|
||
&LocalInput,
|
||
&CapturedInput,
|
||
TRUE );
|
||
|
||
if ( !NT_SUCCESS( scRet ) )
|
||
{
|
||
pInput = NULL ;
|
||
scApiRet = scRet ;
|
||
goto InitCleanExit ;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
LocalInput.pBuffers = InputBuffers ;
|
||
LocalInput.cBuffers = 0 ;
|
||
LocalInput.ulVersion = SECBUFFER_VERSION ;
|
||
}
|
||
|
||
//
|
||
// Copy the output SecBuffer's so that if they get mapped we can
|
||
// still copy back the data
|
||
//
|
||
|
||
pOutput = &pArgs->sbdOutput;
|
||
if (pOutput->cBuffers)
|
||
{
|
||
LocalOutput.cBuffers = MAX_SECBUFFERS ;
|
||
LocalOutput.pBuffers = OutputBuffers;
|
||
LocalOutput.ulVersion = SECBUFFER_VERSION ;
|
||
|
||
scRet = LsapCaptureBuffers(
|
||
(PUCHAR) pArgs,
|
||
pOutput,
|
||
&LocalOutput,
|
||
&CapturedOutput,
|
||
FALSE );
|
||
|
||
|
||
if ( !NT_SUCCESS( scRet ) )
|
||
{
|
||
scApiRet = scRet ;
|
||
goto Init_FreeStringAndExit ;
|
||
}
|
||
|
||
|
||
MappedOutput = TRUE;
|
||
}
|
||
else
|
||
{
|
||
LocalOutput.cBuffers = 0 ;
|
||
LocalOutput.pBuffers = OutputBuffers ;
|
||
LocalOutput.ulVersion = SECBUFFER_VERSION ;
|
||
}
|
||
|
||
if (pArgs->sbdOutput.cBuffers &&
|
||
!(pArgs->fContextReq & ISC_REQ_ALLOCATE_MEMORY))
|
||
{
|
||
if (FAILED(scRet = MapTokenBuffer(&LocalOutput, FALSE)))
|
||
{
|
||
scApiRet = scRet;
|
||
goto InitCleanExit;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Call the worker for relay to the package:
|
||
//
|
||
|
||
if ( ( pArgs->hContext.dwUpper == 0 ) &&
|
||
( pArgs->hContext.dwLower == 0 ) )
|
||
{
|
||
FirstCall = TRUE ;
|
||
}
|
||
else
|
||
{
|
||
FirstCall = FALSE ;
|
||
}
|
||
|
||
scApiRet = WLsaInitContext( &pArgs->hCredential,
|
||
&pArgs->hContext,
|
||
(PSECURITY_STRING) &ssTarget,
|
||
pArgs->fContextReq,
|
||
pArgs->dwReserved1,
|
||
pArgs->TargetDataRep,
|
||
&LocalInput, // &pArgs->sbdInput,
|
||
pArgs->dwReserved2,
|
||
&pArgs->hNewContext,
|
||
&LocalOutput,
|
||
&pArgs->fContextAttr,
|
||
&pArgs->tsExpiry,
|
||
&pArgs->MappedContext,
|
||
&ContextData );
|
||
|
||
// DsysAssert( scApiRet != SEC_E_INVALID_HANDLE );
|
||
if( scApiRet == SEC_E_INVALID_HANDLE ||
|
||
scApiRet == STATUS_INVALID_HANDLE )
|
||
{
|
||
DebugLog((DEB_ERROR, "[%x] LpcInitContext() returning invalid handle\n", pSession->dwProcessID));
|
||
|
||
DebugLog((DEB_ERROR, " hCredentials = %p:%p\n",
|
||
pArgs->hCredential.dwUpper,
|
||
pArgs->hCredential.dwLower));
|
||
DebugLog((DEB_ERROR, " hContext = %p:%p\n",
|
||
pArgs->hContext.dwUpper,
|
||
pArgs->hContext.dwLower));
|
||
|
||
DsysAssert( scApiRet == STATUS_SUCCESS );
|
||
}
|
||
|
||
//
|
||
// Reset the reply flags:
|
||
//
|
||
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
|
||
//
|
||
// If this is the failure case, don't bother copying everything down.
|
||
//
|
||
|
||
if (FAILED(scApiRet))
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
|
||
//
|
||
// Unmap any output buffers
|
||
//
|
||
|
||
Flags = 0 ;
|
||
|
||
scRet = LsapUncaptureBuffers(
|
||
(PUCHAR) pArgs,
|
||
&CapturedOutput,
|
||
&pArgs->sbdOutput,
|
||
&LocalOutput,
|
||
FALSE,
|
||
FALSE,
|
||
&Flags );
|
||
|
||
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Now we have to look at the output and copy all the mapped
|
||
// buffers back.
|
||
//
|
||
|
||
Flags = pApiMessage->ApiMessage.Args.SpmArguments.fAPI ;
|
||
|
||
//
|
||
// if a KMap is present, use it.
|
||
//
|
||
|
||
if ( CallInfo->KMap )
|
||
{
|
||
CallInfo->Flags |= CALL_FLAG_KMAP_USED ;
|
||
}
|
||
|
||
scRet = LsapUncaptureBuffers(
|
||
(PUCHAR) pArgs,
|
||
&CapturedOutput,
|
||
&pArgs->sbdOutput,
|
||
&LocalOutput,
|
||
(pArgs->fContextReq & ISC_REQ_ALLOCATE_MEMORY) ? TRUE : FALSE,
|
||
TRUE,
|
||
&Flags );
|
||
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI = (USHORT) Flags ;
|
||
|
||
if (NT_SUCCESS(scRet) && (ContextData.cbBuffer != 0))
|
||
{
|
||
pArgs->ContextData = ContextData;
|
||
pArgs->ContextData.pvBuffer = LsapClientAllocate(ContextData.cbBuffer);
|
||
if ( pArgs->ContextData.pvBuffer )
|
||
{
|
||
scRet = LsapCopyToClient(
|
||
ContextData.pvBuffer,
|
||
pArgs->ContextData.pvBuffer,
|
||
ContextData.cbBuffer
|
||
);
|
||
}
|
||
else
|
||
{
|
||
scRet = SEC_E_INSUFFICIENT_MEMORY ;
|
||
}
|
||
}
|
||
|
||
|
||
if (FAILED(scRet))
|
||
{
|
||
//
|
||
// Again, we have a real problem when this fails. We
|
||
// abort the context and return an error.
|
||
//
|
||
|
||
if ( FirstCall )
|
||
{
|
||
AbortLpcContext(&pArgs->hContext);
|
||
}
|
||
|
||
scApiRet = scRet;
|
||
|
||
goto InitCleanExit;
|
||
|
||
}
|
||
|
||
|
||
|
||
}
|
||
|
||
InitCleanExit:
|
||
|
||
pApiMessage->ApiMessage.scRet = scApiRet;
|
||
|
||
//
|
||
// Unmap the input buffers
|
||
//
|
||
|
||
|
||
scRet = LsapUncaptureBuffers(
|
||
(PUCHAR) pArgs,
|
||
&CapturedInput,
|
||
&pArgs->sbdInput,
|
||
&LocalInput,
|
||
FALSE,
|
||
FALSE,
|
||
NULL );
|
||
|
||
|
||
if (ContextData.pvBuffer != NULL)
|
||
{
|
||
LsapFreeLsaHeap(ContextData.pvBuffer);
|
||
}
|
||
|
||
if (FAILED(scRet) && (pArgs->ContextData.pvBuffer != NULL))
|
||
{
|
||
LsapClientFree(pArgs->ContextData.pvBuffer);
|
||
pArgs->ContextData.pvBuffer;
|
||
|
||
}
|
||
|
||
Init_FreeStringAndExit:
|
||
|
||
|
||
//
|
||
// Test the string pointer. If it is within the KMap, do
|
||
// not free it. If there is no KMap, or it was separately
|
||
// allocated, free it:
|
||
//
|
||
|
||
if ( !LsapIsBlockInKMap( CallInfo->KMap, ssTarget.Buffer ) )
|
||
{
|
||
LsapFreePrivateHeap( ssTarget.Buffer );
|
||
|
||
}
|
||
|
||
return(scRet);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcAcceptContext()
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes: The memory management is kind of weird. The input buffers
|
||
// are mapped into the SPMgr's memory and can be freed. Easy.
|
||
// The output buffers are more complex. The original buffer
|
||
// pointers are kep in the arguments structure, while the
|
||
// local copies are kept in LocalOutput.
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcAcceptContext(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
|
||
{
|
||
NTSTATUS scRet = S_OK;
|
||
NTSTATUS scApiRet;
|
||
PSession pSession ;
|
||
ULONG i;
|
||
SecBufferDesc LocalOutput;
|
||
SecBufferDesc LocalInput ;
|
||
PSecBufferDesc pInput = NULL;
|
||
PSecBufferDesc pOutput = NULL ;
|
||
SPMAcceptContextAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.AcceptContext;
|
||
BOOLEAN MappedOutput = FALSE;
|
||
BOOLEAN FirstCall ;
|
||
BOOL CopyBack = FALSE ;
|
||
DWORD Flags ;
|
||
PVOID CapturedInput = NULL ;
|
||
PVOID CapturedOutput = NULL ;
|
||
|
||
|
||
SecBuffer OutputBuffers[MAX_SECBUFFERS];
|
||
SecBuffer InputBuffers[MAX_SECBUFFERS];
|
||
SecBuffer ContextData = {0,0,NULL};
|
||
PLSA_CALL_INFO CallInfo = LsapGetCurrentCall();
|
||
|
||
pSession = GetCurrentSession();
|
||
|
||
DebugLog((DEB_TRACE, "[%x] LpcAcceptContext\n", pSession->dwProcessID));
|
||
|
||
// Copy input token to local space:
|
||
//
|
||
// Set all the SecBuffer's to be unmapped, but map the Security token
|
||
//
|
||
|
||
pInput = &pArgs->sbdInput;
|
||
|
||
LocalInput.pBuffers = InputBuffers ;
|
||
LocalInput.cBuffers = MAX_SECBUFFERS ;
|
||
LocalInput.ulVersion = SECBUFFER_VERSION ;
|
||
|
||
if (pInput->cBuffers)
|
||
{
|
||
|
||
scRet = LsapCaptureBuffers(
|
||
(PUCHAR) pArgs,
|
||
pInput,
|
||
&LocalInput,
|
||
&CapturedInput,
|
||
TRUE );
|
||
|
||
|
||
if ( !NT_SUCCESS( scRet ) )
|
||
{
|
||
scApiRet = scRet;
|
||
goto AcceptCleanExit;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
LocalInput.cBuffers = 0 ;
|
||
}
|
||
|
||
//
|
||
// Copy the output SecBuffer's so that if they get mapped we can
|
||
// still copy back the data
|
||
//
|
||
|
||
|
||
LocalOutput.cBuffers = MAX_SECBUFFERS ;
|
||
LocalOutput.pBuffers = OutputBuffers ;
|
||
LocalOutput.ulVersion = SECBUFFER_VERSION ;
|
||
|
||
pOutput = &pArgs->sbdOutput ;
|
||
|
||
if ( pOutput->cBuffers )
|
||
{
|
||
scRet = LsapCaptureBuffers(
|
||
(PUCHAR) pArgs,
|
||
pOutput,
|
||
&LocalOutput,
|
||
&CapturedOutput,
|
||
FALSE );
|
||
|
||
if ( !NT_SUCCESS( scRet ) )
|
||
{
|
||
scApiRet = scRet ;
|
||
|
||
goto AcceptCleanExit ;
|
||
}
|
||
|
||
#if DBG
|
||
if ( (pArgs->fContextReq & ASC_REQ_ALLOCATE_MEMORY ) == 0 )
|
||
{
|
||
for ( i = 0 ; i < LocalOutput.cBuffers ; i++ )
|
||
{
|
||
if ( (LocalOutput.pBuffers[ i ].BufferType & (~SECBUFFER_ATTRMASK)) == SECBUFFER_TOKEN )
|
||
{
|
||
DsysAssert( LocalOutput.pBuffers[ i ].cbBuffer > 0 );
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
#endif
|
||
|
||
}
|
||
else
|
||
{
|
||
LocalOutput.cBuffers = 0 ;
|
||
}
|
||
|
||
|
||
MappedOutput = TRUE;
|
||
if (LocalOutput.cBuffers &&
|
||
!(pArgs->fContextReq & ASC_REQ_ALLOCATE_MEMORY))
|
||
{
|
||
|
||
|
||
if (FAILED(scRet = MapTokenBuffer(&LocalOutput,FALSE)))
|
||
{
|
||
scApiRet = scRet;
|
||
goto AcceptCleanExit;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Since they asked us to allocate memory, ensure the output
|
||
// buffers are NULL.
|
||
//
|
||
|
||
for (i = 0; i < LocalOutput.cBuffers ; i++ )
|
||
{
|
||
LocalOutput.pBuffers[i].pvBuffer = NULL;
|
||
}
|
||
}
|
||
|
||
if ( ( pArgs->hContext.dwUpper == 0 ) &&
|
||
( pArgs->hContext.dwLower == 0 ) )
|
||
{
|
||
FirstCall = TRUE ;
|
||
}
|
||
else
|
||
{
|
||
FirstCall = FALSE ;
|
||
}
|
||
|
||
scApiRet = WLsaAcceptContext( &pArgs->hCredential,
|
||
&pArgs->hContext,
|
||
&LocalInput,
|
||
pArgs->fContextReq,
|
||
pArgs->TargetDataRep,
|
||
&pArgs->hNewContext,
|
||
&LocalOutput,
|
||
&pArgs->fContextAttr,
|
||
&pArgs->tsExpiry,
|
||
&pArgs->MappedContext,
|
||
&ContextData );
|
||
|
||
//
|
||
// Reset the reply flags:
|
||
//
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET;
|
||
|
||
|
||
if (FAILED(scApiRet))
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
|
||
//
|
||
// Copy the sizes from the output security buffers in case they
|
||
// are used to indicate how much space is required
|
||
//
|
||
|
||
if ((pArgs->fContextAttr & ASC_RET_EXTENDED_ERROR) == 0)
|
||
{
|
||
CopyBack = FALSE ;
|
||
}
|
||
else
|
||
{
|
||
CopyBack = TRUE ;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
CopyBack = TRUE ;
|
||
}
|
||
|
||
//
|
||
// Turn on this flag on return, so that all allocations will come
|
||
// out of the map. This is safe because KMap would only be set
|
||
// for the right callers.
|
||
//
|
||
if ( CallInfo->KMap )
|
||
{
|
||
CallInfo->Flags |= CALL_FLAG_KMAP_USED ;
|
||
}
|
||
|
||
if (NT_SUCCESS(scRet) && (ContextData.cbBuffer != 0))
|
||
{
|
||
pArgs->ContextData = ContextData;
|
||
pArgs->ContextData.pvBuffer = LsapClientAllocate(ContextData.cbBuffer);
|
||
if (pArgs->ContextData.pvBuffer == NULL)
|
||
{
|
||
scRet = SEC_E_INSUFFICIENT_MEMORY;
|
||
}
|
||
else
|
||
{
|
||
scRet = LsapCopyToClient(
|
||
ContextData.pvBuffer,
|
||
pArgs->ContextData.pvBuffer,
|
||
ContextData.cbBuffer
|
||
);
|
||
|
||
if ( !NT_SUCCESS( scRet ) )
|
||
{
|
||
DebugLog(( DEB_ERROR, "Copy to Client failed, %x. Client addr %p, size %#x\n",
|
||
scRet, pArgs->ContextData.pvBuffer, ContextData.cbBuffer ));
|
||
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
if ( NT_SUCCESS( scRet ) )
|
||
{
|
||
Flags = pApiMessage->ApiMessage.Args.SpmArguments.fAPI ;
|
||
|
||
#if DBG
|
||
if ( ( scRet == SEC_I_CONTINUE_NEEDED ) &&
|
||
( LocalInput.pBuffers[0].cbBuffer < 2048 ) )
|
||
{
|
||
ULONG t ;
|
||
|
||
for ( t = 0 ; t < LocalOutput.cBuffers ; t++ )
|
||
{
|
||
if ( ( LocalOutput.pBuffers[ t ].BufferType & 0xFFFF ) == SECBUFFER_TOKEN )
|
||
{
|
||
DsysAssert( LocalOutput.pBuffers[ t ].cbBuffer > 0 );
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
}
|
||
#endif
|
||
|
||
scRet = LsapUncaptureBuffers(
|
||
(PUCHAR) pArgs,
|
||
&CapturedOutput,
|
||
&pArgs->sbdOutput,
|
||
&LocalOutput,
|
||
(pArgs->fContextReq & ASC_REQ_ALLOCATE_MEMORY ) ? TRUE : FALSE,
|
||
CopyBack,
|
||
&Flags );
|
||
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI = (USHORT) Flags ;
|
||
|
||
}
|
||
|
||
|
||
if (FAILED(scRet))
|
||
{
|
||
|
||
if ( FirstCall )
|
||
{
|
||
AbortLpcContext(&pArgs->hNewContext);
|
||
}
|
||
|
||
if( scRet == SEC_E_INSUFFICIENT_MEMORY )
|
||
{
|
||
DebugLog((DEB_ERROR,"[%x] Accept Failed, low memory handle passed: %p:%p\n",
|
||
pSession->dwProcessID,
|
||
pArgs->hNewContext.dwUpper,
|
||
pArgs->hNewContext.dwLower
|
||
));
|
||
}
|
||
|
||
//
|
||
// Turn off any flags that would cause the client to try and send
|
||
// an invalid blob:
|
||
//
|
||
|
||
pArgs->fContextAttr &= ~ ( ASC_RET_EXTENDED_ERROR );
|
||
|
||
scApiRet = scRet;
|
||
|
||
goto AcceptCleanExit;
|
||
}
|
||
|
||
|
||
AcceptCleanExit:
|
||
|
||
pApiMessage->ApiMessage.scRet = scApiRet;
|
||
|
||
//
|
||
// This is cool. Either I allocated the buffer, and I can free it this
|
||
// way, or the package allocated it. If the package allocated, then the
|
||
// address is in this buffer, and I free it. So cool.
|
||
//
|
||
|
||
scRet = LsapUncaptureBuffers(
|
||
(PUCHAR) pArgs,
|
||
&CapturedInput,
|
||
&pArgs->sbdInput,
|
||
&LocalInput,
|
||
FALSE,
|
||
FALSE,
|
||
NULL );
|
||
|
||
if (ContextData.pvBuffer != NULL)
|
||
{
|
||
LsapFreeLsaHeap(ContextData.pvBuffer);
|
||
}
|
||
|
||
if (FAILED(scRet) && (pArgs->ContextData.pvBuffer != NULL))
|
||
{
|
||
LsapClientFree(pArgs->ContextData.pvBuffer);
|
||
pArgs->ContextData.pvBuffer = NULL;
|
||
}
|
||
|
||
|
||
return(scRet);
|
||
}
|
||
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcEstablishCreds
|
||
//
|
||
// Synopsis: Lpc stub for WLsaEstablishCreds()
|
||
//
|
||
// Notes: obsolete
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcEstablishCreds(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
pApiMessage->ApiMessage.scRet = STATUS_NOT_SUPPORTED ;
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
|
||
return STATUS_SUCCESS ;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcDeleteContext
|
||
//
|
||
// Synopsis: Delete context
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcDeleteContext(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS scRet;
|
||
SPMDeleteContextAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.DeleteContext;
|
||
|
||
|
||
scRet = WLsaDeleteContext( &pArgs->hContext );
|
||
|
||
//
|
||
// Reset the reply flags:
|
||
//
|
||
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
|
||
|
||
return(S_OK);
|
||
}
|
||
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcGetBinding
|
||
//
|
||
// Synopsis: Get the DLL binding info for a package
|
||
//
|
||
// Arguments: [pApiMessage] --
|
||
//
|
||
// History: 8-14-98 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcGetBinding(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
SPMGetBindingAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.GetBinding;
|
||
NTSTATUS scRet;
|
||
ULONG Size;
|
||
PWSTR Base;
|
||
PWSTR Remote;
|
||
|
||
pArgs->BindingInfo.PackageName.Buffer = NULL ;
|
||
pArgs->BindingInfo.Comment.Buffer = NULL ;
|
||
|
||
scRet = WLsaGetBinding( pArgs->ulPackageId,
|
||
&pArgs->BindingInfo,
|
||
&Size,
|
||
&Base );
|
||
|
||
if (SUCCEEDED(scRet))
|
||
{
|
||
//
|
||
// We succeeded so now we have to copy the two strings
|
||
//
|
||
|
||
Remote = (PWSTR) LsapClientAllocate( Size );
|
||
|
||
if (Remote != NULL)
|
||
{
|
||
LsapCopyToClient( Base, Remote, Size );
|
||
|
||
pArgs->BindingInfo.PackageName.Buffer = Remote ;
|
||
pArgs->BindingInfo.Comment.Buffer = Remote +
|
||
pArgs->BindingInfo.PackageName.MaximumLength / 2;
|
||
|
||
pArgs->BindingInfo.ModuleName.Buffer = pArgs->BindingInfo.Comment.Buffer +
|
||
pArgs->BindingInfo.Comment.MaximumLength / 2;
|
||
}
|
||
else
|
||
{
|
||
scRet = SEC_E_INSUFFICIENT_MEMORY;
|
||
}
|
||
|
||
LsapFreeLsaHeap( Base );
|
||
|
||
}
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
|
||
return(scRet);
|
||
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcSetSession
|
||
//
|
||
// Synopsis: Internal function to set session options, including the
|
||
// hook to do direct calls while in-process.
|
||
//
|
||
// Arguments: [pApiMessage] --
|
||
//
|
||
// History: 8-14-98 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcSetSession(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS scRet;
|
||
SPMSetSessionAPI * Args = &pApiMessage->ApiMessage.Args.SpmArguments.API.SetSession ;
|
||
|
||
DebugLog((DEB_TRACE_VERB,"SetSession\n"));
|
||
|
||
scRet = LsapSetSessionOptions( Args->Request,
|
||
Args->Argument,
|
||
&Args->Response );
|
||
|
||
pApiMessage->ApiMessage.scRet = STATUS_SUCCESS;
|
||
|
||
return(scRet);
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcFindPackage
|
||
//
|
||
// Synopsis: Locates a package by id
|
||
//
|
||
// Arguments: [pApiMessage] --
|
||
//
|
||
// History: 8-14-98 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcFindPackage(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS scRet;
|
||
SECURITY_STRING ssPackageName;
|
||
SPMFindPackageAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.FindPackage;
|
||
PUCHAR Where = NULL;
|
||
|
||
scRet = GetClientString(&pArgs->ssPackageName,&ssPackageName, pApiMessage, &Where);
|
||
if (FAILED(scRet))
|
||
{
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
return(scRet);
|
||
}
|
||
|
||
DebugLog((DEB_TRACE_VERB,"Find Package called for %wZ\n",&ssPackageName));
|
||
|
||
scRet = WLsaFindPackage(&ssPackageName,&pArgs->ulPackageId);
|
||
|
||
LsapFreePrivateHeap(ssPackageName.Buffer);
|
||
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
return(scRet);
|
||
|
||
}
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcEnumPackages
|
||
//
|
||
// Synopsis: Enumerate available packages
|
||
//
|
||
// Arguments: [pApiMessage] --
|
||
//
|
||
// History: 8-14-98 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcEnumPackages(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS scRet;
|
||
SPMEnumPackagesAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.EnumPackages;
|
||
|
||
scRet = WLsaEnumeratePackages(&pArgs->cPackages,&pArgs->pPackages);
|
||
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
return(scRet);
|
||
|
||
}
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcApplyToken
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
LpcApplyToken(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS scRet;
|
||
SPMApplyTokenAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.ApplyToken;
|
||
ULONG i;
|
||
|
||
|
||
|
||
pArgs->sbdInput.pBuffers = pArgs->sbInputBuffer;
|
||
|
||
scRet = MapTokenBuffer(&pArgs->sbdInput, TRUE);
|
||
if (FAILED(scRet))
|
||
{
|
||
return(SEC_E_INSUFFICIENT_MEMORY);
|
||
}
|
||
|
||
scRet = WLsaApplyControlToken( &pArgs->hContext,
|
||
&pArgs->sbdInput);
|
||
|
||
//
|
||
// Reset the reply flags:
|
||
//
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
|
||
|
||
for (i = 0; i < pArgs->sbdInput.cBuffers; i++ )
|
||
{
|
||
if (!(pArgs->sbdInput.pBuffers[i].BufferType & SECBUFFER_UNMAPPED))
|
||
{
|
||
LsapFreeLsaHeap(pArgs->sbdInput.pBuffers[i].pvBuffer);
|
||
}
|
||
}
|
||
|
||
|
||
return(scRet);
|
||
}
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcQueryPackage
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcQueryPackage(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS scRet;
|
||
SPMQueryPackageAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.QueryPackage;
|
||
SECURITY_STRING ssPackageName;
|
||
BOOLEAN fNameAlloc = FALSE;
|
||
BOOLEAN fCommentAlloc = FALSE;
|
||
LPWSTR pszNameString = NULL;
|
||
LPWSTR pszCommentString = NULL;
|
||
ULONG cbLength;
|
||
PUCHAR Where = NULL;
|
||
|
||
|
||
|
||
scRet = GetClientString(&pArgs->ssPackageName,&ssPackageName, pApiMessage, &Where);
|
||
if (FAILED(scRet))
|
||
{
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
return(scRet);
|
||
}
|
||
|
||
DebugLog((DEB_TRACE_VERB,"Querying package %wZ\n",&ssPackageName));
|
||
|
||
scRet = WLsaQueryPackageInfo( &ssPackageName,
|
||
&pArgs->pPackageInfo);
|
||
|
||
//
|
||
// Reset the reply flags:
|
||
//
|
||
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
DebugLog((DEB_TRACE_VERB,"Querying package returned %x\n",scRet));
|
||
|
||
LsapFreePrivateHeap(ssPackageName.Buffer);
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
|
||
return(scRet);
|
||
}
|
||
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcGetUserInfo
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcGetUserInfo(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS scRet;
|
||
static LUID lFake = {0,0};
|
||
SPMGetUserInfoAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.GetUserInfo;
|
||
PLUID pLogonId;
|
||
|
||
if ((pArgs->LogonId.LowPart == 0) &&
|
||
(pArgs->LogonId.HighPart == 0))
|
||
{
|
||
pLogonId = NULL;
|
||
}
|
||
else pLogonId = &pArgs->LogonId;
|
||
|
||
scRet = WLsaGetSecurityUserInfo(
|
||
pLogonId,
|
||
pArgs->fFlags,
|
||
&pArgs->pUserInfo
|
||
);
|
||
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
return(scRet);
|
||
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcGetCreds
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
LpcGetCreds(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS scRet;
|
||
SPMGetCredsAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.GetCreds;
|
||
|
||
scRet = SEC_E_UNSUPPORTED_FUNCTION;
|
||
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
|
||
//
|
||
// It is up to the package to do the right thing with the
|
||
// buffer (for now).
|
||
//
|
||
|
||
return(scRet);
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcSaveCreds
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
LpcSaveCreds(PSPM_LPC_MESSAGE pApiMessage)
|
||
{
|
||
NTSTATUS scRet;
|
||
SPMSaveCredsAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.SaveCreds;
|
||
|
||
scRet = SEC_E_UNSUPPORTED_FUNCTION;
|
||
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
|
||
|
||
return(scRet);
|
||
}
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcDeleteCreds
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcDeleteCreds(PSPM_LPC_MESSAGE pApiMessage)
|
||
{
|
||
NTSTATUS scRet;
|
||
SPMDeleteCredsAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.DeleteCreds;
|
||
|
||
scRet = SEC_E_UNSUPPORTED_FUNCTION;
|
||
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
|
||
|
||
return(scRet);
|
||
}
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcLsaLookupPackage
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcLsaLookupPackage(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
PLSAP_AU_API_MESSAGE pLsaMessage = (PLSAP_AU_API_MESSAGE) pApiMessage;
|
||
UNICODE_STRING sPackageName;
|
||
ANSI_STRING sAnsiName;
|
||
PLSAP_SECURITY_PACKAGE pspPackage;
|
||
NTSTATUS Status;
|
||
|
||
//
|
||
// First, convert ANSI name to UNICODE
|
||
//
|
||
|
||
if ( pLsaMessage->Arguments.LookupPackage.PackageNameLength >
|
||
LSAP_MAX_PACKAGE_NAME_LENGTH )
|
||
{
|
||
return STATUS_INVALID_PARAMETER ;
|
||
}
|
||
|
||
sAnsiName.Length = (USHORT) pLsaMessage->Arguments.LookupPackage.PackageNameLength;
|
||
sAnsiName.MaximumLength = LSAP_MAX_PACKAGE_NAME_LENGTH+1;
|
||
sAnsiName.Buffer = pLsaMessage->Arguments.LookupPackage.PackageName;
|
||
|
||
Status = RtlAnsiStringToUnicodeString(&sPackageName, &sAnsiName, TRUE);
|
||
if ( !NT_SUCCESS(Status) )
|
||
{
|
||
pLsaMessage->Arguments.LookupPackage.AuthenticationPackage = (ULONG) -1;
|
||
pLsaMessage->ReturnedStatus = Status;
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Now, look up the package.
|
||
//
|
||
pspPackage = SpmpLookupPackage(&sPackageName);
|
||
|
||
if (pspPackage)
|
||
{
|
||
pLsaMessage->Arguments.LookupPackage.AuthenticationPackage = (DWORD) pspPackage->dwPackageID;
|
||
pLsaMessage->ReturnedStatus = STATUS_SUCCESS;
|
||
}
|
||
else
|
||
{
|
||
pLsaMessage->Arguments.LookupPackage.AuthenticationPackage = (ULONG) -1;
|
||
pLsaMessage->ReturnedStatus = STATUS_NO_SUCH_PACKAGE;
|
||
}
|
||
RtlFreeUnicodeString(&sPackageName);
|
||
}
|
||
|
||
return(S_OK);
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcLsaDeregisterLogonProcess
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcLsaDeregisterLogonProcess(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
PLSAP_AU_API_MESSAGE pLsaMessage = (PLSAP_AU_API_MESSAGE) pApiMessage;
|
||
|
||
|
||
//
|
||
// The client side will close the handle (or not, not a big deal), and
|
||
// we will run down the session at that time. Safer that way, as well.
|
||
//
|
||
|
||
|
||
pLsaMessage->ReturnedStatus = STATUS_SUCCESS;
|
||
|
||
return(S_OK);
|
||
}
|
||
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcLsaLogonUser
|
||
//
|
||
// Synopsis: Unmarshalls everything for a call to WLsaLogonUserWhoopee
|
||
//
|
||
// Arguments: [pApiMessage] --
|
||
//
|
||
// History: 6-14-94 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcLsaLogonUser(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS Status;
|
||
LSAP_CLIENT_REQUEST ClientRequest;
|
||
PLSAP_AU_API_MESSAGE pLsaMessage = (PLSAP_AU_API_MESSAGE) pApiMessage;
|
||
PSession Session = GetCurrentSession();
|
||
|
||
ClientRequest.Request = (PLSAP_AU_API_MESSAGE) pApiMessage;
|
||
|
||
pLsaMessage->ReturnedStatus = LsapAuApiDispatchLogonUser(&ClientRequest);
|
||
|
||
if ( NT_SUCCESS( pLsaMessage->ReturnedStatus ) )
|
||
{
|
||
if ( ( pLsaMessage->Arguments.LogonUser.LogonType == Interactive ) &&
|
||
( pLsaMessage->Arguments.LogonUser.ProfileBuffer == NULL ) )
|
||
{
|
||
DsysAssertMsg( pLsaMessage->Arguments.LogonUser.ProfileBuffer,
|
||
"Successful logon, but profile is NULL. w\n" );
|
||
}
|
||
}
|
||
|
||
return(STATUS_SUCCESS);
|
||
|
||
}
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcLsaCallPackage
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcLsaCallPackage(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
LSAP_CLIENT_REQUEST ClientRequest;
|
||
PLSAP_AU_API_MESSAGE pLsaMessage = (PLSAP_AU_API_MESSAGE) pApiMessage;
|
||
PSession Session = GetCurrentSession();
|
||
|
||
ClientRequest.Request = (PLSAP_AU_API_MESSAGE) pApiMessage;
|
||
|
||
pLsaMessage->ReturnedStatus = LsapAuApiDispatchCallPackage(&ClientRequest);
|
||
|
||
return(STATUS_SUCCESS);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcQueryCredAttributes
|
||
//
|
||
//
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcQueryCredAttributes(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS hrApiRet;
|
||
SPMQueryCredAttributesAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.QueryCredAttributes;
|
||
PLSA_CALL_INFO CallInfo ;
|
||
|
||
CallInfo = LsapGetCurrentCall();
|
||
|
||
hrApiRet = WLsaQueryCredAttributes(
|
||
&pArgs->hCredentials,
|
||
pArgs->ulAttribute,
|
||
pArgs->pBuffer
|
||
);
|
||
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
if ( CallInfo->Allocs )
|
||
{
|
||
ULONG i ;
|
||
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ALLOCS ;
|
||
|
||
pArgs->Allocs = CallInfo->Allocs ;
|
||
for ( i = 0 ; i < CallInfo->Allocs ; i++ )
|
||
{
|
||
pArgs->Buffers[i] = CallInfo->Buffers[i] ;
|
||
}
|
||
}
|
||
|
||
pApiMessage->ApiMessage.scRet = hrApiRet;
|
||
|
||
if (FAILED(hrApiRet))
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
}
|
||
|
||
return(S_OK);
|
||
}
|
||
|
||
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcAddPackage
|
||
//
|
||
// Algorithm:
|
||
//
|
||
// History: 3-05-97 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
SECURITY_STATUS
|
||
LpcAddPackage(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
SPMAddPackageAPI * pArgs;
|
||
SECURITY_STRING PackageName;
|
||
SECURITY_STATUS scRet ;
|
||
PUCHAR Where = NULL;
|
||
SECURITY_PACKAGE_OPTIONS Options;
|
||
|
||
pArgs = LPC_MESSAGE_ARGSP( pApiMessage, AddPackage );
|
||
|
||
scRet = GetClientString( &pArgs->Package,
|
||
&PackageName,
|
||
pApiMessage,
|
||
&Where);
|
||
if (FAILED(scRet))
|
||
{
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
|
||
return(scRet);
|
||
}
|
||
|
||
DebugLog((DEB_TRACE_VERB,"Add Package called for %ws\n",
|
||
PackageName.Buffer ));
|
||
|
||
Options.Flags = pArgs->OptionsFlags ;
|
||
Options.Size = sizeof( SECURITY_PACKAGE_OPTIONS );
|
||
|
||
scRet = WLsaAddPackage( &PackageName,
|
||
&Options );
|
||
|
||
LsapFreePrivateHeap( PackageName.Buffer );
|
||
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
|
||
return( scRet );
|
||
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcDeletePackage
|
||
//
|
||
// History: 3-05-97 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
SECURITY_STATUS
|
||
LpcDeletePackage(
|
||
PSPM_LPC_MESSAGE pApiMessage)
|
||
{
|
||
pApiMessage->ApiMessage.scRet = SEC_E_UNSUPPORTED_FUNCTION ;
|
||
|
||
return( SEC_E_OK );
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcQueryContextAttributes
|
||
//
|
||
// History: 3-05-97 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcQueryContextAttributes(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS hrApiRet;
|
||
SPMQueryContextAttrAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.QueryContextAttr;
|
||
PLSA_CALL_INFO CallInfo ;
|
||
|
||
CallInfo = LsapGetCurrentCall();
|
||
|
||
hrApiRet = WLsaQueryContextAttributes(
|
||
&pArgs->hContext,
|
||
pArgs->ulAttribute,
|
||
pArgs->pBuffer
|
||
);
|
||
|
||
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
pApiMessage->ApiMessage.scRet = hrApiRet;
|
||
|
||
if ( CallInfo->Allocs )
|
||
{
|
||
ULONG i ;
|
||
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ALLOCS ;
|
||
|
||
pArgs->Allocs = CallInfo->Allocs ;
|
||
for ( i = 0 ; i < CallInfo->Allocs ; i++ )
|
||
{
|
||
pArgs->Buffers[i] = CallInfo->Buffers[i] ;
|
||
}
|
||
pApiMessage->pmMessage.u1.s1.DataLength = LPC_DATA_LENGTH( CallInfo->Allocs * sizeof( PVOID ) );
|
||
pApiMessage->pmMessage.u1.s1.TotalLength = LPC_TOTAL_LENGTH( CallInfo->Allocs * sizeof( PVOID ) );
|
||
}
|
||
|
||
|
||
if (FAILED(hrApiRet))
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
}
|
||
|
||
return(S_OK);
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcSetContextAttributes
|
||
//
|
||
// History: 4-20-00 CliffV Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcSetContextAttributes(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS hrApiRet;
|
||
SPMSetContextAttrAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.SetContextAttr;
|
||
PLSA_CALL_INFO CallInfo ;
|
||
|
||
CallInfo = LsapGetCurrentCall();
|
||
|
||
hrApiRet = WLsaSetContextAttributes(
|
||
&pArgs->hContext,
|
||
pArgs->ulAttribute,
|
||
pArgs->pBuffer,
|
||
pArgs->cbBuffer
|
||
);
|
||
|
||
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
pApiMessage->ApiMessage.scRet = hrApiRet;
|
||
|
||
if (FAILED(hrApiRet))
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
}
|
||
|
||
return(S_OK);
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcCallback
|
||
//
|
||
// Synopsis: Callback handler. Should never be hit.
|
||
//
|
||
// Arguments: [pApiMessage] --
|
||
//
|
||
// History: 3-05-97 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcCallback(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
pApiMessage->ApiMessage.scRet = SEC_E_UNSUPPORTED_FUNCTION ;
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
return S_OK ;
|
||
}
|
||
|
||
|
||
|
||
NTSTATUS
|
||
WLsaGenerateKey(
|
||
PEFS_DATA_STREAM_HEADER DirectoryEfsStream,
|
||
PEFS_DATA_STREAM_HEADER * EfsStream,
|
||
PULONG EfsLength,
|
||
PEFS_KEY * Fek
|
||
)
|
||
{
|
||
NTSTATUS Status;
|
||
DWORD HResult;
|
||
|
||
HANDLE hToken = NULL;
|
||
HANDLE hProfile = NULL;
|
||
|
||
PEFS_DATA_STREAM_HEADER EfsStreamHeader;
|
||
|
||
//
|
||
// Impersonate the client
|
||
//
|
||
|
||
Status = LsapImpersonateClient( );
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
return( Status );
|
||
}
|
||
|
||
EFS_USER_INFO EfsUserInfo;
|
||
|
||
if (EfspGetUserInfo( &EfsUserInfo )) {
|
||
|
||
BOOL b = EfspLoadUserProfile( &EfsUserInfo, &hToken, &hProfile );
|
||
|
||
if (!b) {
|
||
|
||
HResult = GetLastError();
|
||
if (!EfsErrorToNtStatus(HResult, &Status)) {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// Generate the Fek. This routine will fill in the
|
||
// EFS_KEY structure with key data.
|
||
//
|
||
|
||
if (GenerateFEK( Fek )) {
|
||
|
||
if (!ConstructEFS( &EfsUserInfo, *Fek, DirectoryEfsStream, &EfsStreamHeader )) {
|
||
|
||
HResult = GetLastError();
|
||
|
||
ASSERT( HResult != ERROR_SUCCESS );
|
||
|
||
DebugLog((DEB_ERROR, "ConstructEFS failed, error = (%x)\n" ,HResult ));
|
||
|
||
LsapFreeLsaHeap( *Fek );
|
||
*Fek = NULL;
|
||
|
||
if (!EfsErrorToNtStatus(HResult, &Status)) {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
} else {
|
||
|
||
*EfsStream = EfsStreamHeader;
|
||
*EfsLength = EfsStreamHeader->Length;
|
||
}
|
||
|
||
} else {
|
||
|
||
HResult = GetLastError();
|
||
if (!EfsErrorToNtStatus(HResult, &Status)) {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
}
|
||
|
||
EfspUnloadUserProfile( hToken, hProfile );
|
||
}
|
||
|
||
EfspFreeUserInfo( &EfsUserInfo );
|
||
|
||
} else {
|
||
|
||
HResult = GetLastError();
|
||
if (!EfsErrorToNtStatus(HResult, &Status)) {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
RevertToSelf();
|
||
|
||
return Status;
|
||
}
|
||
|
||
NTSTATUS
|
||
WLsaGenerateDirEfs(
|
||
PEFS_DATA_STREAM_HEADER DirectoryEfsStream,
|
||
PEFS_DATA_STREAM_HEADER * EfsStream
|
||
)
|
||
{
|
||
NTSTATUS Status;
|
||
DWORD HResult;
|
||
|
||
HANDLE hToken = NULL;
|
||
HANDLE hProfile = NULL;
|
||
PEFS_KEY Fek = NULL;
|
||
|
||
Status = LsapImpersonateClient( );
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
return( Status );
|
||
}
|
||
|
||
EFS_USER_INFO EfsUserInfo;
|
||
|
||
if (EfspGetUserInfo( &EfsUserInfo )) {
|
||
|
||
if (!EfspLoadUserProfile( &EfsUserInfo, &hToken, &hProfile )) {
|
||
|
||
HResult = GetLastError();
|
||
if (!EfsErrorToNtStatus(HResult, &Status)) {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
} else {
|
||
|
||
if (GenerateFEK( &Fek )) {
|
||
|
||
if (!ConstructDirectoryEFS(
|
||
&EfsUserInfo,
|
||
Fek,
|
||
EfsStream
|
||
)) {
|
||
|
||
HResult = GetLastError();
|
||
ASSERT( HResult != ERROR_SUCCESS );
|
||
DebugLog((DEB_ERROR, "ConstructDirectoryEFS failed, error = (%x)\n" ,HResult ));
|
||
if (!EfsErrorToNtStatus(HResult, &Status)) {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
}
|
||
|
||
LsapFreeLsaHeap( Fek );
|
||
|
||
} else {
|
||
|
||
HResult = GetLastError();
|
||
if (!EfsErrorToNtStatus(HResult, &Status)) {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
}
|
||
|
||
EfspUnloadUserProfile( hToken, hProfile );
|
||
}
|
||
|
||
EfspFreeUserInfo( &EfsUserInfo );
|
||
|
||
} else {
|
||
|
||
HResult = GetLastError();
|
||
if (!EfsErrorToNtStatus(HResult, &Status)) {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
}
|
||
|
||
RevertToSelf();
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
|
||
NTSTATUS
|
||
LpcEfsGenerateKey( PSPM_LPC_MESSAGE pApiMessage)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine generates an FEK and an EFS stream for the file
|
||
being encrypted.
|
||
|
||
Arguments:
|
||
|
||
pApiMessage - Supplies the LPC message from the driver.
|
||
|
||
Return Value:
|
||
|
||
return-value - Description of conditions needed to return value. - or -
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS scRet;
|
||
SPMEfsGenerateKeyAPI * Args = &pApiMessage->ApiMessage.Args.SpmArguments.API.EfsGenerateKey ;
|
||
ULONG EfsLength = 0;
|
||
PEFS_KEY Fek = NULL;
|
||
PEFS_DATA_STREAM_HEADER EfsStream;
|
||
SIZE_T BufferLength;
|
||
|
||
DebugLog((DEB_TRACE_EFS,"LpcEfsGenerateKey, Args is at %x\n",Args));
|
||
|
||
if ((pApiMessage->pmMessage.u2.s2.Type & LPC_KERNELMODE_MESSAGE) == 0){
|
||
DebugLog((DEB_ERROR,"Caller is not from kernelmode \n"));
|
||
pApiMessage->ApiMessage.scRet = STATUS_ACCESS_DENIED ;
|
||
return STATUS_ACCESS_DENIED;
|
||
}
|
||
|
||
if (EfsPersonalVer || EfsDisabled) {
|
||
pApiMessage->ApiMessage.scRet = STATUS_NOT_SUPPORTED;
|
||
return STATUS_NOT_SUPPORTED;
|
||
}
|
||
|
||
scRet = WLsaGenerateKey(
|
||
(PEFS_DATA_STREAM_HEADER)Args->DirectoryEfsStream,
|
||
&EfsStream,
|
||
&EfsLength,
|
||
&Fek
|
||
);
|
||
|
||
if (NT_SUCCESS( scRet )) {
|
||
|
||
//
|
||
// Copy the FEK to the client's address space
|
||
//
|
||
|
||
PVOID Target = NULL;
|
||
|
||
BufferLength = EFS_KEY_SIZE( Fek ) + EfsLength;
|
||
|
||
#ifdef LSAP_CATCH_BAD_VM
|
||
if ( BufferLength > 0x2000000 )
|
||
{
|
||
DbgPrint("Allocation too large\n" );
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
scRet = NtAllocateVirtualMemory(
|
||
GetCurrentProcess(),
|
||
&Target,
|
||
0,
|
||
&BufferLength,
|
||
MEM_COMMIT,
|
||
PAGE_READWRITE
|
||
);
|
||
|
||
Args->BufferLength = (ULONG) BufferLength;
|
||
if (NT_SUCCESS( scRet )) {
|
||
|
||
//
|
||
// Save away the base of the allocation so that the driver may free it
|
||
// when it's finished with it.
|
||
//
|
||
|
||
Args->BufferBase = Target;
|
||
Args->Fek = Target;
|
||
|
||
RtlCopyMemory(
|
||
Target,
|
||
(PVOID)Fek,
|
||
EFS_KEY_SIZE( Fek )
|
||
);
|
||
|
||
|
||
Target = (PVOID)((ULONG_PTR)Target + EFS_KEY_SIZE( Fek ));
|
||
Args->EfsStream = Target;
|
||
|
||
RtlCopyMemory(
|
||
Target,
|
||
(PVOID)EfsStream,
|
||
EfsLength
|
||
);
|
||
|
||
} else {
|
||
|
||
Args->BufferBase = NULL;
|
||
Args->BufferLength = 0;
|
||
Args->Fek = NULL;
|
||
Args->EfsStream = NULL;
|
||
|
||
}
|
||
|
||
if ( Fek ){
|
||
LsapFreeLsaHeap( Fek );
|
||
}
|
||
|
||
if ( EfsStream ){
|
||
LsapFreeLsaHeap( EfsStream );
|
||
}
|
||
}
|
||
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
return( scRet );
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LpcEfsGenerateDirEfs(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Lpc stub for GenerateDirEfs
|
||
|
||
Arguments:
|
||
|
||
pApiMessage - LPC Message
|
||
|
||
Return Value:
|
||
|
||
NtStatus
|
||
|
||
--*/
|
||
{
|
||
SPMEfsGenerateDirEfsAPI * Args = &pApiMessage->ApiMessage.Args.SpmArguments.API.EfsGenerateDirEfs ;
|
||
PEFS_DATA_STREAM_HEADER EfsStream;
|
||
NTSTATUS scRet;
|
||
ULONG EfsLength = 0;
|
||
|
||
if ((pApiMessage->pmMessage.u2.s2.Type & LPC_KERNELMODE_MESSAGE) == 0){
|
||
DebugLog((DEB_ERROR,"Caller is not from kernelmode \n"));
|
||
pApiMessage->ApiMessage.scRet = STATUS_ACCESS_DENIED ;
|
||
return STATUS_ACCESS_DENIED;
|
||
}
|
||
|
||
if (EfsPersonalVer || EfsDisabled) {
|
||
pApiMessage->ApiMessage.scRet = STATUS_NOT_SUPPORTED;
|
||
return STATUS_NOT_SUPPORTED;
|
||
}
|
||
|
||
scRet = WLsaGenerateDirEfs(
|
||
(PEFS_DATA_STREAM_HEADER)Args->DirectoryEfsStream,
|
||
&EfsStream
|
||
);
|
||
|
||
if (NT_SUCCESS( scRet )) {
|
||
|
||
PVOID Target = NULL;
|
||
|
||
SIZE_T EfsLength = EfsStream->Length;
|
||
|
||
#ifdef LSAP_CATCH_BAD_VM
|
||
if ( EfsLength > 0x2000000 )
|
||
{
|
||
DbgPrint("Allocation too large\n" );
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
|
||
scRet = NtAllocateVirtualMemory(
|
||
GetCurrentProcess(),
|
||
&Target,
|
||
0,
|
||
&EfsLength,
|
||
MEM_COMMIT,
|
||
PAGE_READWRITE
|
||
);
|
||
|
||
if (NT_SUCCESS( scRet )) {
|
||
|
||
Args->BufferBase = Target;
|
||
Args->BufferLength = EfsStream->Length;
|
||
Args->EfsStream = Target;
|
||
|
||
RtlCopyMemory(
|
||
Target,
|
||
(PVOID)EfsStream,
|
||
EfsStream->Length
|
||
);
|
||
|
||
} else {
|
||
|
||
Args->BufferBase = NULL;
|
||
Args->BufferLength = 0;
|
||
Args->EfsStream = NULL;
|
||
}
|
||
|
||
if (EfsStream){
|
||
LsapFreeLsaHeap( EfsStream );
|
||
}
|
||
}
|
||
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
return( scRet );
|
||
}
|
||
|
||
NTSTATUS
|
||
WLsaDecryptFek(
|
||
PEFS_DATA_STREAM_HEADER EfsStream,
|
||
PEFS_KEY * Fek,
|
||
PEFS_DATA_STREAM_HEADER * NewEfs,
|
||
ULONG OpenType
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Worker function for DecryptFek
|
||
|
||
Arguments:
|
||
|
||
EfsStream - The $EFS attribute for the file being decrypted.
|
||
|
||
Fek - Returns the FEK for the file being decrypted. This structure
|
||
is allocated out of heap and must be freed by the caller.
|
||
|
||
NewEfs - Optionally returns a new $EFS stream to be applied to
|
||
the file.
|
||
|
||
OpenType - Whether this is a decrypt or recovery operation.
|
||
|
||
|
||
Return Value:
|
||
|
||
NtStatus
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
DWORD HResult;
|
||
DWORD rc;
|
||
|
||
HANDLE hToken = NULL;
|
||
HANDLE hProfile = NULL;
|
||
|
||
Status = LsapImpersonateClient( );
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
return( Status );
|
||
}
|
||
|
||
EFS_USER_INFO EfsUserInfo;
|
||
|
||
if (EfspGetUserInfo( &EfsUserInfo ) ) {
|
||
|
||
if (EfspLoadUserProfile( &EfsUserInfo, &hToken, &hProfile )) {
|
||
|
||
HResult = DecryptFek( &EfsUserInfo, EfsStream, Fek, NewEfs, OpenType );
|
||
|
||
if (HResult != ERROR_SUCCESS) {
|
||
DebugLog((DEB_ERROR, "WLsaDecryptFek: DecryptFek failed, error = %x\n" ,HResult ));
|
||
if (!EfsErrorToNtStatus(HResult, &Status)) {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
}
|
||
|
||
EfspUnloadUserProfile( hToken, hProfile );
|
||
|
||
} else {
|
||
|
||
HResult = GetLastError();
|
||
if (!EfsErrorToNtStatus(HResult, &Status)) {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
}
|
||
|
||
EfspFreeUserInfo( &EfsUserInfo );
|
||
|
||
} else {
|
||
|
||
HResult = GetLastError();
|
||
if (!EfsErrorToNtStatus(HResult, &Status)) {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
}
|
||
|
||
RevertToSelf();
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LpcEfsDecryptFek( PSPM_LPC_MESSAGE pApiMessage)
|
||
{
|
||
SPMEfsDecryptFekAPI * Args = &pApiMessage->ApiMessage.Args.SpmArguments.API.EfsDecryptFek ;
|
||
PEFS_DATA_STREAM_HEADER NewEfs;
|
||
NTSTATUS Status;
|
||
ULONG EfsLength = 0;
|
||
PEFS_KEY Fek;
|
||
SIZE_T BufferLength;
|
||
|
||
Args->BufferBase = NULL;
|
||
Args->BufferLength = 0;
|
||
Args->Fek = NULL;
|
||
Args->NewEfs = NULL;
|
||
|
||
if ((pApiMessage->pmMessage.u2.s2.Type & LPC_KERNELMODE_MESSAGE) == 0){
|
||
DebugLog((DEB_ERROR,"Caller is not from kernelmode \n"));
|
||
pApiMessage->ApiMessage.scRet = STATUS_ACCESS_DENIED ;
|
||
return STATUS_ACCESS_DENIED;
|
||
}
|
||
|
||
if (EfsPersonalVer || EfsDisabled) {
|
||
pApiMessage->ApiMessage.scRet = STATUS_NOT_SUPPORTED;
|
||
return STATUS_NOT_SUPPORTED;
|
||
}
|
||
|
||
Status = WLsaDecryptFek( (PEFS_DATA_STREAM_HEADER)Args->EfsStream, &Fek, &NewEfs, Args->OpenType );
|
||
|
||
|
||
if (NT_SUCCESS( Status )) {
|
||
|
||
BufferLength = EFS_KEY_SIZE( Fek );
|
||
|
||
if (NewEfs != NULL) {
|
||
BufferLength += NewEfs->Length;
|
||
}
|
||
|
||
PVOID Target = NULL;
|
||
|
||
#ifdef LSAP_CATCH_BAD_VM
|
||
if ( BufferLength > 0x2000000 )
|
||
{
|
||
DbgPrint("Allocation too large\n" );
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
Status = NtAllocateVirtualMemory(
|
||
GetCurrentProcess(),
|
||
&Target,
|
||
0,
|
||
&BufferLength,
|
||
MEM_COMMIT,
|
||
PAGE_READWRITE
|
||
);
|
||
|
||
|
||
Args->BufferLength = (ULONG) BufferLength;
|
||
if (NT_SUCCESS( Status )) {
|
||
|
||
Args->BufferBase = Target;
|
||
Args->Fek = Target;
|
||
|
||
RtlCopyMemory(
|
||
Target,
|
||
(PVOID)Fek,
|
||
EFS_KEY_SIZE( Fek )
|
||
);
|
||
|
||
if (NewEfs != NULL) {
|
||
|
||
Target = (PVOID)((DWORD_PTR)Target + EFS_KEY_SIZE( Fek ));
|
||
Args->NewEfs = Target;
|
||
|
||
RtlCopyMemory(
|
||
Target,
|
||
(PVOID)NewEfs,
|
||
NewEfs->Length
|
||
);
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
Args->BufferBase = NULL;
|
||
Args->BufferLength = 0;
|
||
Args->Fek = NULL;
|
||
|
||
}
|
||
|
||
if ( Fek){
|
||
LsapFreeLsaHeap( Fek );
|
||
}
|
||
|
||
if ( NewEfs ){
|
||
LsapFreeLsaHeap( NewEfs );
|
||
}
|
||
}
|
||
|
||
pApiMessage->ApiMessage.scRet = Status;
|
||
|
||
return( Status );
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LpcEfsGenerateSessionKey(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
SPMEfsGenerateSessionKeyAPI * Args = &pApiMessage->ApiMessage.Args.SpmArguments.API.EfsGenerateSessionKey ;
|
||
NTSTATUS scRet;
|
||
|
||
EFS_INIT_DATAEXG InitDataExg;
|
||
|
||
if ((pApiMessage->pmMessage.u2.s2.Type & LPC_KERNELMODE_MESSAGE) == 0){
|
||
DebugLog((DEB_ERROR,"Caller is not from kernelmode \n"));
|
||
pApiMessage->ApiMessage.scRet = STATUS_ACCESS_DENIED ;
|
||
return STATUS_ACCESS_DENIED;
|
||
}
|
||
|
||
if ( EfsSessionKeySent ){
|
||
pApiMessage->ApiMessage.scRet = STATUS_ACCESS_DENIED ;
|
||
return STATUS_ACCESS_DENIED;
|
||
}
|
||
|
||
scRet = GenerateDriverSessionKey( &InitDataExg );
|
||
|
||
if (NT_SUCCESS( scRet )) {
|
||
|
||
//
|
||
// Copy the returned session key into the argument buffer
|
||
//
|
||
|
||
RtlCopyMemory( &Args->InitDataExg, &InitDataExg, sizeof( EFS_INIT_DATAEXG ));
|
||
|
||
pApiMessage->pmMessage.u1.s1.DataLength = LPC_DATA_LENGTH( sizeof( EFS_INIT_DATAEXG ) );
|
||
pApiMessage->pmMessage.u1.s1.TotalLength = LPC_TOTAL_LENGTH( sizeof( EFS_INIT_DATAEXG ) );
|
||
|
||
EfsSessionKeySent = TRUE;
|
||
}
|
||
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
|
||
return( scRet );
|
||
}
|
||
|
||
NTSTATUS
|
||
LpcGetUserName(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
|
||
LUID LogonId ;
|
||
PLSAP_LOGON_SESSION LogonSession ;
|
||
NTSTATUS Status ;
|
||
SECPKG_CLIENT_INFO ClientInfo ;
|
||
SPMGetUserNameXAPI * Args = &pApiMessage->ApiMessage.Args.SpmArguments.API.GetUserNameX ;
|
||
PLSAP_DS_NAME_MAP Map ;
|
||
PLSAP_DS_NAME_MAP SamMap = NULL ;
|
||
UNICODE_STRING String ;
|
||
PWSTR Scan ;
|
||
PWSTR DnsDomainName = NULL;
|
||
|
||
Status = LsapGetClientInfo( &ClientInfo );
|
||
|
||
if ( NT_SUCCESS( Status ) )
|
||
{
|
||
LogonSession = LsapLocateLogonSession( &ClientInfo.LogonId );
|
||
|
||
if ( LogonSession )
|
||
{
|
||
if ( RtlEqualLuid( &ClientInfo.LogonId,
|
||
&LsapSystemLogonId ) &&
|
||
(Args->Options & SPM_NAME_OPTION_NT4_ONLY) )
|
||
{
|
||
Map = LsapGetNameForLocalSystem();
|
||
|
||
Status = STATUS_SUCCESS ;
|
||
|
||
}
|
||
else
|
||
{
|
||
Status = LsapGetNameForLogonSession(
|
||
LogonSession,
|
||
Args->Options,
|
||
&Map,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status)
|
||
&&
|
||
(Args->Options & (~SPM_NAME_OPTION_MASK)) == NameDnsDomain)
|
||
{
|
||
//
|
||
// To cruft up the NameDnsDomain format, we need
|
||
// the SAM username.
|
||
//
|
||
|
||
Status = LsapGetNameForLogonSession(
|
||
LogonSession,
|
||
NameSamCompatible,
|
||
&SamMap,
|
||
FALSE);
|
||
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
LsapDerefDsNameMap(Map);
|
||
}
|
||
}
|
||
}
|
||
|
||
LsapReleaseLogonSession( LogonSession );
|
||
|
||
if ( NT_SUCCESS( Status ) )
|
||
{
|
||
//
|
||
// See what we can do.
|
||
//
|
||
|
||
if ( (Args->Options & SPM_NAME_OPTION_NT4_ONLY) == 0)
|
||
{
|
||
if ((Args->Options & (~SPM_NAME_OPTION_MASK )) != NameDnsDomain)
|
||
{
|
||
String = Map->Name ;
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Build up the DnsDomainName format
|
||
//
|
||
|
||
Scan = wcschr( SamMap->Name.Buffer, L'\\' );
|
||
|
||
if ( Scan )
|
||
{
|
||
Scan++;
|
||
}
|
||
else
|
||
{
|
||
Scan = SamMap->Name.Buffer;
|
||
}
|
||
|
||
//
|
||
// SAM name is always NULL-terminated
|
||
//
|
||
|
||
DnsDomainName = (LPWSTR) LsapAllocatePrivateHeap(
|
||
Map->Name.Length + (wcslen(Scan) + 2) * sizeof(WCHAR));
|
||
|
||
if (DnsDomainName != NULL)
|
||
{
|
||
ULONG Index = Map->Name.Length / sizeof(WCHAR);
|
||
|
||
wcsncpy(DnsDomainName, Map->Name.Buffer, Index);
|
||
DnsDomainName[Index++] = L'\\';
|
||
wcscpy(DnsDomainName + Index, Scan);
|
||
|
||
RtlInitUnicodeString(&String, DnsDomainName);
|
||
}
|
||
else
|
||
{
|
||
String.Length = String.MaximumLength = 0;
|
||
String.Buffer = NULL;
|
||
|
||
Status = STATUS_NO_MEMORY;
|
||
}
|
||
|
||
LsapDerefDsNameMap(SamMap);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Scan = wcschr( Map->Name.Buffer, L'\\' );
|
||
|
||
if ( Scan )
|
||
{
|
||
Scan++;
|
||
RtlInitUnicodeString( &String, Scan );
|
||
}
|
||
else
|
||
{
|
||
String = Map->Name ;
|
||
}
|
||
}
|
||
|
||
if (NT_SUCCESS(Status))
|
||
{
|
||
if ( String.Length <= Args->Name.MaximumLength )
|
||
{
|
||
Args->Name.Length = String.Length ;
|
||
|
||
if ( String.Length < CBPREPACK )
|
||
{
|
||
Args->Name.Buffer = (PWSTR) ((LONG_PTR) pApiMessage->ApiMessage.bData
|
||
- (LONG_PTR) Args);
|
||
|
||
RtlCopyMemory(
|
||
pApiMessage->ApiMessage.bData,
|
||
String.Buffer,
|
||
String.Length );
|
||
|
||
pApiMessage->pmMessage.u1.s1.DataLength = LPC_DATA_LENGTH( String.Length );
|
||
pApiMessage->pmMessage.u1.s1.TotalLength = LPC_TOTAL_LENGTH( String.Length );
|
||
}
|
||
else
|
||
{
|
||
Status = LsapCopyToClient(
|
||
String.Buffer,
|
||
Args->Name.Buffer,
|
||
String.Length );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Args->Name.Length = String.Length ;
|
||
Args->Name.Buffer = NULL ;
|
||
Status = STATUS_BUFFER_OVERFLOW ;
|
||
}
|
||
}
|
||
|
||
LsapDerefDsNameMap( Map );
|
||
}
|
||
else
|
||
{
|
||
if ( Status == STATUS_UNSUCCESSFUL )
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_WIN32_ERROR ;
|
||
Status = GetLastError();
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
DebugLog(( DEB_ERROR, "No logon session found for impersonated client!\n" ));
|
||
Status = STATUS_NO_SUCH_LOGON_SESSION ;
|
||
}
|
||
}
|
||
|
||
if (DnsDomainName != NULL)
|
||
{
|
||
LsapFreePrivateHeap(DnsDomainName);
|
||
}
|
||
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
pApiMessage->ApiMessage.scRet = Status ;
|
||
|
||
return STATUS_SUCCESS ;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LpcAddCredentials(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
UNICODE_STRING ssPrincipalName;
|
||
UNICODE_STRING ssPackageName;
|
||
NTSTATUS scApiRet;
|
||
NTSTATUS scRet;
|
||
SPMAddCredentialAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.AddCredential;
|
||
|
||
PSession pSession ;
|
||
PUCHAR Where = NULL;
|
||
|
||
pSession = GetCurrentSession();
|
||
|
||
DebugLog((DEB_TRACE, "[%x] LpcAddCredentials()\n", pSession->dwProcessID));
|
||
|
||
ssPrincipalName.Buffer = NULL;
|
||
ssPackageName.Buffer = NULL;
|
||
|
||
if (pArgs->ssPrincipal.Buffer )
|
||
{
|
||
scRet = GetClientString(&pArgs->ssPrincipal,
|
||
&ssPrincipalName,
|
||
pApiMessage,
|
||
&Where);
|
||
if (FAILED(scRet))
|
||
{
|
||
DebugLog((DEB_ERROR, "GetClientString failed to get principal name 0x%08x\n", scRet));
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
return(scRet);
|
||
}
|
||
|
||
} else {
|
||
ssPrincipalName.MaximumLength = 0;
|
||
ssPrincipalName.Length = 0;
|
||
ssPrincipalName.Buffer = NULL;
|
||
}
|
||
|
||
scRet = GetClientString(&pArgs->ssSecPackage,
|
||
&ssPackageName,
|
||
pApiMessage,
|
||
&Where);
|
||
|
||
if (FAILED(scRet))
|
||
{
|
||
LsapFreePrivateHeap(ssPrincipalName.Buffer);
|
||
DebugLog((DEB_ERROR, "GetClientString failed to get package name 0x%08x\n", scRet));
|
||
pApiMessage->ApiMessage.scRet = scRet;
|
||
return(scRet);
|
||
}
|
||
|
||
scApiRet = WLsaAddCredentials(
|
||
&pArgs->hCredentials,
|
||
&ssPrincipalName,
|
||
&ssPackageName,
|
||
pArgs->fCredentialUse,
|
||
(PVOID) pArgs->pvAuthData,
|
||
(PVOID) pArgs->pvGetKeyFn,
|
||
(PVOID) pArgs->ulGetKeyArgument,
|
||
&pArgs->tsExpiry );
|
||
|
||
|
||
//
|
||
// Reset the reply flags:
|
||
//
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
|
||
LsapFreePrivateHeap(ssPackageName.Buffer);
|
||
|
||
LsapFreePrivateHeap(ssPrincipalName.Buffer);
|
||
|
||
pApiMessage->ApiMessage.scRet = scApiRet;
|
||
if (FAILED(pApiMessage->ApiMessage.scRet))
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
}
|
||
return(S_OK);
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
LpcEnumLogonSessions(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS scApiRet;
|
||
NTSTATUS scRet;
|
||
SPMEnumLogonSessionAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.EnumLogonSession ;
|
||
PSession pSession ;
|
||
|
||
pSession = GetCurrentSession();
|
||
|
||
DebugLog((DEB_TRACE, "[%x] LpcEnumLogonSessions()\n", pSession->dwProcessID));
|
||
|
||
scApiRet = WLsaEnumerateLogonSession(
|
||
&pArgs->LogonSessionCount,
|
||
(PLUID *) &pArgs->LogonSessionList );
|
||
|
||
//
|
||
// Reset the reply flags:
|
||
//
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
|
||
pApiMessage->ApiMessage.scRet = scApiRet;
|
||
|
||
if (FAILED(pApiMessage->ApiMessage.scRet))
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
}
|
||
return(S_OK);
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
LpcGetLogonSessionData(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS scApiRet;
|
||
NTSTATUS scRet;
|
||
SPMGetLogonSessionDataAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.GetLogonSessionData ;
|
||
PSession pSession ;
|
||
|
||
pSession = GetCurrentSession();
|
||
|
||
DebugLog((DEB_TRACE, "[%x] LpcGetLogonSessionData()\n", pSession->dwProcessID));
|
||
|
||
scApiRet = WLsaGetLogonSessionData(
|
||
&pArgs->LogonId,
|
||
&pArgs->LogonSessionInfo );
|
||
|
||
//
|
||
// Reset the reply flags:
|
||
//
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
|
||
pApiMessage->ApiMessage.scRet = scApiRet;
|
||
|
||
if (FAILED(pApiMessage->ApiMessage.scRet))
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
}
|
||
return(S_OK);
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
LpcLookupAccountName(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS scApiRet;
|
||
NTSTATUS scRet;
|
||
SPMLookupAccountNameXAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.LookupAccountNameX ;
|
||
PSession pSession ;
|
||
UNICODE_STRING Name ;
|
||
PUCHAR Where = NULL ;
|
||
LSAPR_TRANSLATED_SIDS_EX2 Sids ;
|
||
PLSAPR_REFERENCED_DOMAIN_LIST DomList ;
|
||
LSAPR_UNICODE_STRING String ;
|
||
ULONG MappedCount ;
|
||
ULONG Available ;
|
||
ULONG Size ;
|
||
|
||
pSession = GetCurrentSession();
|
||
|
||
DebugLog((DEB_TRACE, "[%x] LpcLookupAccountName()\n", pSession->dwProcessID));
|
||
|
||
|
||
scApiRet = GetClientString(
|
||
&pArgs->Name,
|
||
&Name,
|
||
pApiMessage,
|
||
&Where );
|
||
|
||
if ( NT_SUCCESS( scApiRet ) )
|
||
{
|
||
MappedCount = 0 ;
|
||
|
||
String.Length = Name.Length ;
|
||
String.MaximumLength = Name.MaximumLength ;
|
||
String.Buffer = Name.Buffer ;
|
||
|
||
scApiRet = LsarLookupNames3(
|
||
LsapPolicyHandle,
|
||
1,
|
||
&String,
|
||
&DomList,
|
||
&Sids,
|
||
LsapLookupWksta,
|
||
&MappedCount,
|
||
0,
|
||
LSA_CLIENT_LATEST );
|
||
|
||
if ( NT_SUCCESS( scApiRet ) )
|
||
{
|
||
|
||
Where = pApiMessage->ApiMessage.bData ;
|
||
pArgs->NameUse = Sids.Sids[0].Use ;
|
||
|
||
Size = RtlLengthSid( (PSID) Sids.Sids[0].Sid );
|
||
|
||
pArgs->Sid = (PVOID) (Where - (PUCHAR) pApiMessage) ;
|
||
RtlCopyMemory(
|
||
Where,
|
||
Sids.Sids[0].Sid,
|
||
Size );
|
||
|
||
|
||
Available = CBPREPACK - Size ;
|
||
Where += Size ;
|
||
|
||
Size = DomList->Domains[0].Name.Length ;
|
||
if ( Available >= Size )
|
||
{
|
||
RtlCopyMemory(
|
||
Where,
|
||
DomList->Domains[0].Name.Buffer,
|
||
Size );
|
||
|
||
pArgs->Domain.Buffer = (PWSTR) (Where - (PUCHAR) pApiMessage ) ;
|
||
pArgs->Domain.Length = (USHORT) Size ;
|
||
pArgs->Domain.MaximumLength = (USHORT) Size ;
|
||
|
||
}
|
||
else
|
||
{
|
||
pArgs->Domain.Buffer = NULL ;
|
||
pArgs->Domain.Length = 0 ;
|
||
pArgs->Domain.MaximumLength = 0 ;
|
||
}
|
||
|
||
MIDL_user_free( DomList );
|
||
MIDL_user_free( Sids.Sids );
|
||
}
|
||
|
||
|
||
}
|
||
|
||
//
|
||
// Reset the reply flags:
|
||
//
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
|
||
pApiMessage->ApiMessage.scRet = scApiRet;
|
||
|
||
if (FAILED(pApiMessage->ApiMessage.scRet))
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
}
|
||
|
||
return(S_OK);
|
||
}
|
||
|
||
NTSTATUS
|
||
LpcLookupAccountSid(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
NTSTATUS scApiRet = STATUS_SUCCESS ;
|
||
NTSTATUS scRet;
|
||
SPMLookupAccountSidXAPI * pArgs = &pApiMessage->ApiMessage.Args.SpmArguments.API.LookupAccountSidX ;
|
||
PSession pSession ;
|
||
PUCHAR Where = NULL ;
|
||
PLSAPR_REFERENCED_DOMAIN_LIST DomList ;
|
||
LSAPR_SID_ENUM_BUFFER SidBuffer ;
|
||
LSAPR_SID_INFORMATION SidInfo ;
|
||
LSAPR_TRANSLATED_NAMES_EX Names ;
|
||
ULONG MappedCount ;
|
||
SIZE_T Available ;
|
||
ULONG Size ;
|
||
PSID Sid = NULL ;
|
||
|
||
pSession = GetCurrentSession();
|
||
|
||
DebugLog((DEB_TRACE, "[%x] LpcLookupAccountSid()\n", pSession->dwProcessID));
|
||
|
||
Where = (ULONG_PTR) pArgs->Sid + (PUCHAR) pApiMessage ;
|
||
Available = sizeof( SPM_LPC_MESSAGE ) - (ULONG_PTR) pArgs->Sid ;
|
||
|
||
//
|
||
// Verify that the passed SID is at least large enough for the SID header
|
||
//
|
||
if ( Available < sizeof( SID ) )
|
||
{
|
||
scApiRet = STATUS_INVALID_PARAMETER ;
|
||
}
|
||
|
||
if ( NT_SUCCESS( scApiRet ) )
|
||
{
|
||
Sid = (PSID) ( Where );
|
||
|
||
Size = RtlLengthSid( Sid );
|
||
|
||
if ( Size > Available )
|
||
{
|
||
scApiRet = STATUS_INVALID_PARAMETER ;
|
||
}
|
||
}
|
||
|
||
if ( NT_SUCCESS( scApiRet ) )
|
||
{
|
||
PSID DomainSid = NULL;
|
||
MappedCount = 0 ;
|
||
|
||
SidInfo.Sid = (PLSAPR_SID) Sid ;
|
||
SidBuffer.Entries = 1 ;
|
||
SidBuffer.SidInfo = &SidInfo ;
|
||
|
||
if( LsapAccountDomainMemberSid )
|
||
{
|
||
ULONG SidLength = RtlLengthSid( LsapAccountDomainMemberSid );
|
||
DomainSid = LsapAllocatePrivateHeap(
|
||
SidLength
|
||
);
|
||
|
||
if( DomainSid != NULL )
|
||
{
|
||
RtlCopyMemory(DomainSid, LsapAccountDomainMemberSid, SidLength);
|
||
|
||
*(RtlSubAuthoritySid(
|
||
DomainSid,
|
||
(*GetSidSubAuthorityCount(DomainSid) - 1)
|
||
)) = DOMAIN_USER_RID_GUEST;
|
||
|
||
SidInfo.Sid = (PLSAPR_SID)DomainSid;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
scApiRet = LsarLookupSids2(
|
||
LsapPolicyHandle,
|
||
&SidBuffer,
|
||
&DomList,
|
||
&Names,
|
||
LsapLookupWksta,
|
||
&MappedCount,
|
||
0,
|
||
LSA_CLIENT_LATEST );
|
||
|
||
|
||
if ( NT_SUCCESS( scApiRet ) &&
|
||
( MappedCount == 1 ) )
|
||
{
|
||
|
||
Where = pApiMessage->ApiMessage.bData ;
|
||
|
||
pArgs->NameUse = Names.Names[0].Use ;
|
||
|
||
Size = Names.Names[0].Name.Length ;
|
||
|
||
pArgs->Name.Buffer = (PWSTR) (Where - (PUCHAR) pApiMessage );
|
||
pArgs->Name.Length = (USHORT) Size ;
|
||
pArgs->Name.MaximumLength = pArgs->Name.Length ;
|
||
|
||
RtlCopyMemory(
|
||
Where,
|
||
Names.Names[0].Name.Buffer,
|
||
Size );
|
||
|
||
Available = CBPREPACK - Size ;
|
||
Where += Size ;
|
||
|
||
Size = DomList->Domains[0].Name.Length ;
|
||
if ( Available >= Size )
|
||
{
|
||
RtlCopyMemory(
|
||
Where,
|
||
DomList->Domains[0].Name.Buffer,
|
||
Size );
|
||
|
||
pArgs->Domain.Buffer = (PWSTR) Where ;
|
||
pArgs->Domain.Length = (USHORT) Size ;
|
||
pArgs->Domain.MaximumLength = (USHORT) Size ;
|
||
|
||
}
|
||
else
|
||
{
|
||
pArgs->Domain.Buffer = NULL ;
|
||
pArgs->Domain.Length = 0 ;
|
||
pArgs->Domain.MaximumLength = 0 ;
|
||
}
|
||
|
||
MIDL_user_free( DomList );
|
||
MIDL_user_free( Names.Names );
|
||
|
||
|
||
}
|
||
|
||
if( DomainSid )
|
||
{
|
||
LsapFreePrivateHeap( DomainSid );
|
||
}
|
||
|
||
|
||
}
|
||
|
||
//
|
||
// Reset the reply flags:
|
||
//
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI &= KLPC_FLAG_RESET ;
|
||
|
||
|
||
pApiMessage->ApiMessage.scRet = scApiRet;
|
||
|
||
if (FAILED(pApiMessage->ApiMessage.scRet))
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
}
|
||
|
||
return(S_OK);
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LsapClientCallback
|
||
//
|
||
// Synopsis: Client Callback.
|
||
//
|
||
// Arguments: [Session] --
|
||
// [Type] --
|
||
// [Function] --
|
||
// [Argument1] --
|
||
// [Argument2] --
|
||
// [Input] --
|
||
// [Output] --
|
||
//
|
||
// History: 12-09-97 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LsapClientCallback(
|
||
PSession Session,
|
||
ULONG Type,
|
||
PVOID Function,
|
||
PVOID Argument1,
|
||
PVOID Argument2,
|
||
PSecBuffer Input,
|
||
PSecBuffer Output
|
||
)
|
||
{
|
||
PSPM_LPC_MESSAGE Message ;
|
||
NTSTATUS Status ;
|
||
SPMCallbackAPI * Args ;
|
||
PSPM_LPC_MESSAGE ReplyTo ;
|
||
PVOID ClientBuffer ;
|
||
PLSA_CALL_INFO CallInfo ;
|
||
|
||
CallInfo = LsapGetCurrentCall();
|
||
|
||
if ( !CallInfo )
|
||
{
|
||
return STATUS_INVALID_PARAMETER ;
|
||
}
|
||
|
||
ReplyTo = CallInfo->Message ;
|
||
|
||
if ( !ReplyTo )
|
||
{
|
||
return STATUS_INVALID_PARAMETER ;
|
||
}
|
||
|
||
Message = (PSPM_LPC_MESSAGE) LsapAllocatePrivateHeap(
|
||
sizeof( SPM_LPC_MESSAGE ) );
|
||
|
||
if ( !Message )
|
||
{
|
||
return SEC_E_INSUFFICIENT_MEMORY ;
|
||
}
|
||
|
||
// DebugLog(( DEB_TRACE_LPC, "Calling back on LPC message %x\n",
|
||
// ReplyTo->pmMessage.MessageId ));
|
||
|
||
PREPARE_MESSAGE_EX( (*Message), Callback, SPMAPI_FLAG_CALLBACK, 0 );
|
||
|
||
Message->pmMessage = ReplyTo->pmMessage ;
|
||
Message->pmMessage.u1.s1.DataLength = LPC_DATA_LENGTH( 0 );
|
||
Message->pmMessage.u1.s1.TotalLength = LPC_TOTAL_LENGTH( 0 );
|
||
|
||
Args = LPC_MESSAGE_ARGS( (*Message), Callback );
|
||
|
||
Args->Type = Type ;
|
||
Args->CallbackFunction = Function ;
|
||
Args->Argument1 = Argument1 ;
|
||
Args->Argument2 = Argument2 ;
|
||
|
||
if ( Input->pvBuffer )
|
||
{
|
||
Status = LsapWriteClientBuffer( Input, &Args->Input );
|
||
|
||
if ( !NT_SUCCESS( Status ) )
|
||
{
|
||
LsapFreePrivateHeap( Message );
|
||
|
||
return Status ;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Args->Input.BufferType = SECBUFFER_EMPTY ;
|
||
Args->Input.cbBuffer = 0 ;
|
||
Args->Input.pvBuffer = NULL ;
|
||
}
|
||
|
||
ClientBuffer = Args->Input.pvBuffer ;
|
||
|
||
if ( CallInfo->InProcCall )
|
||
{
|
||
//
|
||
// Inproc Callback!
|
||
//
|
||
|
||
Status = DllCallbackHandler( Message );
|
||
}
|
||
else
|
||
{
|
||
|
||
DsysAssert( Session->hPort );
|
||
|
||
Status = NtRequestWaitReplyPort( Session->hPort,
|
||
(PPORT_MESSAGE) Message,
|
||
(PPORT_MESSAGE) Message );
|
||
|
||
}
|
||
if ( !NT_SUCCESS( Status ) )
|
||
{
|
||
LsapFreePrivateHeap( Message );
|
||
|
||
return Status ;
|
||
}
|
||
|
||
if ( ClientBuffer )
|
||
{
|
||
LsapFreeClientBuffer( NULL, ClientBuffer );
|
||
}
|
||
|
||
*Output = Args->Output ;
|
||
|
||
Status = Message->ApiMessage.scRet ;
|
||
|
||
LsapFreePrivateHeap( Message );
|
||
|
||
return Status ;
|
||
}
|
||
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LsapShutdownInprocDll
|
||
//
|
||
// Synopsis: Shuts down the inproc secur32 DLL
|
||
//
|
||
// History: 11-04-98 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
VOID
|
||
LsapShutdownInprocDll(
|
||
VOID
|
||
)
|
||
{
|
||
SPM_LPC_MESSAGE LocalMessage ;
|
||
PSPM_LPC_MESSAGE Message ;
|
||
SPMCallbackAPI * Args ;
|
||
|
||
Message = &LocalMessage;
|
||
|
||
PREPARE_MESSAGE_EX( (*Message), Callback, SPMAPI_FLAG_CALLBACK, 0 );
|
||
|
||
Args = LPC_MESSAGE_ARGS( (*Message), Callback );
|
||
|
||
Args->Type = SPM_CALLBACK_INTERNAL ;
|
||
Args->CallbackFunction = NULL ;
|
||
Args->Argument1 = (PVOID) SPM_CALLBACK_SHUTDOWN ;
|
||
Args->Argument2 = 0 ;
|
||
|
||
if ( DllCallbackHandler )
|
||
{
|
||
(void) DllCallbackHandler( Message );
|
||
}
|
||
|
||
}
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: DispatchAPI()
|
||
//
|
||
// Synopsis: Dispatches API requests
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments: pApiMessage - Input message
|
||
// pApiMessage - Output message
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
|
||
extern "C"
|
||
NTSTATUS
|
||
DispatchAPI(PSPM_LPC_MESSAGE pApiMessage)
|
||
{
|
||
NTSTATUS scRet;
|
||
PSession pSession ;
|
||
|
||
pSession = GetCurrentSession();
|
||
|
||
DebugLog((DEB_TRACE,"[%x] LpcDispatch: dispatching %s (%x)\n",
|
||
pSession->dwProcessID, ApiLabel(pApiMessage->ApiMessage.dwAPI),
|
||
pApiMessage->ApiMessage.dwAPI));
|
||
|
||
|
||
|
||
scRet = 0;
|
||
|
||
|
||
if ((pApiMessage->ApiMessage.dwAPI >= LsapAuLookupPackageApi) &&
|
||
(pApiMessage->ApiMessage.dwAPI < SPMAPI_MaxApiNumber) &&
|
||
(LpcDispatchTable[pApiMessage->ApiMessage.dwAPI] != NULL) )
|
||
{
|
||
if ( !ShutdownBegun )
|
||
{
|
||
scRet = LpcDispatchTable[pApiMessage->ApiMessage.dwAPI](pApiMessage);
|
||
|
||
//
|
||
// BUGBUG: If scRet is not STATUS_SUCCESS, the error code gets dropped
|
||
//
|
||
}
|
||
else
|
||
{
|
||
pApiMessage->ApiMessage.scRet = STATUS_SHUTDOWN_IN_PROGRESS;
|
||
}
|
||
|
||
//
|
||
// Shutdown may have been initiated prior or during a call in progress.
|
||
// If the call failed, we always return an error code indicating that
|
||
// shutdown was invoked. This avoids returning random error codes
|
||
// that can result from calls failing due to async shutdown activities.
|
||
//
|
||
|
||
if( ShutdownBegun && !NT_SUCCESS(pApiMessage->ApiMessage.scRet) )
|
||
{
|
||
scRet = STATUS_SHUTDOWN_IN_PROGRESS;
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
pApiMessage->ApiMessage.scRet = scRet ;
|
||
}
|
||
|
||
//
|
||
// Do some checking to see if we're getting pounded by an agressive
|
||
// app. NOTE: This is not MT safe (counters are not interlocked,
|
||
// resets are not protected). This is merely an optimization to try
|
||
// and service clients with dedicated threads. The counter may not
|
||
// be precise - them's the breaks.
|
||
//
|
||
|
||
pSession->CallCount++ ;
|
||
|
||
if ( pSession->Tick + 5000 < GetTickCount() )
|
||
{
|
||
//
|
||
// Ok, in a minimum five second interval, did more than, say, 50
|
||
// requests come in. If so, set a flag indicating that the client
|
||
// should request a workqueue.
|
||
//
|
||
|
||
if ( pSession->CallCount > 50 )
|
||
{
|
||
if (pApiMessage->ApiMessage.dwAPI > LsapAuMaxApiNumber )
|
||
{
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_GETSTATE ;
|
||
}
|
||
}
|
||
pSession->CallCount = 0;
|
||
pSession->Tick = GetTickCount();
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
DebugLog((DEB_ERROR, "[%x] Dispatch: Unknown API code %d\n",
|
||
pSession->dwProcessID, pApiMessage->ApiMessage.dwAPI));
|
||
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
|
||
pApiMessage->ApiMessage.scRet = SEC_E_UNSUPPORTED_FUNCTION;
|
||
}
|
||
|
||
DebugLog((DEB_TRACE, "[%x] LpcDispatch: retcode = %x\n", pSession->dwProcessID, pApiMessage->ApiMessage.scRet));
|
||
|
||
|
||
return(S_OK);
|
||
}
|
||
|
||
VOID
|
||
LsapInitializeCallInfo(
|
||
PLSA_CALL_INFO CallInfo,
|
||
BOOL InProcess
|
||
)
|
||
{
|
||
PLSA_CALL_INFO OriginalCall ;
|
||
|
||
OriginalCall = LsapGetCurrentCall() ;
|
||
|
||
ZeroMemory( CallInfo, sizeof( LSA_CALL_INFO ) );
|
||
|
||
CallInfo->PreviousCall = OriginalCall ;
|
||
|
||
CallInfo->InProcCall = InProcess ;
|
||
|
||
CallInfo->CallInfo.ProcessId = HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess) ;
|
||
CallInfo->CallInfo.ThreadId = HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread) ;
|
||
|
||
CallInfo->CallInfo.Attributes = 0 ;
|
||
CallInfo->Allocs = 0 ;
|
||
|
||
CallInfo->LogContext = NULL ;
|
||
}
|
||
|
||
NTSTATUS
|
||
LsapBuildCallInfo(
|
||
PSPM_LPC_MESSAGE pApiMessage,
|
||
PLSA_CALL_INFO CallInfo,
|
||
PHANDLE Impersonated,
|
||
PSession * NewSession,
|
||
PSession * OldSession
|
||
)
|
||
{
|
||
NTSTATUS scRet ;
|
||
BOOL Recurse = FALSE ;
|
||
HANDLE ImpersonatedToken ;
|
||
PSession pOldSession ;
|
||
PSession pSession ;
|
||
PLSA_CALL_INFO OriginalCall ;
|
||
|
||
OriginalCall = LsapGetCurrentCall() ;
|
||
|
||
LsapInitializeCallInfo( CallInfo,
|
||
TRUE );
|
||
|
||
//
|
||
// Save away who we were impersonating
|
||
//
|
||
|
||
scRet = NtOpenThreadToken(
|
||
NtCurrentThread(),
|
||
TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE,
|
||
TRUE,
|
||
&ImpersonatedToken
|
||
);
|
||
if (!NT_SUCCESS(scRet))
|
||
{
|
||
if (scRet != STATUS_NO_TOKEN)
|
||
{
|
||
return(scRet);
|
||
}
|
||
ImpersonatedToken = NULL ;
|
||
|
||
scRet = STATUS_SUCCESS ;
|
||
}
|
||
|
||
*Impersonated = ImpersonatedToken ;
|
||
|
||
CallInfo->InProcToken = ImpersonatedToken ;
|
||
CallInfo->Message = pApiMessage ;
|
||
|
||
//
|
||
// Check to see if we're recursing:
|
||
//
|
||
if ( OriginalCall &&
|
||
OriginalCall->InProcCall &&
|
||
pApiMessage &&
|
||
OriginalCall->Message )
|
||
{
|
||
if ( OriginalCall->Message->ApiMessage.dwAPI ==
|
||
pApiMessage->ApiMessage.dwAPI )
|
||
{
|
||
//
|
||
// Same call. Since they're both inproc, the pointers
|
||
// are valid. Compare the target strings
|
||
//
|
||
if ( pApiMessage->ApiMessage.dwAPI == SPMAPI_InitContext )
|
||
{
|
||
Recurse = (RtlCompareUnicodeString(
|
||
&pApiMessage->ApiMessage.Args.SpmArguments.API.InitContext.ssTarget,
|
||
&OriginalCall->Message->ApiMessage.Args.SpmArguments.API.InitContext.ssTarget,
|
||
TRUE ) == 0) ;
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( Recurse )
|
||
{
|
||
DebugLog(( DEB_ERROR, "Recursive call\n" ));
|
||
CallInfo->CallInfo.Attributes |= SECPKG_CALL_RECURSIVE ;
|
||
}
|
||
|
||
pOldSession = GetCurrentSession();
|
||
|
||
pSession = pDefaultSession ;
|
||
|
||
CallInfo->Session = pSession ;
|
||
|
||
SpmpReferenceSession( pSession );
|
||
|
||
*NewSession = pSession ;
|
||
*OldSession = pOldSession ;
|
||
|
||
return scRet ;
|
||
|
||
}
|
||
|
||
extern "C"
|
||
NTSTATUS
|
||
InitializeDirectDispatcher(
|
||
VOID
|
||
)
|
||
{
|
||
InternalApiLog = ApiLogCreate( 0 );
|
||
|
||
if ( InternalApiLog )
|
||
{
|
||
return STATUS_SUCCESS ;
|
||
}
|
||
|
||
return STATUS_UNSUCCESSFUL ;
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: DispatchAPIDirect
|
||
//
|
||
// Synopsis: Dispatcher to be called from security.dll when in process.
|
||
//
|
||
// Arguments: [pApiMessage] --
|
||
//
|
||
// History: 9-13-96 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
SEC_ENTRY
|
||
DispatchAPIDirect(
|
||
PSPM_LPC_MESSAGE pApiMessage)
|
||
{
|
||
NTSTATUS scRet;
|
||
PSession pOldSession;
|
||
PSession pSession;
|
||
PVOID DsaState ;
|
||
HANDLE ImpersonatedToken = NULL;
|
||
ULONG TokenSize = sizeof(HANDLE);
|
||
LSA_CALL_INFO CallInfo ;
|
||
PLSA_CALL_INFO OriginalCall ;
|
||
ULONG_PTR OriginalPackageId;
|
||
PLSAP_API_LOG_ENTRY Entry ;
|
||
|
||
//
|
||
// save off the current package hints to allow recursion in process.
|
||
//
|
||
|
||
OriginalCall = LsapGetCurrentCall() ;
|
||
OriginalPackageId = GetCurrentPackageId();
|
||
|
||
pApiMessage->pmMessage.MessageId = InterlockedIncrement( &InternalMessageId );
|
||
|
||
Entry = ApiLogAlloc( InternalApiLog );
|
||
|
||
scRet = LsapBuildCallInfo(
|
||
pApiMessage,
|
||
&CallInfo,
|
||
&ImpersonatedToken,
|
||
&pSession,
|
||
&pOldSession );
|
||
|
||
|
||
if ( !NT_SUCCESS( scRet ) )
|
||
{
|
||
return scRet ;
|
||
}
|
||
|
||
DBG_DISPATCH_PROLOGUE_EX( Entry, pApiMessage, CallInfo );
|
||
|
||
LsapSetCurrentCall( &CallInfo );
|
||
|
||
SetCurrentSession( pSession );
|
||
|
||
|
||
if ( GetDsaThreadState )
|
||
{
|
||
DsaState = GetDsaThreadState();
|
||
}
|
||
else
|
||
{
|
||
DsaState = NULL ;
|
||
}
|
||
|
||
DebugLog((DEB_TRACE,"[%x] DispatchAPIDirect: dispatching %s (%d)\n",
|
||
pSession->dwProcessID, ApiLabel(pApiMessage->ApiMessage.dwAPI),
|
||
pApiMessage->ApiMessage.dwAPI));
|
||
|
||
|
||
scRet = 0;
|
||
|
||
if ((pApiMessage->ApiMessage.dwAPI >= LsapAuLookupPackageApi) &&
|
||
(pApiMessage->ApiMessage.dwAPI < SPMAPI_MaxApiNumber) &&
|
||
(LpcDispatchTable[pApiMessage->ApiMessage.dwAPI] != NULL) )
|
||
{
|
||
|
||
scRet = LpcDispatchTable[pApiMessage->ApiMessage.dwAPI](pApiMessage);
|
||
|
||
}
|
||
else
|
||
{
|
||
DebugLog((DEB_ERROR, "[%x] Dispatch: Unknown API code %x\n", pSession->dwProcessID, pApiMessage->ApiMessage.dwAPI));
|
||
pApiMessage->ApiMessage.Args.SpmArguments.fAPI |= SPMAPI_FLAG_ERROR_RET;
|
||
pApiMessage->ApiMessage.scRet = SEC_E_UNSUPPORTED_FUNCTION;
|
||
}
|
||
|
||
DebugLog((DEB_TRACE, "[%x] DispatchAPIDirect: retcode = %x\n", pSession->dwProcessID, pApiMessage->ApiMessage.scRet));
|
||
|
||
if ( DsaState )
|
||
{
|
||
RestoreDsaThreadState( DsaState );
|
||
}
|
||
|
||
if ( pOldSession != pSession )
|
||
{
|
||
SetCurrentSession( pOldSession );
|
||
}
|
||
|
||
DBG_DISPATCH_POSTLOGUE( ULongToPtr( pApiMessage->ApiMessage.scRet ),
|
||
pApiMessage->ApiMessage.dwAPI );
|
||
|
||
SpmpDereferenceSession( pSession );
|
||
|
||
SetCurrentPackageId( OriginalPackageId );
|
||
|
||
LsapSetCurrentCall( OriginalCall );
|
||
|
||
(void) NtSetInformationThread(
|
||
NtCurrentThread(),
|
||
ThreadImpersonationToken,
|
||
(PVOID) &ImpersonatedToken,
|
||
sizeof(HANDLE)
|
||
);
|
||
|
||
if ( ImpersonatedToken )
|
||
{
|
||
NtClose( ImpersonatedToken );
|
||
}
|
||
|
||
return( SEC_E_OK );
|
||
|
||
}
|
||
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LpcLsaPolicyChangeNotify
|
||
//
|
||
// Synopsis: Lpc stub for LsaPolicyChangeNotify
|
||
//
|
||
// Arguments: [pApiMessage] --
|
||
//
|
||
// History: 06-05-98 MacM Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LpcLsaPolicyChangeNotify(
|
||
PSPM_LPC_MESSAGE pApiMessage
|
||
)
|
||
{
|
||
SPMLsaPolicyChangeNotifyAPI * Args = &pApiMessage->ApiMessage.Args.SpmArguments.API.LsaPolicyChangeNotify;
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
HANDLE LocalHandle = NULL;
|
||
PSession Session;
|
||
|
||
Session = GetCurrentSession();
|
||
|
||
Status = CheckCaller( Session );
|
||
|
||
if ( !NT_SUCCESS( Status ) ) {
|
||
|
||
DebugLog(( DEB_ERROR, "CheckCaller returned 0x%lx\n", Status ));
|
||
|
||
return( Status );
|
||
|
||
}
|
||
|
||
//
|
||
// Duplicate the handle
|
||
//
|
||
Status = NtDuplicateObject( Session->hProcess,
|
||
Args->EventHandle,
|
||
NtCurrentProcess(),
|
||
&LocalHandle,
|
||
0,
|
||
0,
|
||
DUPLICATE_SAME_ACCESS );
|
||
|
||
//
|
||
// Now, the notify
|
||
//
|
||
if (NT_SUCCESS( Status )) {
|
||
|
||
Status = LsapNotifyProcessNotificationEvent( Args->NotifyInfoClass,
|
||
LocalHandle,
|
||
Session->dwProcessID,
|
||
Args->EventHandle,
|
||
Args->Register );
|
||
|
||
if ( NT_SUCCESS( Status )) {
|
||
// Indicate that we've successfully registered the handle
|
||
LocalHandle = NULL;
|
||
}
|
||
|
||
//
|
||
// Since we duplicated the handle in our namespace, if we fail to register it,
|
||
// make sure we close it
|
||
//
|
||
if ( LocalHandle != NULL ) {
|
||
NtClose( LocalHandle );
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
pApiMessage->ApiMessage.scRet = Status;
|
||
|
||
return( Status );
|
||
}
|
||
|