You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1402 lines
43 KiB
1402 lines
43 KiB
/*++
|
|
|
|
Copyright (c) 1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
stub.c
|
|
|
|
Abstract:
|
|
|
|
Kerberos Security Support Provider client stubs.
|
|
|
|
Author:
|
|
|
|
Chandana Surlu (ChandanS) 11-Feb-1997
|
|
|
|
Environment: Win9x User Mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <kerb.hxx>
|
|
|
|
#include <rpc.h> // PSEC_WINNT_AUTH_IDENTITY
|
|
#include <stdarg.h> // Variable-length argument support
|
|
|
|
#define KERBSTUB_ALLOCATE
|
|
|
|
#include <kerbp.h>
|
|
|
|
SECPKG_DLL_FUNCTIONS UserFunctionTable;
|
|
VOID
|
|
KerbShutdownSecurityInterface(
|
|
VOID
|
|
);
|
|
|
|
VOID DumpLogonSession();
|
|
|
|
BOOL WINAPI DllMain(
|
|
HINSTANCE hInstance,
|
|
ULONG dwReason,
|
|
PVOID lpReserved)
|
|
{
|
|
if (dwReason == DLL_PROCESS_ATTACH)
|
|
{
|
|
InitializeCriticalSection( &KerbDllCritSect );
|
|
|
|
#if DBG
|
|
InitializeCriticalSection( &KerbGlobalLogFileCritSect );
|
|
KerbInfoLevel = DEB_ERROR | DEB_WARN | DEB_TRACE | DEB_TRACE_API |
|
|
DEB_TRACE_CRED | DEB_TRACE_CTXT | DEB_TRACE_LOCKS |
|
|
DEB_TRACE_CTXT2 | DEB_TRACE_KDC | DEB_TRACE_LSESS |
|
|
DEB_TRACE_LOGON;
|
|
#endif // DBG
|
|
}
|
|
else if (dwReason == DLL_PROCESS_DETACH)
|
|
{
|
|
KerbShutdownSecurityInterface();
|
|
#if DBG
|
|
DeleteCriticalSection( &KerbGlobalLogFileCritSect );
|
|
#endif // DBG
|
|
|
|
DeleteCriticalSection( &KerbDllCritSect );
|
|
}
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
HKEY hRegKey;
|
|
DWORD dwError = 0, dwSize = 0;
|
|
DWORD dwType = REG_BINARY;
|
|
LPWSTR pUserName = NULL, pDomainName = NULL;
|
|
PKERB_LOGON_SESSION_CACHE RegLogonSession = NULL;
|
|
PKERB_LOGON_SESSION LogonSession = NULL;
|
|
SECURITY_STATUS Status = SEC_E_OK;
|
|
|
|
// BUBUG Init this to something, we need Parameters.DomainName,
|
|
// Parameters.DnsDomainName & Parameters.version at least
|
|
SECPKG_PARAMETERS Parameters;
|
|
PVOID ignored = NULL;
|
|
|
|
DebugLog((DEB_TRACE_API, "Entering KerbInitSecurityInterface\n"));
|
|
|
|
// Initialize the SecurityFunctionTable
|
|
ZeroMemory( &KerbDllSecurityFunctionTable,
|
|
sizeof(KerbDllSecurityFunctionTable) );
|
|
|
|
KerbGlobalCapabilities = KERBEROS_CAPABILITIES;
|
|
|
|
KerberosState = KerberosUserMode;
|
|
|
|
KerbDllSecurityFunctionTable.dwVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION;
|
|
|
|
KerbDllSecurityFunctionTable.EnumerateSecurityPackages = KerbEnumerateSecurityPackages;
|
|
KerbDllSecurityFunctionTable.AcquireCredentialsHandle = KerbAcquireCredentialsHandle;
|
|
KerbDllSecurityFunctionTable.FreeCredentialHandle = KerbFreeCredentialsHandle;
|
|
KerbDllSecurityFunctionTable.InitializeSecurityContext = KerbInitializeSecurityContext;
|
|
KerbDllSecurityFunctionTable.QueryCredentialsAttributes = KerbQueryCredentialsAttributes;
|
|
KerbDllSecurityFunctionTable.AcceptSecurityContext = NULL;
|
|
KerbDllSecurityFunctionTable.CompleteAuthToken = KerbCompleteAuthToken;
|
|
KerbDllSecurityFunctionTable.QueryContextAttributes = KerbQueryContextAttributes;
|
|
KerbDllSecurityFunctionTable.SspiLogonUser = KerbSspiLogonUser;
|
|
KerbDllSecurityFunctionTable.DeleteSecurityContext = KerbDeleteSecurityContext;
|
|
KerbDllSecurityFunctionTable.ApplyControlToken = KerbApplyControlToken;
|
|
KerbDllSecurityFunctionTable.ImpersonateSecurityContext = KerbImpersonateSecurityContext;
|
|
KerbDllSecurityFunctionTable.RevertSecurityContext = KerbRevertSecurityContext;
|
|
KerbDllSecurityFunctionTable.MakeSignature = KerbMakeSignature;
|
|
KerbDllSecurityFunctionTable.VerifySignature = KerbVerifySignature;
|
|
KerbDllSecurityFunctionTable.FreeContextBuffer = KerbFreeContextBuffer;
|
|
KerbDllSecurityFunctionTable.QuerySecurityPackageInfo = KerbQuerySecurityPackageInfo;
|
|
KerbDllSecurityFunctionTable.Reserved3 = KerbSealMessage;
|
|
KerbDllSecurityFunctionTable.Reserved4 = KerbUnsealMessage;
|
|
KerbDllSecurityFunctionTable.EncryptMessage = KerbSealMessage;
|
|
KerbDllSecurityFunctionTable.DecryptMessage = KerbUnsealMessage;
|
|
|
|
|
|
// Before we call SpInitialize, fill a table of LsaFunctions that are
|
|
// imlemented locally. This is done so that the code does not look awful.
|
|
// Fill in dummy functions in case more functions are used so we don't
|
|
// av
|
|
|
|
// FunctionTable.CreateLogonSession = CreateLogonSession;
|
|
// FunctionTable.DeleteLogonSession = DeleteLogonSession;
|
|
// FunctionTable.AddCredential = AddCredential;
|
|
// FunctionTable.GetCredentials = GetCredentials;
|
|
// FunctionTable.DeleteCredential = DeleteCredential;
|
|
FunctionTable.AllocateLsaHeap = AllocateLsaHeap;
|
|
FunctionTable.FreeLsaHeap = FreeLsaHeap;
|
|
FunctionTable.AllocateClientBuffer = AllocateClientBuffer;
|
|
FunctionTable.FreeClientBuffer = FreeClientBuffer;
|
|
FunctionTable.CopyToClientBuffer = CopyToClientBuffer;
|
|
FunctionTable.CopyFromClientBuffer = CopyFromClientBuffer;
|
|
// FunctionTable.ImpersonateClient = ImperosnateClient;
|
|
// FunctionTable.UnloadPackage = UnloadPackage;
|
|
FunctionTable.DuplicateHandle = KerbDuplicateHandle;
|
|
// FunctionTable.SaveSupplementalCredentials = SaveSupplementalCredentials;
|
|
// FunctionTable.GetWindow = GetWindow;
|
|
// FunctionTable.ReleaseWindow = ReleaseWindow;
|
|
// FunctionTable.CreateThread = CreateThread;
|
|
FunctionTable.GetClientInfo = GetClientInfo;
|
|
// FunctionTable.RegisterNotification = RegisterNotification;
|
|
// FunctionTable.CancelNotification = CancelNotification;
|
|
FunctionTable.MapBuffer = MapBuffer;
|
|
// FunctionTable.CreateToken = CreateToken;
|
|
FunctionTable.AuditLogon = AuditLogon;
|
|
// FunctionTable.CallPackage = CallPackage;
|
|
FunctionTable.FreeReturnBuffer = FreeReturnBuffer;
|
|
FunctionTable.GetCallInfo = GetCallInfo;
|
|
// FunctionTable.CallPackageEx = CallPackageEx;
|
|
// FunctionTable.CreateSharedMemory = CreateSharedMemory;
|
|
// FunctionTable.AllocateSharedMemory = AllocateSharedMemory;
|
|
// FunctionTable.FreeSharedMemory = FreeSharedMemory;
|
|
// FunctionTable.DeleteSharedMemory = DeleteSharedMemory;
|
|
// FunctionTable.OpenSamUser = OpenSamUser;
|
|
// FunctionTable.GetUserCredentials = GetUserCredentials;
|
|
// FunctionTable.GetUserAuthData = GetUserAuthData;
|
|
// FunctionTable.CloseSamUser = CloseSamUser;
|
|
// FunctionTable.ConvertAuthDataToTokenInfo = ConvertAuthDataToTokenInfo;
|
|
|
|
// we call into the kerb routines
|
|
Parameters.Version = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION;
|
|
Parameters.MachineState = SECPKG_STATE_STANDALONE;
|
|
|
|
// NOTE - Yikes!
|
|
Parameters.DomainName.Buffer = L"";
|
|
Parameters.DomainName.Length = 0;
|
|
Parameters.DomainName.MaximumLength = 2;
|
|
Parameters.DnsDomainName.Buffer = L"";
|
|
Parameters.DnsDomainName.Length = 0;
|
|
Parameters.DnsDomainName.MaximumLength = 2;
|
|
|
|
// If logon session data exists, load it
|
|
|
|
if ( ERROR_SUCCESS != ( dwError = RegOpenKeyEx (
|
|
HKEY_LOCAL_MACHINE,
|
|
KERBEROS_TICKET_KEY,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hRegKey ) ) )
|
|
{
|
|
DebugLog((DEB_ERROR, "Error opening KERBEROS_TICKET_KEY\n"));
|
|
goto RestOfInit;
|
|
}
|
|
|
|
// get username size
|
|
if ( ERROR_SUCCESS != ( dwError = RegQueryValueEx (
|
|
hRegKey,
|
|
KERBEROS_TICKET_USERNAME_KEY,
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize )))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error reading KERBEROS_TICKET_USERNAME_KEY size\n"));
|
|
goto RestOfInit;
|
|
}
|
|
|
|
if (dwSize == 0 )
|
|
{
|
|
DebugLog((DEB_ERROR, "KERBEROS_TICKET_USERNAME_KEY contains 0 bytes\n"));
|
|
goto RestOfInit;
|
|
}
|
|
|
|
pUserName = (LPWSTR) KerbAllocate(dwSize);
|
|
|
|
if (pUserName == NULL)
|
|
{
|
|
DebugLog((DEB_ERROR, "Error allocing KERBEROS_TICKET_USERNAME_KEY \n"));
|
|
goto RestOfInit;
|
|
}
|
|
// get username into LogonSession->PrimaryCredentials->Username
|
|
if ( ERROR_SUCCESS != ( dwError = RegQueryValueEx (
|
|
hRegKey,
|
|
KERBEROS_TICKET_USERNAME_KEY,
|
|
NULL,
|
|
&dwType,
|
|
(PUCHAR) pUserName,
|
|
&dwSize )))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error reading from KERBEROS_TICKET_USERNAME_KEY\n"));
|
|
goto RestOfInit;
|
|
}
|
|
|
|
// get domainname
|
|
if ( ERROR_SUCCESS != ( dwError = RegQueryValueEx (
|
|
hRegKey,
|
|
KERBEROS_TICKET_DOMAINNAME_KEY,
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize )))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error reading KERBEROS_TICKET_DOMAINNAME_KEY size\n"));
|
|
goto RestOfInit;
|
|
}
|
|
if (dwSize == 0 )
|
|
{
|
|
DebugLog((DEB_ERROR, "KERBEROS_TICKET_DOMAINNAME_KEY contains 0 bytes\n"));
|
|
goto RestOfInit;
|
|
}
|
|
|
|
pDomainName = (LPWSTR) KerbAllocate(dwSize);
|
|
|
|
if (pDomainName == NULL)
|
|
{
|
|
DebugLog((DEB_ERROR, "Error allocing KERBEROS_TICKET_DOMAINNAME_KEY \n"));
|
|
goto RestOfInit;
|
|
}
|
|
// get domainname into LogonSession->PrimaryCredentials->Domainname
|
|
if ( ERROR_SUCCESS != ( dwError = RegQueryValueEx (
|
|
hRegKey,
|
|
KERBEROS_TICKET_DOMAINNAME_KEY,
|
|
NULL,
|
|
&dwType,
|
|
(PUCHAR) pDomainName,
|
|
&dwSize )))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error reading from KERBEROS_TICKET_DOMAINNAME_KEY\n"));
|
|
goto RestOfInit;
|
|
}
|
|
|
|
// get domainname into Parameters.DomainName
|
|
Parameters.DomainName.Buffer = pDomainName;
|
|
Parameters.DomainName.Length = (USHORT)dwSize;
|
|
Parameters.DomainName.MaximumLength = (USHORT)dwSize;
|
|
|
|
|
|
// get logon session data size
|
|
if ( ERROR_SUCCESS != ( dwError = RegQueryValueEx (
|
|
hRegKey,
|
|
KERBEROS_TICKET_LOGONSESSION_KEY,
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize )))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error reading from KERBEROS_TICKET_LOGONSESSION_KEY\n"));
|
|
goto RestOfInit;
|
|
}
|
|
|
|
if (dwSize == 0 )
|
|
{
|
|
DebugLog((DEB_ERROR, "KERBEROS_TICKET_LOGONSESSION_KEY contains 0 bytes\n"));
|
|
goto RestOfInit;
|
|
}
|
|
|
|
RegLogonSession = (PKERB_LOGON_SESSION_CACHE) KerbAllocate(dwSize);
|
|
|
|
if (RegLogonSession == NULL)
|
|
{
|
|
DebugLog((DEB_ERROR, "Error allocing KERBEROS_TICKET_LOGONSESSION_KEY \n"));
|
|
goto RestOfInit;
|
|
}
|
|
// get logon session into LogonSession->PrimaryCredentials->Domainname
|
|
if ( ERROR_SUCCESS != ( dwError = RegQueryValueEx (
|
|
hRegKey,
|
|
KERBEROS_TICKET_LOGONSESSION_KEY,
|
|
NULL,
|
|
&dwType,
|
|
(PUCHAR) RegLogonSession,
|
|
&dwSize )))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error reading from KERBEROS_TICKET_LOGONSESSION_KEY\n"));
|
|
goto RestOfInit;
|
|
}
|
|
|
|
|
|
if ( ERROR_SUCCESS != ( dwError = RegCloseKey ( hRegKey) ))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error closing KERBEROS_TICKET_KEY\n"));
|
|
goto RestOfInit;
|
|
}
|
|
|
|
RestOfInit:
|
|
|
|
Status = SpInitialize(1, &Parameters, &FunctionTable);
|
|
|
|
// Do the user mode init too
|
|
// Before we call SpInstanceInit, fill a table of functions that are
|
|
// imlemented locally. This is done so that the code does not look awful.
|
|
// Fill in dummy functions in case more functions are used so we don't
|
|
// av
|
|
|
|
UserFunctionTable.FreeHeap = FreeLsaHeap;
|
|
UserFunctionTable.AllocateHeap = AllocateLsaHeap;
|
|
|
|
Status = SpInstanceInit(SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
|
|
&UserFunctionTable,
|
|
&ignored );
|
|
|
|
|
|
// Now, copy the logon sessions (if they exist)
|
|
// This is kina what KerbCreateLogonSession does, expect that we don't
|
|
// have to build password list etc.
|
|
|
|
if (RegLogonSession != NULL)
|
|
{
|
|
LUID LogonId;
|
|
NTSTATUS Status;
|
|
ULONG PasswordSize, EncryptKeySize, CredentialSize;
|
|
ULONG Index;
|
|
PUCHAR Base;
|
|
UINT Offset;
|
|
|
|
//
|
|
// Allocate the new logon session
|
|
//
|
|
|
|
Status = NtAllocateLocallyUniqueId (&LogonId);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status = KerbAllocateLogonSession( &LogonSession );
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Fill in the logon session components
|
|
//
|
|
|
|
LogonSession->Lifetime = RegLogonSession->Lifetime;
|
|
LogonSession->LogonSessionFlags = RegLogonSession->LogonSessionFlags;
|
|
LogonSession->LogonId = LogonId;
|
|
|
|
//
|
|
// Munge RegLogonSession & ptrs for username & domainame
|
|
//
|
|
|
|
RegLogonSession->UserName.Buffer = (LPWSTR)((PUCHAR)RegLogonSession + (INT)(RegLogonSession->UserName.Buffer));
|
|
|
|
RegLogonSession->DomainName.Buffer = (LPWSTR)((PUCHAR)RegLogonSession + (INT)(RegLogonSession->DomainName.Buffer));
|
|
|
|
//
|
|
// actually copy the username struct and alloc username.buffer
|
|
//
|
|
|
|
LogonSession->PrimaryCredentials.UserName.Buffer = (LPWSTR) KerbAllocate(RegLogonSession->UserName.MaximumLength);
|
|
|
|
if (LogonSession->PrimaryCredentials.UserName.Buffer == NULL)
|
|
{
|
|
DebugLog((DEB_ERROR, "Error allocing KERBEROS_TICKET_LOGONSESSION_KEY \n"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
RtlCopyMemory(LogonSession->PrimaryCredentials.UserName.Buffer,
|
|
RegLogonSession->UserName.Buffer,
|
|
RegLogonSession->UserName.MaximumLength);
|
|
|
|
LogonSession->PrimaryCredentials.UserName.Length = RegLogonSession->UserName.Length;
|
|
LogonSession->PrimaryCredentials.UserName.MaximumLength = RegLogonSession->UserName.MaximumLength;
|
|
|
|
|
|
// actually copy the domainname struct and alloc domainname.buffer
|
|
|
|
LogonSession->PrimaryCredentials.DomainName.Buffer = (LPWSTR) KerbAllocate(RegLogonSession->DomainName.MaximumLength);
|
|
|
|
if (LogonSession->PrimaryCredentials.DomainName.Buffer == NULL)
|
|
{
|
|
DebugLog((DEB_ERROR, "Error allocing KERBEROS_TICKET_LOGONSESSION_KEY \n"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
RtlCopyMemory(LogonSession->PrimaryCredentials.DomainName.Buffer,
|
|
RegLogonSession->DomainName.Buffer,
|
|
RegLogonSession->DomainName.MaximumLength);
|
|
|
|
LogonSession->PrimaryCredentials.DomainName.Length = RegLogonSession->DomainName.Length;
|
|
LogonSession->PrimaryCredentials.DomainName.MaximumLength = RegLogonSession->DomainName.MaximumLength;
|
|
|
|
|
|
//
|
|
// What is the size of the Credentials struct
|
|
//
|
|
|
|
EncryptKeySize = sizeof(KERB_KEY_DATA) * RegLogonSession->CredentialCount;
|
|
PasswordSize = 0;
|
|
|
|
for (Index = 0; Index < RegLogonSession->CredentialCount ; Index++ )
|
|
{
|
|
PasswordSize += RegLogonSession->Credentials[Index].keyvalue.length;
|
|
RegLogonSession->Credentials[Index].keyvalue.value = (unsigned char*)
|
|
((PUCHAR) RegLogonSession +
|
|
(INT)(RegLogonSession->Credentials[Index].keyvalue.value));
|
|
} // for
|
|
|
|
//
|
|
// Alloc & copy over the Credentials block
|
|
//
|
|
|
|
CredentialSize = sizeof(KERB_STORED_CREDENTIAL) -
|
|
(ANYSIZE_ARRAY * sizeof(KERB_KEY_DATA)) +
|
|
EncryptKeySize + PasswordSize;
|
|
|
|
LogonSession->PrimaryCredentials.Passwords = (PKERB_STORED_CREDENTIAL) KerbAllocate(CredentialSize);
|
|
|
|
if (LogonSession->PrimaryCredentials.Passwords == NULL)
|
|
{
|
|
DebugLog((DEB_ERROR, "Error allocing KERBEROS_TICKET_LOGONSESSION_KEY \n"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// copy revision, flags & credentialcount
|
|
//
|
|
|
|
LogonSession->PrimaryCredentials.Passwords->Revision = RegLogonSession->Revision;
|
|
LogonSession->PrimaryCredentials.Passwords->Flags = RegLogonSession->Flags;
|
|
LogonSession->PrimaryCredentials.Passwords->CredentialCount = RegLogonSession->CredentialCount;
|
|
|
|
//
|
|
// copy all keyvalue.value
|
|
//
|
|
|
|
Offset = 0;
|
|
Base = (PUCHAR)LogonSession->PrimaryCredentials.Passwords +
|
|
CredentialSize - PasswordSize;
|
|
|
|
for (Index = 0; Index < RegLogonSession->CredentialCount ; Index++ )
|
|
{
|
|
RtlCopyMemory(Base + Offset,
|
|
RegLogonSession->Credentials[Index].keyvalue.value,
|
|
RegLogonSession->Credentials[Index].keyvalue.length);
|
|
|
|
LogonSession->PrimaryCredentials.Passwords->Credentials[Index].Key.keytype =
|
|
RegLogonSession->Credentials[Index].keytype;
|
|
LogonSession->PrimaryCredentials.Passwords->Credentials[Index].Key.keyvalue.length =
|
|
RegLogonSession->Credentials[Index].keyvalue.length;
|
|
LogonSession->PrimaryCredentials.Passwords->Credentials[Index].Key.keyvalue.value =
|
|
(unsigned char*) (Base + Offset);
|
|
Offset += RegLogonSession->Credentials[Index].keyvalue.length;
|
|
} // for
|
|
|
|
//
|
|
// All logons are deferred until proven otherwise
|
|
//
|
|
|
|
LogonSession->LogonSessionFlags = KERB_LOGON_DEFERRED;
|
|
|
|
if (LogonSession->PrimaryCredentials.Passwords == NULL)
|
|
{
|
|
LogonSession->LogonSessionFlags |= KERB_LOGON_NO_PASSWORD;
|
|
}
|
|
|
|
//
|
|
// Now that the logon session structure is filled out insert it
|
|
// into the list. After this you need to hold the logon session lock
|
|
// to read or write this logon session.
|
|
//
|
|
|
|
Status = KerbInsertLogonSession(LogonSession);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (LogonSession != NULL)
|
|
{
|
|
KerbReferenceLogonSessionByPointer(LogonSession, TRUE);
|
|
KerbFreeLogonSession(LogonSession);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (LogonSession != NULL)
|
|
{
|
|
KerbDereferenceLogonSession(LogonSession);
|
|
}
|
|
}
|
|
|
|
if (RegLogonSession != NULL)
|
|
{
|
|
KerbFree(RegLogonSession);
|
|
}
|
|
// NOTE - what about pUsername & pDomainname
|
|
|
|
DebugLog((DEB_TRACE_API, "Leaving KerbInitSecurityInterface\n"));
|
|
return SEC_SUCCESS(Status) ? &KerbDllSecurityFunctionTable : NULL;
|
|
}
|
|
|
|
|
|
VOID
|
|
KerbShutdownSecurityInterface(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Cleanup the data shared by the DLL and SERVICE.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PKERB_LOGON_SESSION LogonSession;
|
|
LUID LogonId;
|
|
PKERB_LOGON_SESSION_CACHE RegLogonSession;
|
|
|
|
HKEY hRegKey;
|
|
DWORD dwDisposition;
|
|
DWORD dwError = 0;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
DebugLog((DEB_TRACE_API, "Entering KerbShutdownSecurityInterface\n"));
|
|
|
|
Status = NtAllocateLocallyUniqueId (&LogonId);
|
|
|
|
LogonSession = KerbReferenceLogonSession(
|
|
&LogonId,
|
|
TRUE);
|
|
|
|
// Need to dump out logon session info in the registry
|
|
// create or open the parameters key
|
|
if ( ( dwError = RegCreateKeyEx (
|
|
HKEY_LOCAL_MACHINE,
|
|
KERBEROS_TICKET_KEY,
|
|
0,
|
|
"",
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hRegKey,
|
|
&dwDisposition) ) )
|
|
{
|
|
DebugLog((DEB_ERROR, "Error creating KERBEROS_TICKET_KEY\n"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (LogonSession != NULL)
|
|
{
|
|
ULONG PasswordSize, Offset;
|
|
ULONG Index;
|
|
ULONG TotalSize = 0 ;
|
|
PUCHAR Base;
|
|
|
|
//
|
|
// Compute the size of the passwords, which are assumed to be
|
|
// marshalled in order.
|
|
//
|
|
|
|
PasswordSize = sizeof(KERB_LOGON_SESSION_CACHE) - sizeof(KERB_KEY_DATA) * ANYSIZE_ARRAY +
|
|
LogonSession->PrimaryCredentials.Passwords->CredentialCount * sizeof(KERB_KEY_DATA);
|
|
|
|
for (Index = 0; Index < LogonSession->PrimaryCredentials.Passwords->CredentialCount ; Index++ )
|
|
{
|
|
PasswordSize += LogonSession->PrimaryCredentials.Passwords->Credentials[Index].Key.keyvalue.length;
|
|
DsysAssert((PUCHAR) LogonSession->PrimaryCredentials.Passwords->Credentials[Index].Key.keyvalue.value <=
|
|
(PUCHAR) LogonSession->PrimaryCredentials.Passwords + PasswordSize );
|
|
}
|
|
|
|
// Total size of the logon session cache
|
|
TotalSize = LogonSession->PrimaryCredentials.UserName.MaximumLength +
|
|
LogonSession->PrimaryCredentials.DomainName.MaximumLength +
|
|
PasswordSize;
|
|
|
|
RegLogonSession = (PKERB_LOGON_SESSION_CACHE) KerbAllocate(TotalSize);
|
|
|
|
if (RegLogonSession == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Cleanup;
|
|
}
|
|
|
|
RegLogonSession->Lifetime =
|
|
LogonSession->Lifetime;
|
|
RegLogonSession->LogonSessionFlags =
|
|
LogonSession->LogonSessionFlags;
|
|
RegLogonSession->UserName.Length =
|
|
LogonSession->PrimaryCredentials.UserName.Length;
|
|
RegLogonSession->UserName.MaximumLength =
|
|
LogonSession->PrimaryCredentials.UserName.MaximumLength;
|
|
RegLogonSession->DomainName.Length =
|
|
LogonSession->PrimaryCredentials.DomainName.Length;
|
|
RegLogonSession->DomainName.MaximumLength =
|
|
LogonSession->PrimaryCredentials.DomainName.MaximumLength;
|
|
RegLogonSession->Revision =
|
|
LogonSession->PrimaryCredentials.Passwords->Revision;
|
|
RegLogonSession->Flags =
|
|
LogonSession->PrimaryCredentials.Passwords->Flags;
|
|
RegLogonSession->CredentialCount=
|
|
LogonSession->PrimaryCredentials.Passwords->CredentialCount;
|
|
|
|
Base = (PUCHAR) RegLogonSession;
|
|
|
|
Offset = sizeof(KERB_LOGON_SESSION_CACHE) -
|
|
(ANYSIZE_ARRAY * sizeof(KERB_KEY_DATA)) +
|
|
(RegLogonSession->CredentialCount * sizeof(KERB_KEY_DATA));
|
|
// Offset from the struct
|
|
|
|
RegLogonSession->UserName.Buffer = (LPWSTR)Offset;
|
|
|
|
RtlCopyMemory(Base + Offset,
|
|
LogonSession->PrimaryCredentials.UserName.Buffer,
|
|
LogonSession->PrimaryCredentials.UserName.MaximumLength);
|
|
|
|
Offset += LogonSession->PrimaryCredentials.UserName.MaximumLength;
|
|
|
|
RegLogonSession->DomainName.Buffer = (LPWSTR)(Offset);
|
|
|
|
RtlCopyMemory(Base + Offset,
|
|
LogonSession->PrimaryCredentials.DomainName.Buffer,
|
|
LogonSession->PrimaryCredentials.DomainName.MaximumLength);
|
|
Offset += LogonSession->PrimaryCredentials.DomainName.MaximumLength;
|
|
|
|
for (Index = 0; Index < RegLogonSession->CredentialCount ; Index++ )
|
|
{
|
|
RegLogonSession->Credentials[Index].keytype =
|
|
LogonSession->PrimaryCredentials.Passwords->Credentials[Index].Key.keytype;
|
|
|
|
RegLogonSession->Credentials[Index].keyvalue.length =
|
|
LogonSession->PrimaryCredentials.Passwords->Credentials[Index].Key.keyvalue.length;
|
|
|
|
RegLogonSession->Credentials[Index].keyvalue.value =
|
|
(unsigned char *) (Offset);
|
|
|
|
RtlCopyMemory(Base + Offset,
|
|
LogonSession->PrimaryCredentials.Passwords->Credentials[Index].Key.keyvalue.value,
|
|
LogonSession->PrimaryCredentials.Passwords->Credentials[Index].Key.keyvalue.length);
|
|
|
|
Offset += LogonSession->PrimaryCredentials.Passwords->Credentials[Index].Key.keyvalue.length;
|
|
|
|
} // for
|
|
|
|
|
|
// add username from LogonSession->PrimaryCredentials->Username
|
|
if ( ( dwError = RegSetValueEx (
|
|
hRegKey,
|
|
KERBEROS_TICKET_USERNAME_KEY,
|
|
0,
|
|
REG_BINARY,
|
|
(LPBYTE) LogonSession->PrimaryCredentials.UserName.Buffer,
|
|
LogonSession->PrimaryCredentials.UserName.Length
|
|
) ))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error writing to KERBEROS_TICKET_USERNAME_KEY\n"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
// add domainname from LogonSession->PrimaryCredentials->domainname
|
|
if ( ( dwError = RegSetValueEx (
|
|
hRegKey,
|
|
KERBEROS_TICKET_DOMAINNAME_KEY,
|
|
0,
|
|
REG_BINARY,
|
|
(LPBYTE) LogonSession->PrimaryCredentials.DomainName.Buffer,
|
|
LogonSession->PrimaryCredentials.DomainName.Length)))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error writing to KERBEROS_TICKET_DOMAINNAME_KEY\n"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
// add logon session data from RegLogonSession & TotalSize
|
|
if ( ( dwError = RegSetValueEx (
|
|
hRegKey,
|
|
KERBEROS_TICKET_LOGONSESSION_KEY,
|
|
0,
|
|
REG_BINARY,
|
|
(LPBYTE) RegLogonSession,
|
|
TotalSize) ) )
|
|
{
|
|
DebugLog((DEB_ERROR, "Error writing to KERBEROS_TICKET_LOGONSESSION_KEY\n"));
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else // (LogonSession is NULL)
|
|
{
|
|
// We did not have any valid kerberos logon sessions.
|
|
// Delete all the registry values in keys.
|
|
|
|
DebugLog((DEB_TRACE, "No Kerberos LogonSession\n"));
|
|
if ( ( dwError = RegDeleteValue (
|
|
hRegKey,
|
|
KERBEROS_TICKET_USERNAME_KEY)))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error deleting value KERBEROS_TICKET_USERNAME_KEY\n"));
|
|
}
|
|
|
|
if ( ( dwError = RegDeleteValue (
|
|
hRegKey,
|
|
KERBEROS_TICKET_DOMAINNAME_KEY)))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error deleting value KERBEROS_TICKET_DOMAINNAME_KEY\n"));
|
|
}
|
|
|
|
if ( ( dwError = RegDeleteValue (
|
|
hRegKey,
|
|
KERBEROS_TICKET_LOGONSESSION_KEY)))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error deleting value KERBEROS_TICKET_LOGONSESSION_KEY\n"));
|
|
}
|
|
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if ( ( dwError = RegFlushKey ( hRegKey) ))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error Flushing KERBEROS_TICKET_KEY\n"));
|
|
}
|
|
|
|
if ( ( dwError = RegCloseKey ( hRegKey) ))
|
|
{
|
|
DebugLog((DEB_ERROR, "Error closing KERBEROS_TICKET_KEY\n"));
|
|
}
|
|
|
|
if (LogonSession != NULL)
|
|
{
|
|
KerbDereferenceLogonSession(LogonSession);
|
|
LogonSession = NULL;
|
|
}
|
|
|
|
SpShutdown();
|
|
|
|
DebugLog((DEB_TRACE_API, "Leaving KerbShutdownSecurityInterface\n"));
|
|
|
|
}
|
|
|
|
|
|
SECURITY_STATUS
|
|
KerbSpGetInfo(
|
|
IN LPTSTR PackageName,
|
|
OUT PSecPkgInfo *PackageInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This API is intended to provide basic information about Security
|
|
Packages themselves. This information will include the bounds on sizes
|
|
of authentication information, credentials and contexts.
|
|
|
|
?? This is a local routine rather than the real API call since the API
|
|
call has a bad interface that neither allows me to allocate the
|
|
buffer nor tells me how big the buffer is. Perhaps when the real API
|
|
is fixed, I'll make this the real API.
|
|
|
|
Arguments:
|
|
|
|
PackageName - Name of the package being queried.
|
|
|
|
PackageInfo - Returns a pointer to an allocated block describing the
|
|
security package. The allocated block 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
|
|
|
|
--*/
|
|
{
|
|
LPTSTR Where;
|
|
|
|
//
|
|
// Ensure the correct package name was passed in.
|
|
//
|
|
|
|
if ( lstrcmpi( PackageName, KERBEROS_PACKAGE_NAME ) != 0 ) {
|
|
return SEC_E_SECPKG_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Allocate a buffer for the PackageInfo
|
|
//
|
|
|
|
*PackageInfo = (PSecPkgInfo) LocalAlloc( 0, sizeof(SecPkgInfo) +
|
|
sizeof(KERBEROS_PACKAGE_NAME) +
|
|
sizeof(KERBEROS_PACKAGE_COMMENT) );
|
|
|
|
if ( *PackageInfo == NULL ) {
|
|
return SEC_E_INSUFFICIENT_MEMORY;
|
|
}
|
|
|
|
//
|
|
// Fill in the information.
|
|
//
|
|
|
|
(*PackageInfo)->fCapabilities = KerbGlobalCapabilities;
|
|
(*PackageInfo)->wVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION;
|
|
(*PackageInfo)->wRPCID = RPC_C_AUTHN_GSS_KERBEROS;
|
|
(*PackageInfo)->cbMaxToken = KERBEROS_MAX_TOKEN;
|
|
|
|
Where = (LPTSTR)((*PackageInfo)+1);
|
|
|
|
(*PackageInfo)->Name = Where;
|
|
lstrcpy( Where, KERBEROS_PACKAGE_NAME);
|
|
Where += lstrlen(Where) + 1;
|
|
|
|
(*PackageInfo)->Comment = Where;
|
|
lstrcpy( Where, KERBEROS_PACKAGE_COMMENT);
|
|
Where += lstrlen(Where) + 1;
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
|
|
SECURITY_STATUS
|
|
KerbEnumerateSecurityPackages(
|
|
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;
|
|
|
|
*PackageCount = 1;
|
|
//
|
|
// Allocate a buffer for the PackageInfo
|
|
//
|
|
|
|
*PackageInfo = (PSecPkgInfo) LocalAlloc( 0, sizeof(SecPkgInfo) +
|
|
sizeof(KERBEROS_PACKAGE_NAME) +
|
|
sizeof(KERBEROS_PACKAGE_COMMENT) );
|
|
|
|
if ( *PackageInfo == NULL ) {
|
|
return SEC_E_INSUFFICIENT_MEMORY;
|
|
}
|
|
|
|
//
|
|
// Fill in the information.
|
|
//
|
|
|
|
(*PackageInfo)->fCapabilities = KerbGlobalCapabilities;
|
|
(*PackageInfo)->wVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION;
|
|
(*PackageInfo)->wRPCID = RPC_C_AUTHN_GSS_KERBEROS;
|
|
(*PackageInfo)->cbMaxToken = KERBEROS_MAX_TOKEN;
|
|
|
|
Where = (LPTSTR)((*PackageInfo)+1);
|
|
|
|
(*PackageInfo)->Name = Where;
|
|
lstrcpy( Where, KERBEROS_PACKAGE_NAME);
|
|
Where += lstrlen(Where) + 1;
|
|
|
|
(*PackageInfo)->Comment = Where;
|
|
lstrcpy( Where, KERBEROS_PACKAGE_COMMENT);
|
|
Where += lstrlen(Where) + 1;
|
|
|
|
|
|
return SEC_E_OK;
|
|
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
KerbQuerySecurityPackageInfo (
|
|
LPTSTR PackageName,
|
|
PSecPkgInfo SEC_FAR * Package
|
|
)
|
|
{
|
|
|
|
return ( KerbSpGetInfo(
|
|
PackageName,
|
|
Package));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECURITY_STATUS SEC_ENTRY
|
|
KerbFreeContextBuffer (
|
|
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.
|
|
//
|
|
|
|
(VOID) LocalFree( ContextBuffer );
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
#if DBG
|
|
//
|
|
// Control which messages get displayed
|
|
//
|
|
|
|
// DWORD KerbInfoLevel = DEB_ERROR | DEB_WARN | DEB_TRACE | DEB_TRACE_API;
|
|
|
|
//
|
|
// SspPrintRoutine - Displays debug output
|
|
//
|
|
VOID __cdecl
|
|
KerbPrintRoutine(
|
|
IN DWORD DebugFlag,
|
|
IN LPCSTR FormatString, // PRINTF()-STYLE FORMAT STRING.
|
|
... // OTHER ARGUMENTS ARE POSSIBLE.
|
|
)
|
|
{
|
|
static char prefix[] = "KERB: ";
|
|
char outbuf[256];
|
|
va_list args;
|
|
|
|
if ( DebugFlag & KerbInfoLevel) {
|
|
EnterCriticalSection( &KerbGlobalLogFileCritSect );
|
|
lstrcpy(outbuf, prefix);
|
|
va_start(args, FormatString);
|
|
wvsprintf(outbuf + sizeof(prefix) - 1, FormatString, args);
|
|
OutputDebugString(outbuf);
|
|
LeaveCriticalSection( &KerbGlobalLogFileCritSect );
|
|
}
|
|
|
|
return;
|
|
}
|
|
#endif DBG
|
|
|
|
SECURITY_STATUS
|
|
KerbAcquireCredentialsHandle(
|
|
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;
|
|
|
|
//
|
|
// Validate the arguments
|
|
//
|
|
|
|
if ( lstrcmpi( PackageName, KERBEROS_PACKAGE_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;
|
|
}
|
|
|
|
//
|
|
// Don't allow inbound credentials if we don't have an authentication
|
|
// server avaiable
|
|
//
|
|
|
|
if ( (KerbGlobalCapabilities & SECPKG_FLAG_CLIENT_ONLY)
|
|
&& (CredentialUseFlags & SECPKG_CRED_INBOUND) ) {
|
|
DebugLog(( SSP_API,
|
|
"KerbAcquireCredentialHandle: no authentication service for inbound handle.\n" ));
|
|
SecStatus = SEC_E_NO_AUTHENTICATING_AUTHORITY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!RtlCreateUnicodeStringFromAsciiz( &NewPrincipalName, PrincipalName)){
|
|
SecStatus = SEC_E_INSUFFICIENT_MEMORY;;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
SecStatus = SpAcquireCredentialsHandle(
|
|
&NewPrincipalName,
|
|
CredentialUseFlags,
|
|
(PLUID)LogonId,
|
|
AuthData,
|
|
GetKeyFunction,
|
|
GetKeyArgument,
|
|
&CredentialHandle->dwUpper,
|
|
Lifetime );
|
|
|
|
Cleanup:
|
|
|
|
return SecStatus;
|
|
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
KerbFreeCredentialsHandle(
|
|
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;
|
|
|
|
|
|
|
|
|
|
SecStatus = SpFreeCredentialsHandle(
|
|
CredentialHandle->dwUpper );
|
|
|
|
|
|
|
|
return SecStatus;
|
|
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
KerbQueryCredentialsAttributes(
|
|
IN PCredHandle CredentialsHandle,
|
|
IN ULONG Attribute,
|
|
OUT PVOID Buffer
|
|
)
|
|
{
|
|
SECURITY_STATUS SecStatus;
|
|
|
|
|
|
SecStatus = SpQueryCredentialsAttributes(
|
|
CredentialsHandle->dwUpper,
|
|
Attribute,
|
|
Buffer );
|
|
|
|
return SecStatus;
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
KerbInitializeSecurityContext(
|
|
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};
|
|
|
|
RtlCreateUnicodeStringFromAsciiz (&TargetNameUStr, TargetName);
|
|
|
|
if (!ARGUMENT_PRESENT(InputToken))
|
|
{
|
|
InputToken = &EmptyBuffer;
|
|
}
|
|
|
|
if (!ARGUMENT_PRESENT(OutputToken))
|
|
{
|
|
OutputToken = &EmptyBuffer;
|
|
}
|
|
|
|
SecStatus = SpInitLsaModeContext (
|
|
CredentialHandle ? CredentialHandle->dwUpper : NULL,
|
|
OldContextHandle ? OldContextHandle->dwUpper : NULL,
|
|
&TargetNameUStr,
|
|
ContextReqFlags,
|
|
TargetDataRep,
|
|
InputToken,
|
|
&NewContextHandle->dwUpper,
|
|
OutputToken,
|
|
ContextAttributes,
|
|
ExpirationTime,
|
|
&fMappedContext,
|
|
&ContextData);
|
|
|
|
if (NT_SUCCESS(SecStatus) && fMappedContext)
|
|
{
|
|
SecondaryStatus = SpInitUserModeContext(NewContextHandle->dwUpper,
|
|
&ContextData);
|
|
|
|
if (!NT_SUCCESS(SecondaryStatus))
|
|
{
|
|
SecStatus = SecondaryStatus;
|
|
|
|
SecondaryStatus = KerbDeleteSecurityContext(NewContextHandle);
|
|
}
|
|
}
|
|
|
|
return SecStatus;
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
KerbDeleteSecurityContext (
|
|
IN PCtxtHandle ContextHandle
|
|
)
|
|
{
|
|
SECURITY_STATUS SecStatus = SEC_E_OK;
|
|
|
|
SecStatus = SpDeleteContext (ContextHandle->dwUpper);
|
|
|
|
return SecStatus;
|
|
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
KerbApplyControlToken (
|
|
PCtxtHandle ContextHandle,
|
|
PSecBufferDesc Input
|
|
)
|
|
{
|
|
SECURITY_STATUS SecStatus = SEC_E_OK;
|
|
|
|
SecStatus = SpApplyControlToken(ContextHandle->dwUpper, Input);
|
|
|
|
return SecStatus;
|
|
}
|
|
|
|
|
|
SECURITY_STATUS
|
|
KerbImpersonateSecurityContext (
|
|
PCtxtHandle ContextHandle
|
|
)
|
|
{
|
|
return (SEC_E_NO_IMPERSONATION);
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
KerbRevertSecurityContext (
|
|
PCtxtHandle ContextHandle
|
|
)
|
|
{
|
|
return (SEC_E_NO_IMPERSONATION);
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
KerbQueryContextAttributes(
|
|
IN PCtxtHandle ContextHandle,
|
|
IN ULONG Attribute,
|
|
OUT PVOID Buffer
|
|
)
|
|
{
|
|
SECURITY_STATUS SecStatus = SEC_E_OK;
|
|
|
|
SecStatus = SpQueryContextAttributes(ContextHandle->dwUpper,
|
|
Attribute,
|
|
Buffer);
|
|
|
|
return SecStatus;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY
|
|
KerbCompleteAuthToken (
|
|
PCtxtHandle ContextHandle,
|
|
PSecBufferDesc BufferDescriptor
|
|
)
|
|
{
|
|
SECURITY_STATUS SecStatus = SEC_E_OK;
|
|
|
|
SecStatus = SpCompleteAuthToken(ContextHandle->dwUpper, BufferDescriptor);
|
|
|
|
return SecStatus;
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
KerbMakeSignature (
|
|
PCtxtHandle ContextHandle,
|
|
unsigned long QualityOfProtection,
|
|
PSecBufferDesc Message,
|
|
unsigned long SequenceNumber
|
|
)
|
|
{
|
|
SECURITY_STATUS SecStatus = SEC_E_OK;
|
|
|
|
SecStatus = SpMakeSignature(ContextHandle->dwUpper,
|
|
QualityOfProtection,
|
|
Message,
|
|
SequenceNumber);
|
|
|
|
return SecStatus;
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
KerbVerifySignature (
|
|
PCtxtHandle ContextHandle,
|
|
PSecBufferDesc Message,
|
|
unsigned long SequenceNumber,
|
|
unsigned long * QualityOfProtection
|
|
)
|
|
{
|
|
SECURITY_STATUS SecStatus = SEC_E_OK;
|
|
|
|
SecStatus = SpVerifySignature(ContextHandle->dwUpper,
|
|
Message,
|
|
SequenceNumber,
|
|
QualityOfProtection);
|
|
|
|
return SecStatus;
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
KerbSealMessage (
|
|
PCtxtHandle ContextHandle,
|
|
unsigned long QualityOfProtection,
|
|
PSecBufferDesc Message,
|
|
unsigned long SequenceNumber
|
|
)
|
|
{
|
|
SECURITY_STATUS SecStatus = SEC_E_OK;
|
|
|
|
SecStatus = SpSealMessage(ContextHandle->dwUpper,
|
|
QualityOfProtection,
|
|
Message,
|
|
SequenceNumber);
|
|
|
|
return SecStatus;
|
|
}
|
|
|
|
SECURITY_STATUS
|
|
KerbUnsealMessage (
|
|
PCtxtHandle ContextHandle,
|
|
PSecBufferDesc Message,
|
|
unsigned long SequenceNumber,
|
|
unsigned long * QualityOfProtection
|
|
)
|
|
{
|
|
SECURITY_STATUS SecStatus = SEC_E_OK;
|
|
|
|
SecStatus = SpUnsealMessage(ContextHandle->dwUpper,
|
|
Message,
|
|
SequenceNumber,
|
|
QualityOfProtection);
|
|
|
|
return SecStatus;
|
|
}
|