2025-04-27 07:49:33 -04:00

762 lines
19 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
negstub.cxx
Abstract:
Negotiate Security Support Provider client stubs.
Author:
Chandana Surlu (ChandanS) 11-Aug-1997
Environment: Win9x User Mode
Revision History:
--*/
#include <kerb.hxx>
#define NEGSTUB_ALLOCATE
#include <stdarg.h> // Variable-length argument support
#include <cryptdll.h>
#include "negotiat.hxx"
#include <debug.h>
SECPKG_DLL_FUNCTIONS UserFunctionTable;
VOID
NegShutdownSecurityInterface(
VOID
);
VOID DumpLogonSession();
BOOL WINAPI DllMain(
HINSTANCE hInstance,
ULONG dwReason,
PVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
InitializeCriticalSection( &NegDllCritSect );
#if DBG
InitializeCriticalSection( &NegGlobalLogFileCritSect );
NegInfoLevel = DEB_ERROR | DEB_WARN | DEB_TRACE | DEB_TRACE_API |
DEB_TRACE_NEG | DEB_TRACE_NEG_LOCKS;
#endif // DBG
}
else if (dwReason == DLL_PROCESS_DETACH)
{
NegShutdownSecurityInterface();
#if DBG
DeleteCriticalSection( &NegGlobalLogFileCritSect );
#endif // DBG
DeleteCriticalSection( &NegDllCritSect );
}
return TRUE;
}
PSecurityFunctionTable
InitSecurityInterfaceA(
VOID
)
/*++
Routine Description:
RPC calls this function to get the addresses of all the other functions
that it might call.
Arguments:
None.
Return Value:
A pointer to our static SecurityFunctionTable. The caller need
not deallocate this table.
--*/
{
SECURITY_STATUS Status = SEC_E_OK;
// BUBUG Init this to something, we need Parameters.DomainName,
// Parameters.DnsDomainName & Parameters.version at least
SECPKG_PARAMETERS Parameters;
DebugLog((DEB_TRACE_API, "Entering InitSecurityInterface\n"));
// Initialize the SecurityFunctionTable
ZeroMemory( &NegDllSecurityFunctionTable,
sizeof(NegDllSecurityFunctionTable) );
NegDllSecurityFunctionTable.dwVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION;
NegDllSecurityFunctionTable.EnumerateSecurityPackages = NegEnumerateSecurityPackages;
NegDllSecurityFunctionTable.AcquireCredentialsHandle = SpAcquireCredentialsHandle;
NegDllSecurityFunctionTable.FreeCredentialHandle = SpFreeCredentialsHandle;
NegDllSecurityFunctionTable.InitializeSecurityContext = SpInitializeSecurityContext;
NegDllSecurityFunctionTable.QueryCredentialsAttributes = SpQueryCredentialsAttributes;
NegDllSecurityFunctionTable.AcceptSecurityContext = SpAcceptSecurityContext;
NegDllSecurityFunctionTable.CompleteAuthToken = SpCompleteAuthToken;
NegDllSecurityFunctionTable.QueryContextAttributes = SpQueryContextAttributes;
NegDllSecurityFunctionTable.SspiLogonUser = NULL;
NegDllSecurityFunctionTable.DeleteSecurityContext = SpDeleteSecurityContext;
NegDllSecurityFunctionTable.ApplyControlToken = SpApplyControlToken;
NegDllSecurityFunctionTable.ImpersonateSecurityContext = NULL;
NegDllSecurityFunctionTable.RevertSecurityContext = NULL;
NegDllSecurityFunctionTable.MakeSignature = NULL;
NegDllSecurityFunctionTable.VerifySignature = NULL;
NegDllSecurityFunctionTable.FreeContextBuffer = NegFreeContextBuffer;
NegDllSecurityFunctionTable.QuerySecurityPackageInfo = NegQuerySecurityPackageInfo;
NegDllSecurityFunctionTable.Reserved3 = NULL;
NegDllSecurityFunctionTable.Reserved4 = NULL;
Parameters.MachineState = SECPKG_STATE_STANDALONE;
Status = NegInitialize(2, &Parameters, &FunctionTable);
DebugLog((DEB_TRACE_API, "NegInitialize returned 0x%x\n", Status));
DebugLog((DEB_TRACE_API, "Leaving InitSecurityInterface\n"));
return SEC_SUCCESS(Status) ? &NegDllSecurityFunctionTable : NULL;
}
VOID
NegShutdownSecurityInterface(
VOID
)
/*++
Routine Description:
Cleanup the data shared by the DLL and SERVICE.
Arguments:
None.
Return Value:
None.
--*/
{
DebugLog((DEB_TRACE_API, "Entering NegShutdownSecurityInterface\n"));
// NegShutdown();
DebugLog((DEB_TRACE_API, "Leaving NegShutdownSecurityInterface\n"));
}
SECURITY_STATUS
NegEnumerateSecurityPackages(
OUT PULONG PackageCount,
OUT PSecPkgInfo *PackageInfo
)
/*++
Routine Description:
This API returns a list of Security Packages available to client (i.e.
those that are either loaded or can be loaded on demand). The caller
must free the returned buffer with FreeContextBuffer. This API returns
a list of all the security packages available to a service. The names
returned can then be used to acquire credential handles, as well as
determine which package in the system best satisfies the requirements
of the caller. It is assumed that all available packages can be
included in the single call.
This is really a dummy API that just returns information about this
security package. It is provided to ensure this security package has the
same interface as the multiplexer DLL does.
Arguments:
PackageCount - Returns the number of packages supported.
PackageInfo - Returns an allocate array of structures
describing the security packages. The array must be freed
using FreeContextBuffer.
Return Value:
SEC_E_OK -- Call completed successfully
SEC_E_PACKAGE_UNKNOWN -- Package being queried is not this package
SEC_E_INSUFFICIENT_MEMORY -- Not enough memory
--*/
{
//
// Get the information for this package.
//
LPTSTR Where;
DebugLog((DEB_TRACE_API, "Entering NegEnumerateSecurityPackages\n"));
*PackageCount = 1;
//
// Allocate a buffer for the PackageInfo
//
*PackageInfo = (PSecPkgInfo) LocalAlloc( 0, sizeof(SecPkgInfo) +
sizeof(NEGOSSP_NAME_A) +
sizeof(NEGOSSP_PACKAGE_COMMENT) );
if ( *PackageInfo == NULL ) {
return SEC_E_INSUFFICIENT_MEMORY;
}
//
// Fill in the information.
//
(*PackageInfo)->fCapabilities = SECPKG_FLAG_INTEGRITY |
SECPKG_FLAG_PRIVACY |
SECPKG_FLAG_DATAGRAM |
SECPKG_FLAG_CONNECTION |
SECPKG_FLAG_MULTI_REQUIRED |
SECPKG_FLAG_EXTENDED_ERROR |
SECPKG_FLAG_IMPERSONATION |
SECPKG_FLAG_ACCEPT_WIN32_NAME |
SECPKG_FLAG_LOGON;
(*PackageInfo)->wVersion = 1;
(*PackageInfo)->wRPCID = NEGOSSP_RPCID;
(*PackageInfo)->cbMaxToken = 4000;
Where = (LPTSTR)((*PackageInfo)+1);
(*PackageInfo)->Name = Where;
lstrcpy( Where, NEGOSSP_NAME);
Where += lstrlen(Where) + 1;
(*PackageInfo)->Comment = Where;
lstrcpy( Where, NEGOSSP_PACKAGE_COMMENT);
Where += lstrlen(Where) + 1;
return SEC_E_OK;
}
SECURITY_STATUS
NegQuerySecurityPackageInfo (
LPTSTR PackageName,
PSecPkgInfo SEC_FAR * Package
)
{
ULONG PackageCount;
DebugLog((DEB_TRACE_API, "Entering NegQuerySecurityPackageInfo\n"));
return ( NegEnumerateSecurityPackages(
&PackageCount,
Package));
}
SECURITY_STATUS SEC_ENTRY
NegFreeContextBuffer (
void __SEC_FAR * ContextBuffer
)
/*++
Routine Description:
This API is provided to allow callers of security API such as
InitializeSecurityContext() for free the memory buffer allocated for
returning the outbound context token.
Arguments:
ContextBuffer - Address of the buffer to be freed.
Return Value:
SEC_E_OK - Call completed successfully
--*/
{
//
// The only allocated buffer that the kerb currently returns to the caller
// is from EnumeratePackages. It uses LocalAlloc to allocate memory. If
// we ever need memory to be allocated by the service, we have to rethink
// how this routine distinguishes between to two types of allocated memory.
//
DebugLog((DEB_TRACE_API, "Entering NegFreeContextBuffer\n"));
(VOID) LocalFree( ContextBuffer );
return SEC_E_OK;
}
SECURITY_STATUS
SpAcquireCredentialsHandle(
IN LPTSTR PrincipalName,
IN LPTSTR PackageName,
IN ULONG CredentialUseFlags,
IN PVOID LogonId,
IN PVOID AuthData,
IN SEC_GET_KEY_FN GetKeyFunction,
IN PVOID GetKeyArgument,
OUT PCredHandle CredentialHandle,
OUT PTimeStamp Lifetime
)
{
SECURITY_STATUS SecStatus = SEC_E_OK;
UNICODE_STRING NewPrincipalName;
DebugLog((DEB_TRACE_API, "Entering SpAcquireCredentialsHandle\n"));
//
// Validate the arguments
//
if ( lstrcmpi( PackageName, NEGOSSP_NAME) != 0 ) {
SecStatus = SEC_E_SECPKG_NOT_FOUND;
goto Cleanup;
}
if ( (CredentialUseFlags & SECPKG_CRED_OUTBOUND) &&
ARGUMENT_PRESENT(PrincipalName) && *PrincipalName != '\0' ) {
SecStatus = SEC_E_UNKNOWN_CREDENTIALS;
goto Cleanup;
}
if ( ARGUMENT_PRESENT(LogonId) ) {
SecStatus = SEC_E_UNSUPPORTED_FUNCTION;
goto Cleanup;
}
if ( ARGUMENT_PRESENT(GetKeyFunction) ) {
SecStatus = SEC_E_UNSUPPORTED_FUNCTION;
goto Cleanup;
}
if ( ARGUMENT_PRESENT(GetKeyArgument) ) {
SecStatus = SEC_E_UNSUPPORTED_FUNCTION;
goto Cleanup;
}
if (!RtlCreateUnicodeStringFromAsciiz (&NewPrincipalName, PrincipalName))
{
SecStatus = SEC_E_INSUFFICIENT_MEMORY;
goto Cleanup;
}
SecStatus = NegAcquireCredentialsHandle(
&NewPrincipalName,
CredentialUseFlags,
(PLUID)LogonId,
AuthData,
GetKeyFunction,
GetKeyArgument,
&CredentialHandle->dwUpper,
Lifetime );
Cleanup:
return SecStatus;
}
SECURITY_STATUS
SpFreeCredentialsHandle(
IN PCredHandle CredentialHandle
)
/*++
Routine Description:
This API is used to notify the security system that the credentials are
no longer needed and allows the application to free the handle acquired
in the call described above. When all references to this credential
set has been removed then the credentials may themselves be removed.
Arguments:
CredentialHandle - Credential Handle obtained through
AcquireCredentialHandle.
Return Value:
SEC_E_OK -- Call completed successfully
SEC_E_NO_SPM -- Security Support Provider is not running
SEC_E_INVALID_HANDLE -- Credential Handle is invalid
--*/
{
SECURITY_STATUS SecStatus;
DebugLog((DEB_TRACE_API, "Entering SpFreeCredentialsHandle\n"));
SecStatus = NegFreeCredentialsHandle(
CredentialHandle->dwUpper );
return SecStatus;
}
SECURITY_STATUS
SpQueryCredentialsAttributes(
IN PCredHandle CredentialsHandle,
IN ULONG Attribute,
OUT PVOID Buffer
)
{
SECURITY_STATUS SecStatus;
DebugLog((DEB_TRACE_API, "Entering SpQueryCredentialsAttributes\n"));
SecStatus = NegQueryCredentialsAttributes(
CredentialsHandle->dwUpper,
Attribute,
Buffer );
return SecStatus;
}
SECURITY_STATUS
SpInitializeSecurityContext(
IN PCredHandle CredentialHandle,
IN PCtxtHandle OldContextHandle,
IN LPTSTR TargetName,
IN ULONG ContextReqFlags,
IN ULONG Reserved1,
IN ULONG TargetDataRep,
IN PSecBufferDesc InputToken,
IN ULONG Reserved2,
OUT PCtxtHandle NewContextHandle,
OUT PSecBufferDesc OutputToken,
OUT PULONG ContextAttributes,
OUT PTimeStamp ExpirationTime
)
{
UNICODE_STRING TargetNameUStr;
BOOLEAN fMappedContext;
SecBuffer ContextData;
SECURITY_STATUS SecStatus = SEC_E_OK;
SECURITY_STATUS SecondaryStatus = SEC_E_OK;
SecBufferDesc EmptyBuffer = {0,0, NULL};
DebugLog((DEB_TRACE_API, "Entering SpInitializeSecurityContext\n"));
RtlCreateUnicodeStringFromAsciiz (&TargetNameUStr, TargetName);
if (!ARGUMENT_PRESENT(InputToken))
{
InputToken = &EmptyBuffer;
}
if (!ARGUMENT_PRESENT(OutputToken))
{
OutputToken = &EmptyBuffer;
}
SecStatus = NegInitLsaModeContext (
CredentialHandle ? CredentialHandle->dwUpper : NULL,
OldContextHandle ? OldContextHandle->dwUpper : NULL,
&TargetNameUStr,
ContextReqFlags,
TargetDataRep,
InputToken,
&NewContextHandle->dwUpper,
OutputToken,
ContextAttributes,
ExpirationTime,
&fMappedContext,
&ContextData);
(VOID) RtlFreeUnicodeString( &TargetNameUStr );
return SecStatus;
}
SECURITY_STATUS
SpAcceptSecurityContext(
IN PCredHandle CredentialHandle,
IN PCtxtHandle OldContextHandle,
IN PSecBufferDesc InputToken,
IN ULONG ContextReqFlags,
IN ULONG TargetDataRep,
OUT PCtxtHandle NewContextHandle,
OUT PSecBufferDesc OutputToken,
OUT PULONG ContextAttributes,
OUT PTimeStamp ExpirationTime
)
{
BOOLEAN fMappedContext;
SecBuffer ContextData;
SECURITY_STATUS SecStatus = SEC_E_OK;
SECURITY_STATUS SecondaryStatus = SEC_E_OK;
SecBufferDesc EmptyBuffer = {0,0, NULL};
DebugLog((DEB_TRACE_API, "Entering SpAcceptSecurityContext\n"));
if (!ARGUMENT_PRESENT(InputToken))
{
InputToken = &EmptyBuffer;
}
if (!ARGUMENT_PRESENT(OutputToken))
{
OutputToken = &EmptyBuffer;
}
SecStatus = NegAcceptLsaModeContext (
CredentialHandle ? CredentialHandle->dwUpper : NULL,
OldContextHandle ? OldContextHandle->dwUpper : NULL,
InputToken,
ContextReqFlags,
TargetDataRep,
&NewContextHandle->dwUpper,
OutputToken,
ContextAttributes,
ExpirationTime,
&fMappedContext,
&ContextData);
return SecStatus;
}
SECURITY_STATUS
SpDeleteSecurityContext (
IN PCtxtHandle ContextHandle
)
{
SECURITY_STATUS SecStatus = SEC_E_OK;
DebugLog((DEB_TRACE_API, "Entering SpDeleteSecurityContext\n"));
SecStatus = NegDeleteLsaModeContext (ContextHandle->dwUpper);
return SecStatus;
}
SECURITY_STATUS
SpApplyControlToken (
PCtxtHandle ContextHandle,
PSecBufferDesc Input
)
{
SECURITY_STATUS SecStatus = SEC_E_OK;
DebugLog((DEB_TRACE_API, "Entering SpApplyControlToken\n"));
SecStatus = NegApplyControlToken(ContextHandle->dwUpper, Input);
return SecStatus;
}
SECURITY_STATUS
NegImpersonateSecurityContext (
PCtxtHandle ContextHandle
)
{
DebugLog((DEB_TRACE_API, "Entering NegImpersonateSecurityContext\n"));
return (SEC_E_NO_IMPERSONATION);
}
SECURITY_STATUS
NegRevertSecurityContext (
PCtxtHandle ContextHandle
)
{
DebugLog((DEB_TRACE_API, "Entering NegRevertSecurityContext\n"));
return (SEC_E_NO_IMPERSONATION);
}
SECURITY_STATUS
SpQueryContextAttributes(
IN PCtxtHandle ContextHandle,
IN ULONG Attribute,
OUT PVOID Buffer
)
{
DebugLog((DEB_TRACE_API, "Entering SpQueryContextAttributes\n"));
return (SEC_E_UNSUPPORTED_FUNCTION);
}
SECURITY_STATUS SEC_ENTRY
SpCompleteAuthToken (
PCtxtHandle ContextHandle,
PSecBufferDesc BufferDescriptor
)
{
DebugLog((DEB_TRACE_API, "Entering SpCompleteAuthToken\n"));
return (SEC_E_UNSUPPORTED_FUNCTION);
}
#if DBG
//
// Control which messages get displayed
//
// DWORD NegInfoLevel = DEB_ERROR | DEB_WARN | DEB_TRACE | DEB_TRACE_API;
//
// SspPrintRoutine - Displays debug output
//
VOID __cdecl
NegPrintRoutine(
IN DWORD DebugFlag,
IN LPCSTR FormatString, // PRINTF()-STYLE FORMAT STRING.
... // OTHER ARGUMENTS ARE POSSIBLE.
)
{
static char prefix[] = "NEG: ";
char outbuf[256];
va_list args;
if ( DebugFlag & NegInfoLevel) {
EnterCriticalSection( &NegGlobalLogFileCritSect );
lstrcpy(outbuf, prefix);
va_start(args, FormatString);
wvsprintf(outbuf + sizeof(prefix) - 1, FormatString, args);
OutputDebugString(outbuf);
LeaveCriticalSection( &NegGlobalLogFileCritSect );
}
return;
}
#endif DBG
//+-------------------------------------------------------------------------
//
// Function: LsapDuplicateString
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//--------------------------------------------------------------------------
NTSTATUS
LsapDuplicateString(
OUT PUNICODE_STRING pDest,
IN PUNICODE_STRING pSrc
)
{
pDest->Length = 0;
if (pSrc == NULL)
{
pDest->Buffer = NULL;
pDest->MaximumLength = 0;
return(STATUS_SUCCESS);
}
pDest->Buffer = (LPWSTR) LsapAllocateLsaHeap(pSrc->Length + sizeof(WCHAR));
if (pDest->Buffer)
{
pDest->MaximumLength = pSrc->Length + sizeof(WCHAR);
RtlCopyMemory(
pDest->Buffer,
pSrc->Buffer,
pSrc->Length
);
pDest->Buffer[pSrc->Length/sizeof(WCHAR)] = L'\0';
pDest->Length = pSrc->Length;
return(STATUS_SUCCESS);
} else
{
pDest->MaximumLength = 0;
return(STATUS_INSUFFICIENT_RESOURCES);
}
}
//+-------------------------------------------------------------------------
//
// Function: MIDL_user_allocate
//
// Synopsis: Allocation routine for use by RPC client stubs
//
// Effects: allocates memory with LsaFunctions.AllocateLsaHeap
//
// Arguments: BufferSize - size of buffer, in bytes, to allocate
//
// Requires:
//
// Returns: Buffer pointer or NULL on allocation failure
//
// Notes:
//
//
//--------------------------------------------------------------------------
PVOID
MIDL_user_allocate(
IN size_t BufferSize
)
{
return(LocalAlloc( 0, BufferSize) );
}
//+-------------------------------------------------------------------------
//
// Function: MIDL_user_free
//
// Synopsis: Memory free routine for RPC client stubs
//
// Effects: frees the buffer with LsaFunctions.FreeLsaHeap
//
// Arguments: Buffer - Buffer to free
//
// Requires:
//
// Returns: none
//
// Notes:
//
//
//--------------------------------------------------------------------------
VOID
MIDL_user_free(
IN PVOID Buffer
)
{
LocalFree( Buffer );
}