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.
1752 lines
43 KiB
1752 lines
43 KiB
/*--
|
|
|
|
Copyright (c) 1987-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ssptest.c
|
|
|
|
Abstract:
|
|
|
|
Test program for the NtLmSsp service.
|
|
|
|
Author:
|
|
|
|
28-Jun-1993 (cliffv)
|
|
|
|
Environment:
|
|
|
|
User mode only.
|
|
Contains NT-specific code.
|
|
Requires ANSI C extensions: slash-slash comments, long external names.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
//
|
|
// Common include files.
|
|
//
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windef.h>
|
|
#include <winbase.h>
|
|
#include <winsvc.h> // Needed for service controller APIs
|
|
#include <lmcons.h>
|
|
#include <lmerr.h>
|
|
#include <lmaccess.h>
|
|
#include <lmsname.h>
|
|
#include <rpc.h>
|
|
#include <stdio.h> // printf
|
|
#include <stdlib.h> // strtoul
|
|
#include <netlib.h> // NetpGetLocalDomainId
|
|
|
|
|
|
#define SECURITY_KERBEROS
|
|
#include <security.h> // General definition of a Security Support Provider
|
|
|
|
BOOLEAN QuietMode = FALSE; // Don't be verbose
|
|
ULONG RecursionDepth = 0;
|
|
CredHandle ServerCredHandleStorage;
|
|
PCredHandle ServerCredHandle = NULL;
|
|
#define MAX_RECURSION_DEPTH 2
|
|
|
|
|
|
VOID
|
|
DumpBuffer(
|
|
PVOID Buffer,
|
|
DWORD BufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps the buffer content on to the debugger output.
|
|
|
|
Arguments:
|
|
|
|
Buffer: buffer pointer.
|
|
|
|
BufferSize: size of the buffer.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
#define NUM_CHARS 16
|
|
|
|
DWORD i, limit;
|
|
CHAR TextBuffer[NUM_CHARS + 1];
|
|
LPBYTE BufferPtr = Buffer;
|
|
|
|
|
|
printf("------------------------------------\n");
|
|
|
|
//
|
|
// Hex dump of the bytes
|
|
//
|
|
limit = ((BufferSize - 1) / NUM_CHARS + 1) * NUM_CHARS;
|
|
|
|
for (i = 0; i < limit; i++) {
|
|
|
|
if (i < BufferSize) {
|
|
|
|
printf("%02x ", BufferPtr[i]);
|
|
|
|
if (BufferPtr[i] < 31 ) {
|
|
TextBuffer[i % NUM_CHARS] = '.';
|
|
} else if (BufferPtr[i] == '\0') {
|
|
TextBuffer[i % NUM_CHARS] = ' ';
|
|
} else {
|
|
TextBuffer[i % NUM_CHARS] = (CHAR) BufferPtr[i];
|
|
}
|
|
|
|
} else {
|
|
|
|
printf(" ");
|
|
TextBuffer[i % NUM_CHARS] = ' ';
|
|
|
|
}
|
|
|
|
if ((i + 1) % NUM_CHARS == 0) {
|
|
TextBuffer[NUM_CHARS] = 0;
|
|
printf(" %s\n", TextBuffer);
|
|
}
|
|
|
|
}
|
|
|
|
printf("------------------------------------\n");
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintTime(
|
|
LPSTR Comment,
|
|
TimeStamp ConvertTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print the specified time
|
|
|
|
Arguments:
|
|
|
|
Comment - Comment to print in front of the time
|
|
|
|
Time - Local time to print
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
LARGE_INTEGER LocalTime;
|
|
|
|
LocalTime.HighPart = ConvertTime.HighPart;
|
|
LocalTime.LowPart = ConvertTime.LowPart;
|
|
|
|
printf( "%s", Comment );
|
|
|
|
//
|
|
// If the time is infinite,
|
|
// just say so.
|
|
//
|
|
|
|
if ( LocalTime.HighPart == 0x7FFFFFFF && LocalTime.LowPart == 0xFFFFFFFF ) {
|
|
printf( "Infinite\n" );
|
|
|
|
//
|
|
// Otherwise print it more clearly
|
|
//
|
|
|
|
} else {
|
|
|
|
TIME_FIELDS TimeFields;
|
|
|
|
RtlTimeToTimeFields( &LocalTime, &TimeFields );
|
|
|
|
printf( "%ld/%ld/%ld %ld:%2.2ld:%2.2ld\n",
|
|
TimeFields.Month,
|
|
TimeFields.Day,
|
|
TimeFields.Year,
|
|
TimeFields.Hour,
|
|
TimeFields.Minute,
|
|
TimeFields.Second );
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
PrintStatus(
|
|
NET_API_STATUS NetStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print a net status code.
|
|
|
|
Arguments:
|
|
|
|
NetStatus - The net status code to print.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
printf( "Status = %lu 0x%lx", NetStatus, NetStatus );
|
|
|
|
switch (NetStatus) {
|
|
case NERR_Success:
|
|
printf( " NERR_Success" );
|
|
break;
|
|
|
|
case NERR_DCNotFound:
|
|
printf( " NERR_DCNotFound" );
|
|
break;
|
|
|
|
case ERROR_LOGON_FAILURE:
|
|
printf( " ERROR_LOGON_FAILURE" );
|
|
break;
|
|
|
|
case ERROR_ACCESS_DENIED:
|
|
printf( " ERROR_ACCESS_DENIED" );
|
|
break;
|
|
|
|
case ERROR_NOT_SUPPORTED:
|
|
printf( " ERROR_NOT_SUPPORTED" );
|
|
break;
|
|
|
|
case ERROR_NO_LOGON_SERVERS:
|
|
printf( " ERROR_NO_LOGON_SERVERS" );
|
|
break;
|
|
|
|
case ERROR_NO_SUCH_DOMAIN:
|
|
printf( " ERROR_NO_SUCH_DOMAIN" );
|
|
break;
|
|
|
|
case ERROR_NO_TRUST_LSA_SECRET:
|
|
printf( " ERROR_NO_TRUST_LSA_SECRET" );
|
|
break;
|
|
|
|
case ERROR_NO_TRUST_SAM_ACCOUNT:
|
|
printf( " ERROR_NO_TRUST_SAM_ACCOUNT" );
|
|
break;
|
|
|
|
case ERROR_DOMAIN_TRUST_INCONSISTENT:
|
|
printf( " ERROR_DOMAIN_TRUST_INCONSISTENT" );
|
|
break;
|
|
|
|
case ERROR_BAD_NETPATH:
|
|
printf( " ERROR_BAD_NETPATH" );
|
|
break;
|
|
|
|
case ERROR_FILE_NOT_FOUND:
|
|
printf( " ERROR_FILE_NOT_FOUND" );
|
|
break;
|
|
|
|
case NERR_NetNotStarted:
|
|
printf( " NERR_NetNotStarted" );
|
|
break;
|
|
|
|
case NERR_WkstaNotStarted:
|
|
printf( " NERR_WkstaNotStarted" );
|
|
break;
|
|
|
|
case NERR_ServerNotStarted:
|
|
printf( " NERR_ServerNotStarted" );
|
|
break;
|
|
|
|
case NERR_BrowserNotStarted:
|
|
printf( " NERR_BrowserNotStarted" );
|
|
break;
|
|
|
|
case NERR_ServiceNotInstalled:
|
|
printf( " NERR_ServiceNotInstalled" );
|
|
break;
|
|
|
|
case NERR_BadTransactConfig:
|
|
printf( " NERR_BadTransactConfig" );
|
|
break;
|
|
|
|
case SEC_E_NO_SPM:
|
|
printf( " SEC_E_NO_SPM" );
|
|
break;
|
|
case SEC_E_BAD_PKGID:
|
|
printf( " SEC_E_BAD_PKGID" ); break;
|
|
case SEC_E_NOT_OWNER:
|
|
printf( " SEC_E_NOT_OWNER" ); break;
|
|
case SEC_E_CANNOT_INSTALL:
|
|
printf( " SEC_E_CANNOT_INSTALL" ); break;
|
|
case SEC_E_INVALID_TOKEN:
|
|
printf( " SEC_E_INVALID_TOKEN" ); break;
|
|
case SEC_E_CANNOT_PACK:
|
|
printf( " SEC_E_CANNOT_PACK" ); break;
|
|
case SEC_E_QOP_NOT_SUPPORTED:
|
|
printf( " SEC_E_QOP_NOT_SUPPORTED" ); break;
|
|
case SEC_E_NO_IMPERSONATION:
|
|
printf( " SEC_E_NO_IMPERSONATION" ); break;
|
|
case SEC_E_LOGON_DENIED:
|
|
printf( " SEC_E_LOGON_DENIED" ); break;
|
|
case SEC_E_UNKNOWN_CREDENTIALS:
|
|
printf( " SEC_E_UNKNOWN_CREDENTIALS" ); break;
|
|
case SEC_E_NO_CREDENTIALS:
|
|
printf( " SEC_E_NO_CREDENTIALS" ); break;
|
|
case SEC_E_MESSAGE_ALTERED:
|
|
printf( " SEC_E_MESSAGE_ALTERED" ); break;
|
|
case SEC_E_OUT_OF_SEQUENCE:
|
|
printf( " SEC_E_OUT_OF_SEQUENCE" ); break;
|
|
case SEC_E_INSUFFICIENT_MEMORY:
|
|
printf( " SEC_E_INSUFFICIENT_MEMORY" ); break;
|
|
case SEC_E_INVALID_HANDLE:
|
|
printf( " SEC_E_INVALID_HANDLE" ); break;
|
|
case SEC_E_NOT_SUPPORTED:
|
|
printf( " SEC_E_NOT_SUPPORTED" ); break;
|
|
|
|
|
|
}
|
|
|
|
printf( "\n" );
|
|
}
|
|
|
|
VOID
|
|
ConfigureServiceRoutine(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Configure the NtLmSsp Service
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
SC_HANDLE ScManagerHandle = NULL;
|
|
SC_HANDLE ServiceHandle = NULL;
|
|
WCHAR ServiceName[MAX_PATH];
|
|
DWORD WinStatus,NetStatus;
|
|
HKEY LsaKey = NULL;
|
|
USER_INFO_1 UserInfo;
|
|
PSID PrimaryDomain = NULL;
|
|
PSID AccountDomain = NULL;
|
|
|
|
if (NetpGetLocalDomainId(LOCAL_DOMAIN_TYPE_ACCOUNTS, &AccountDomain) != NERR_Success)
|
|
{
|
|
printf("Failed to get account domain ID\n");
|
|
return;
|
|
}
|
|
|
|
if (NetpGetLocalDomainId(LOCAL_DOMAIN_TYPE_PRIMARY, &PrimaryDomain) != NERR_Success)
|
|
{
|
|
printf("Failed to get primary domain ID\n");
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// First set REDMOND as the preferred domain
|
|
//
|
|
|
|
WinStatus = RegOpenKey(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"System\\currentcontrolset\\control\\lsa\\MSV1_0",
|
|
&LsaKey
|
|
);
|
|
if (WinStatus != 0)
|
|
{
|
|
printf("RegOpenKeyW failed:" );
|
|
PrintStatus(WinStatus);
|
|
goto Cleanup;
|
|
}
|
|
|
|
WinStatus = RegSetValueEx(
|
|
LsaKey,
|
|
L"PreferredDomain",
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE) L"REDMOND",
|
|
sizeof(L"REDMOND")
|
|
);
|
|
RegCloseKey(LsaKey);
|
|
if (WinStatus != 0)
|
|
{
|
|
printf("RegOpenKeyW failed:");
|
|
PrintStatus(WinStatus);
|
|
goto Cleanup;
|
|
}
|
|
//
|
|
// Then add Kerberos as a security package
|
|
//
|
|
|
|
|
|
WinStatus = RegOpenKey(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"System\\currentcontrolset\\control\\lsa",
|
|
&LsaKey
|
|
);
|
|
if (WinStatus != 0)
|
|
{
|
|
printf("RegOpenKeyW failed:" );
|
|
PrintStatus(WinStatus);
|
|
goto Cleanup;
|
|
}
|
|
|
|
WinStatus = RegSetValueEx(
|
|
LsaKey,
|
|
L"Security Packages",
|
|
0,
|
|
REG_MULTI_SZ,
|
|
(PBYTE) L"Kerberos\0",
|
|
sizeof(L"Kerberos\0")
|
|
);
|
|
RegCloseKey(LsaKey);
|
|
if (WinStatus != 0)
|
|
{
|
|
printf("RegOpenKeyW failed:");
|
|
PrintStatus(WinStatus);
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// First add Kerberos as a security package for RPC
|
|
//
|
|
|
|
WinStatus = RegOpenKey(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"Software\\Microsoft\\Rpc\\SecurityService",
|
|
&LsaKey
|
|
);
|
|
if (WinStatus != 0)
|
|
{
|
|
printf("RegOpenKeyW failed:" );
|
|
PrintStatus(WinStatus);
|
|
goto Cleanup;
|
|
}
|
|
|
|
WinStatus = RegSetValueEx(
|
|
LsaKey,
|
|
L"1",
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE) L"secur32.dll",
|
|
sizeof(L"secur32.dll")
|
|
);
|
|
RegCloseKey(LsaKey);
|
|
if (WinStatus != 0)
|
|
{
|
|
printf("RegOpenKeyW failed:");
|
|
PrintStatus(WinStatus);
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// If we are on a DC (and the primary domain sid == account domain sid)
|
|
// setup the KDC service
|
|
//
|
|
|
|
if ((PrimaryDomain) != NULL && RtlEqualSid(PrimaryDomain, AccountDomain))
|
|
{
|
|
//
|
|
// Build the name of the Kerberos service.
|
|
//
|
|
|
|
if ( !GetWindowsDirectoryW(
|
|
ServiceName,
|
|
sizeof(ServiceName)/sizeof(WCHAR) ) ) {
|
|
printf( "GetWindowsDirectoryW failed:" );
|
|
PrintStatus( GetLastError() );
|
|
goto Cleanup;
|
|
}
|
|
|
|
wcscat( ServiceName, L"\\system32\\lsass.exe" );
|
|
|
|
|
|
//
|
|
// Open a handle to the Service Controller
|
|
//
|
|
|
|
ScManagerHandle = OpenSCManager(
|
|
NULL,
|
|
NULL,
|
|
SC_MANAGER_CREATE_SERVICE );
|
|
|
|
if (ScManagerHandle == NULL) {
|
|
printf( "OpenSCManager failed:" );
|
|
PrintStatus( GetLastError() );
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// If the service already exists,
|
|
// delete it and start afresh.
|
|
//
|
|
|
|
ServiceHandle = OpenService(
|
|
ScManagerHandle,
|
|
L"KDC",
|
|
DELETE );
|
|
|
|
if ( ServiceHandle == NULL ) {
|
|
WinStatus = GetLastError();
|
|
if ( WinStatus != ERROR_SERVICE_DOES_NOT_EXIST ) {
|
|
printf( "OpenService failed:" );
|
|
PrintStatus( WinStatus );
|
|
goto Cleanup;
|
|
}
|
|
} else {
|
|
|
|
if ( !DeleteService( ServiceHandle ) ) {
|
|
printf( "DeleteService failed:" );
|
|
PrintStatus( GetLastError() );
|
|
goto Cleanup;
|
|
}
|
|
|
|
(VOID) CloseServiceHandle(ServiceHandle);
|
|
}
|
|
|
|
//
|
|
// Create the service
|
|
//
|
|
|
|
ServiceHandle = CreateService(
|
|
ScManagerHandle,
|
|
L"KDC",
|
|
L"Key Distribution Center",
|
|
SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG,
|
|
SERVICE_WIN32_SHARE_PROCESS,
|
|
SERVICE_AUTO_START,
|
|
SERVICE_ERROR_NORMAL,
|
|
ServiceName,
|
|
NULL, // No load order group
|
|
NULL, // No Tag Id required
|
|
L"Netlogon\0rpcss\0afd\0",
|
|
NULL, // Run as LocalSystem
|
|
NULL ); // No password
|
|
|
|
|
|
|
|
if ( ServiceHandle == NULL ) {
|
|
printf( "CreateService failed:" );
|
|
PrintStatus( GetLastError() );
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Create the KDC user account
|
|
//
|
|
|
|
UserInfo.usri1_name = L"KDC";
|
|
UserInfo.usri1_password = L"KDC";
|
|
UserInfo.usri1_password_age = 0;
|
|
UserInfo.usri1_priv = USER_PRIV_USER;
|
|
UserInfo.usri1_home_dir = NULL;
|
|
UserInfo.usri1_comment = L"Key Distribution Center Service Account";
|
|
UserInfo.usri1_script_path = NULL;
|
|
UserInfo.usri1_flags = UF_SCRIPT;
|
|
|
|
NetStatus = NetUserAdd(
|
|
NULL,
|
|
1,
|
|
&UserInfo,
|
|
NULL
|
|
);
|
|
if ((NetStatus != NERR_Success) && (NetStatus != NERR_UserExists))
|
|
{
|
|
printf("Failed to create KDC account: %d\n",NetStatus);
|
|
}
|
|
|
|
}
|
|
|
|
Cleanup:
|
|
if (PrimaryDomain != NULL)
|
|
{
|
|
LocalFree(PrimaryDomain);
|
|
}
|
|
if (AccountDomain != NULL)
|
|
{
|
|
LocalFree(AccountDomain);
|
|
}
|
|
|
|
if ( ScManagerHandle != NULL ) {
|
|
(VOID) CloseServiceHandle(ScManagerHandle);
|
|
}
|
|
if ( ServiceHandle != NULL ) {
|
|
(VOID) CloseServiceHandle(ServiceHandle);
|
|
}
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
TestSspRoutine(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Test base SSP functionality
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
SECURITY_STATUS SecStatus;
|
|
SECURITY_STATUS AcceptStatus;
|
|
SECURITY_STATUS InitStatus;
|
|
CredHandle CredentialHandle2;
|
|
CtxtHandle ClientContextHandle;
|
|
CtxtHandle ServerContextHandle;
|
|
TimeStamp Lifetime;
|
|
ULONG ContextAttributes;
|
|
ULONG PackageCount, Index;
|
|
PSecPkgInfo PackageInfo = NULL;
|
|
HANDLE Token = NULL;
|
|
static int Calls;
|
|
ULONG ClientFlags;
|
|
ULONG ServerFlags;
|
|
BOOLEAN AcquiredServerCred = FALSE;
|
|
LPWSTR DomainName = NULL;
|
|
LPWSTR UserName = NULL;
|
|
WCHAR TargetName[100];
|
|
|
|
|
|
|
|
SecBufferDesc NegotiateDesc;
|
|
SecBuffer NegotiateBuffer;
|
|
|
|
SecBufferDesc ChallengeDesc;
|
|
SecBuffer ChallengeBuffer;
|
|
|
|
SecBufferDesc AuthenticateDesc;
|
|
SecBuffer AuthenticateBuffer;
|
|
|
|
SecPkgContext_Sizes ContextSizes;
|
|
SecPkgContext_Lifespan ContextLifespan;
|
|
UCHAR ContextNamesBuffer[sizeof(SecPkgContext_Names)+UNLEN*sizeof(WCHAR)];
|
|
PSecPkgContext_Names ContextNames = (PSecPkgContext_Names) ContextNamesBuffer;
|
|
|
|
SecBufferDesc SignMessage;
|
|
SecBuffer SigBuffers[2];
|
|
BYTE bDataBuffer[20];
|
|
BYTE bSigBuffer[100];
|
|
|
|
NegotiateBuffer.pvBuffer = NULL;
|
|
ChallengeBuffer.pvBuffer = NULL;
|
|
AuthenticateBuffer.pvBuffer = NULL;
|
|
|
|
SigBuffers[1].pvBuffer = bSigBuffer;
|
|
SigBuffers[1].cbBuffer = sizeof(bSigBuffer);
|
|
SigBuffers[1].BufferType = SECBUFFER_TOKEN;
|
|
|
|
SigBuffers[0].pvBuffer = bDataBuffer;
|
|
SigBuffers[0].cbBuffer = sizeof(bDataBuffer);
|
|
SigBuffers[0].BufferType = SECBUFFER_DATA;
|
|
memset(bDataBuffer,0xeb,sizeof(bDataBuffer));
|
|
|
|
SignMessage.pBuffers = SigBuffers;
|
|
SignMessage.cBuffers = 2;
|
|
SignMessage.ulVersion = 0;
|
|
|
|
DomainName = _wgetenv(L"USERDOMAIN");
|
|
UserName = _wgetenv(L"USERNAME");
|
|
|
|
|
|
printf("Recursion depth = %d\n",RecursionDepth);
|
|
//
|
|
// Get info about the security packages.
|
|
//
|
|
|
|
SecStatus = EnumerateSecurityPackages( &PackageCount, &PackageInfo );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "EnumerateSecurityPackages failed:" );
|
|
PrintStatus( SecStatus );
|
|
return;
|
|
}
|
|
|
|
if ( !QuietMode ) {
|
|
printf( "PackageCount: %ld\n", PackageCount );
|
|
for (Index = 0; Index < PackageCount ; Index++ )
|
|
{
|
|
printf( "Package %d:\n",Index);
|
|
printf( "Name: %ws Comment: %ws\n", PackageInfo[Index].Name, PackageInfo[Index].Comment );
|
|
printf( "Cap: %ld Version: %ld RPCid: %ld MaxToken: %ld\n\n",
|
|
PackageInfo[Index].fCapabilities,
|
|
PackageInfo[Index].wVersion,
|
|
PackageInfo[Index].wRPCID,
|
|
PackageInfo[Index].cbMaxToken );
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Get info about the security packages.
|
|
//
|
|
|
|
SecStatus = QuerySecurityPackageInfo( L"kerberos", &PackageInfo );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "QuerySecurityPackageInfo failed:" );
|
|
PrintStatus( SecStatus );
|
|
return;
|
|
}
|
|
|
|
if ( !QuietMode ) {
|
|
printf( "Name: %ws Comment: %ws\n", PackageInfo->Name, PackageInfo->Comment );
|
|
printf( "Cap: %ld Version: %ld RPCid: %ld MaxToken: %ld\n\n",
|
|
PackageInfo->fCapabilities,
|
|
PackageInfo->wVersion,
|
|
PackageInfo->wRPCID,
|
|
PackageInfo->cbMaxToken );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Acquire a credential handle for the server side
|
|
//
|
|
if (ServerCredHandle == NULL)
|
|
{
|
|
|
|
ServerCredHandle = &ServerCredHandleStorage;
|
|
AcquiredServerCred = TRUE;
|
|
|
|
SecStatus = AcquireCredentialsHandle(
|
|
NULL, // New principal
|
|
L"kerberos", // Package Name
|
|
SECPKG_CRED_INBOUND,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
ServerCredHandle,
|
|
&Lifetime );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "AcquireCredentialsHandle failed: ");
|
|
PrintStatus( SecStatus );
|
|
return;
|
|
}
|
|
|
|
if ( !QuietMode ) {
|
|
printf( "ServerCredHandle: 0x%lx 0x%lx ",
|
|
ServerCredHandle->dwLower, ServerCredHandle->dwUpper );
|
|
PrintTime( "Lifetime: ", Lifetime );
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Acquire a credential handle for the client side
|
|
//
|
|
|
|
|
|
|
|
SecStatus = AcquireCredentialsHandle(
|
|
NULL, // New principal
|
|
L"kerberos", // Package Name
|
|
SECPKG_CRED_OUTBOUND,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&CredentialHandle2,
|
|
&Lifetime );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "AcquireCredentialsHandle failed: " );
|
|
PrintStatus( SecStatus );
|
|
return;
|
|
}
|
|
|
|
|
|
if ( !QuietMode ) {
|
|
printf( "CredentialHandle2: 0x%lx 0x%lx ",
|
|
CredentialHandle2.dwLower, CredentialHandle2.dwUpper );
|
|
PrintTime( "Lifetime: ", Lifetime );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Get the NegotiateMessage (ClientSide)
|
|
//
|
|
|
|
NegotiateDesc.ulVersion = 0;
|
|
NegotiateDesc.cBuffers = 1;
|
|
NegotiateDesc.pBuffers = &NegotiateBuffer;
|
|
|
|
NegotiateBuffer.cbBuffer = PackageInfo->cbMaxToken;
|
|
NegotiateBuffer.BufferType = SECBUFFER_TOKEN;
|
|
NegotiateBuffer.pvBuffer = LocalAlloc( 0, NegotiateBuffer.cbBuffer );
|
|
if ( NegotiateBuffer.pvBuffer == NULL ) {
|
|
printf( "Allocate NegotiateMessage failed: 0x%ld\n", GetLastError() );
|
|
return;
|
|
}
|
|
|
|
ClientFlags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_MUTUAL_AUTH | ISC_REQ_USE_DCE_STYLE | ISC_REQ_DATAGRAM; // | ISC_REQ_DELEGATE;
|
|
|
|
if (Calls == 0)
|
|
{
|
|
ClientFlags |= ISC_REQ_IDENTIFY;
|
|
}
|
|
Calls++;
|
|
|
|
wcscpy(
|
|
TargetName,
|
|
DomainName
|
|
);
|
|
wcscat(
|
|
TargetName,
|
|
L"\\"
|
|
);
|
|
wcscat(
|
|
TargetName,
|
|
UserName
|
|
);
|
|
|
|
InitStatus = InitializeSecurityContext(
|
|
&CredentialHandle2,
|
|
NULL, // No Client context yet
|
|
TargetName, // Faked target name
|
|
ClientFlags,
|
|
0, // Reserved 1
|
|
SECURITY_NATIVE_DREP,
|
|
NULL, // No initial input token
|
|
0, // Reserved 2
|
|
&ClientContextHandle,
|
|
&NegotiateDesc,
|
|
&ContextAttributes,
|
|
&Lifetime );
|
|
|
|
if ( InitStatus != STATUS_SUCCESS ) {
|
|
if ( !QuietMode || !NT_SUCCESS(InitStatus) ) {
|
|
printf( "InitializeSecurityContext (negotiate): " );
|
|
PrintStatus( InitStatus );
|
|
}
|
|
if ( !NT_SUCCESS(InitStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( !QuietMode ) {
|
|
printf( "\n\nNegotiate Message:\n" );
|
|
|
|
printf( "ClientContextHandle: 0x%lx 0x%lx Attributes: 0x%lx ",
|
|
ClientContextHandle.dwLower, ClientContextHandle.dwUpper,
|
|
ContextAttributes );
|
|
PrintTime( "Lifetime: ", Lifetime );
|
|
|
|
DumpBuffer( NegotiateBuffer.pvBuffer, NegotiateBuffer.cbBuffer );
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
|
|
|
//
|
|
// Query as many attributes as possible
|
|
//
|
|
|
|
|
|
SecStatus = QueryContextAttributes(
|
|
&ClientContextHandle,
|
|
SECPKG_ATTR_SIZES,
|
|
&ContextSizes );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "QueryContextAttributes (sizes): " );
|
|
PrintStatus( SecStatus );
|
|
if ( !NT_SUCCESS(SecStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( !QuietMode ) {
|
|
printf( "QuerySizes: %ld %ld %ld %ld\n",
|
|
ContextSizes.cbMaxToken,
|
|
ContextSizes.cbMaxSignature,
|
|
ContextSizes.cbBlockSize,
|
|
ContextSizes.cbSecurityTrailer );
|
|
}
|
|
|
|
SecStatus = QueryContextAttributes(
|
|
&ClientContextHandle,
|
|
SECPKG_ATTR_NAMES,
|
|
ContextNamesBuffer );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "QueryContextAttributes (names): " );
|
|
PrintStatus( SecStatus );
|
|
if ( !NT_SUCCESS(SecStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( !QuietMode ) {
|
|
printf( "QueryNames: %ws\n", ContextNames->sUserName );
|
|
}
|
|
|
|
|
|
SecStatus = QueryContextAttributes(
|
|
&ClientContextHandle,
|
|
SECPKG_ATTR_LIFESPAN,
|
|
&ContextLifespan );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "QueryContextAttributes (lifespan): " );
|
|
PrintStatus( SecStatus );
|
|
if ( !NT_SUCCESS(SecStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( !QuietMode ) {
|
|
PrintTime(" Start:", ContextLifespan.tsStart );
|
|
PrintTime(" Expiry:", ContextLifespan.tsExpiry );
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//
|
|
// Get the ChallengeMessage (ServerSide)
|
|
//
|
|
|
|
NegotiateBuffer.BufferType |= SECBUFFER_READONLY;
|
|
ChallengeDesc.ulVersion = 0;
|
|
ChallengeDesc.cBuffers = 1;
|
|
ChallengeDesc.pBuffers = &ChallengeBuffer;
|
|
|
|
ChallengeBuffer.cbBuffer = PackageInfo->cbMaxToken;
|
|
ChallengeBuffer.BufferType = SECBUFFER_TOKEN;
|
|
ChallengeBuffer.pvBuffer = LocalAlloc( 0, ChallengeBuffer.cbBuffer );
|
|
if ( ChallengeBuffer.pvBuffer == NULL ) {
|
|
printf( "Allocate ChallengeMessage failed: 0x%ld\n", GetLastError() );
|
|
return;
|
|
}
|
|
ServerFlags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_DATAGRAM;
|
|
|
|
AcceptStatus = AcceptSecurityContext(
|
|
ServerCredHandle,
|
|
NULL, // No Server context yet
|
|
&NegotiateDesc,
|
|
ServerFlags,
|
|
SECURITY_NATIVE_DREP,
|
|
&ServerContextHandle,
|
|
&ChallengeDesc,
|
|
&ContextAttributes,
|
|
&Lifetime );
|
|
|
|
if ( AcceptStatus != STATUS_SUCCESS ) {
|
|
if ( !QuietMode || !NT_SUCCESS(AcceptStatus) ) {
|
|
printf( "AcceptSecurityContext (Challenge): " );
|
|
PrintStatus( AcceptStatus );
|
|
}
|
|
if ( !NT_SUCCESS(AcceptStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( !QuietMode ) {
|
|
printf( "\n\nChallenge Message:\n" );
|
|
|
|
printf( "ServerContextHandle: 0x%lx 0x%lx Attributes: 0x%lx ",
|
|
ServerContextHandle.dwLower, ServerContextHandle.dwUpper,
|
|
ContextAttributes );
|
|
PrintTime( "Lifetime: ", Lifetime );
|
|
|
|
DumpBuffer( ChallengeBuffer.pvBuffer, ChallengeBuffer.cbBuffer );
|
|
}
|
|
|
|
|
|
|
|
|
|
if (InitStatus != STATUS_SUCCESS)
|
|
{
|
|
|
|
//
|
|
// Get the AuthenticateMessage (ClientSide)
|
|
//
|
|
|
|
ChallengeBuffer.BufferType |= SECBUFFER_READONLY;
|
|
AuthenticateDesc.ulVersion = 0;
|
|
AuthenticateDesc.cBuffers = 1;
|
|
AuthenticateDesc.pBuffers = &AuthenticateBuffer;
|
|
|
|
AuthenticateBuffer.cbBuffer = PackageInfo->cbMaxToken;
|
|
AuthenticateBuffer.BufferType = SECBUFFER_TOKEN;
|
|
AuthenticateBuffer.pvBuffer = LocalAlloc( 0, AuthenticateBuffer.cbBuffer );
|
|
if ( AuthenticateBuffer.pvBuffer == NULL ) {
|
|
printf( "Allocate AuthenticateMessage failed: 0x%ld\n", GetLastError() );
|
|
return;
|
|
}
|
|
|
|
SecStatus = InitializeSecurityContext(
|
|
NULL,
|
|
&ClientContextHandle,
|
|
L"\\\\Frank\\IPC$", // Faked target name
|
|
0,
|
|
0, // Reserved 1
|
|
SECURITY_NATIVE_DREP,
|
|
&ChallengeDesc,
|
|
0, // Reserved 2
|
|
&ClientContextHandle,
|
|
&AuthenticateDesc,
|
|
&ContextAttributes,
|
|
&Lifetime );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "InitializeSecurityContext (Authenticate): " );
|
|
PrintStatus( SecStatus );
|
|
if ( !NT_SUCCESS(SecStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( !QuietMode ) {
|
|
printf( "\n\nAuthenticate Message:\n" );
|
|
|
|
printf( "ClientContextHandle: 0x%lx 0x%lx Attributes: 0x%lx ",
|
|
ClientContextHandle.dwLower, ClientContextHandle.dwUpper,
|
|
ContextAttributes );
|
|
PrintTime( "Lifetime: ", Lifetime );
|
|
|
|
DumpBuffer( AuthenticateBuffer.pvBuffer, AuthenticateBuffer.cbBuffer );
|
|
}
|
|
|
|
if (AcceptStatus != STATUS_SUCCESS)
|
|
{
|
|
|
|
//
|
|
// Finally authenticate the user (ServerSide)
|
|
//
|
|
|
|
AuthenticateBuffer.BufferType |= SECBUFFER_READONLY;
|
|
|
|
SecStatus = AcceptSecurityContext(
|
|
NULL,
|
|
&ServerContextHandle,
|
|
&AuthenticateDesc,
|
|
0,
|
|
SECURITY_NATIVE_DREP,
|
|
&ServerContextHandle,
|
|
NULL,
|
|
&ContextAttributes,
|
|
&Lifetime );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "AcceptSecurityContext (Challenge): " );
|
|
PrintStatus( SecStatus );
|
|
if ( !NT_SUCCESS(SecStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( !QuietMode ) {
|
|
printf( "\n\nFinal Authentication:\n" );
|
|
|
|
printf( "ServerContextHandle: 0x%lx 0x%lx Attributes: 0x%lx ",
|
|
ServerContextHandle.dwLower, ServerContextHandle.dwUpper,
|
|
ContextAttributes );
|
|
PrintTime( "Lifetime: ", Lifetime );
|
|
printf(" \n" );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef notdef
|
|
//
|
|
// Now make a third call to Initialize to check that RPC can
|
|
// reauthenticate.
|
|
//
|
|
|
|
AuthenticateBuffer.BufferType = SECBUFFER_TOKEN;
|
|
|
|
|
|
SecStatus = InitializeSecurityContext(
|
|
NULL,
|
|
&ClientContextHandle,
|
|
L"\\\\Frank\\IPC$", // Faked target name
|
|
0,
|
|
0, // Reserved 1
|
|
SECURITY_NATIVE_DREP,
|
|
NULL,
|
|
0, // Reserved 2
|
|
&ClientContextHandle,
|
|
&AuthenticateDesc,
|
|
&ContextAttributes,
|
|
&Lifetime );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "InitializeSecurityContext (Re-Authenticate): " );
|
|
PrintStatus( SecStatus );
|
|
if ( !NT_SUCCESS(SecStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Now try to re-authenticate the user (ServerSide)
|
|
//
|
|
|
|
AuthenticateBuffer.BufferType |= SECBUFFER_READONLY;
|
|
|
|
SecStatus = AcceptSecurityContext(
|
|
NULL,
|
|
&ServerContextHandle,
|
|
&AuthenticateDesc,
|
|
0,
|
|
SECURITY_NATIVE_DREP,
|
|
&ServerContextHandle,
|
|
NULL,
|
|
&ContextAttributes,
|
|
&Lifetime );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "AcceptSecurityContext (Re-authenticate): " );
|
|
PrintStatus( SecStatus );
|
|
if ( !NT_SUCCESS(SecStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Impersonate the client (ServerSide)
|
|
//
|
|
|
|
SecStatus = ImpersonateSecurityContext( &ServerContextHandle );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "ImpersonateSecurityContext: " );
|
|
PrintStatus( SecStatus );
|
|
if ( !NT_SUCCESS(SecStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Do something while impersonating (Access the token)
|
|
//
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE TokenHandle = NULL;
|
|
|
|
//
|
|
// Open the token,
|
|
//
|
|
|
|
Status = NtOpenThreadToken(
|
|
NtCurrentThread(),
|
|
TOKEN_QUERY,
|
|
(BOOLEAN) TRUE, // Not really using the impersonation token
|
|
&TokenHandle );
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
printf( "Access Thread token while impersonating: " );
|
|
PrintStatus( Status );
|
|
return;
|
|
} else {
|
|
(VOID) NtClose( TokenHandle );
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// If delegation is enabled and we are below our recursion depth, try
|
|
// this again.
|
|
//
|
|
if ((ClientFlags & ISC_REQ_DELEGATE) && (++RecursionDepth < MAX_RECURSION_DEPTH))
|
|
{
|
|
TestSspRoutine();
|
|
}
|
|
|
|
//
|
|
// RevertToSelf (ServerSide)
|
|
//
|
|
|
|
// SecStatus = RevertSecurityContext( &ServerContextHandle );
|
|
//
|
|
// if ( SecStatus != STATUS_SUCCESS ) {
|
|
// printf( "RevertSecurityContext: " );
|
|
// PrintStatus( SecStatus );
|
|
// if ( !NT_SUCCESS(SecStatus) ) {
|
|
// return;
|
|
// }
|
|
// }
|
|
|
|
|
|
#ifdef notdef
|
|
//
|
|
// Impersonate the client manually
|
|
//
|
|
|
|
SecStatus = QuerySecurityContextToken( &ServerContextHandle,&Token );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "QuerySecurityContextToken: " );
|
|
PrintStatus( SecStatus );
|
|
if ( !NT_SUCCESS(SecStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!ImpersonateLoggedOnUser(Token))
|
|
{
|
|
printf("Impersonate logged on user failed: %d\n",GetLastError());
|
|
return;
|
|
}
|
|
//
|
|
// Do something while impersonating (Access the token)
|
|
//
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE TokenHandle = NULL;
|
|
WCHAR UserName[100];
|
|
ULONG NameLength = 100;
|
|
|
|
//
|
|
// Open the token,
|
|
//
|
|
|
|
Status = NtOpenThreadToken(
|
|
NtCurrentThread(),
|
|
TOKEN_QUERY,
|
|
(BOOLEAN) TRUE, // Not really using the impersonation token
|
|
&TokenHandle );
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
printf( "Access Thread token while impersonating: " );
|
|
PrintStatus( Status );
|
|
return;
|
|
} else {
|
|
(VOID) NtClose( TokenHandle );
|
|
}
|
|
if (!GetUserName(UserName, &NameLength))
|
|
{
|
|
printf("Failed to get username: %d\n",GetLastError());
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
printf("Username = %ws\n",UserName);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// RevertToSelf (ServerSide)
|
|
//
|
|
|
|
// if (!RevertToSelf())
|
|
// {
|
|
// printf( "RevertToSelf failed: %d\n ",GetLastError() );
|
|
// return;
|
|
// }
|
|
CloseHandle(Token);
|
|
#endif
|
|
|
|
//
|
|
// Sign a message
|
|
//
|
|
|
|
SecStatus = MakeSignature(
|
|
&ClientContextHandle,
|
|
0,
|
|
&SignMessage,
|
|
0 );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "MakeSignature: " );
|
|
PrintStatus( SecStatus );
|
|
if ( !NT_SUCCESS(SecStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( !QuietMode ) {
|
|
|
|
printf("\n Signature: \n");
|
|
DumpBuffer(SigBuffers[1].pvBuffer,SigBuffers[1].cbBuffer);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Verify the signature
|
|
//
|
|
|
|
SecStatus = VerifySignature(
|
|
&ServerContextHandle,
|
|
&SignMessage,
|
|
0,
|
|
0 );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "VerifySignature: " );
|
|
PrintStatus( SecStatus );
|
|
if ( !NT_SUCCESS(SecStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Sign a message, this time to check if it can detect a change in the
|
|
// message
|
|
//
|
|
|
|
SecStatus = MakeSignature(
|
|
&ClientContextHandle,
|
|
0,
|
|
&SignMessage,
|
|
0 );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "MakeSignature: " );
|
|
PrintStatus( SecStatus );
|
|
if ( !NT_SUCCESS(SecStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( !QuietMode ) {
|
|
|
|
printf("\n Signature: \n");
|
|
DumpBuffer(SigBuffers[1].pvBuffer,SigBuffers[1].cbBuffer);
|
|
|
|
}
|
|
|
|
//
|
|
// Mess up the message to see if VerifySignature works
|
|
//
|
|
|
|
bDataBuffer[10] = 0xec;
|
|
|
|
//
|
|
// Verify the signature
|
|
//
|
|
|
|
SecStatus = VerifySignature(
|
|
&ServerContextHandle,
|
|
&SignMessage,
|
|
0,
|
|
0 );
|
|
|
|
if ( SecStatus != SEC_E_MESSAGE_ALTERED ) {
|
|
printf( "VerifySignature: " );
|
|
PrintStatus( SecStatus );
|
|
if ( !NT_SUCCESS(SecStatus) ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Delete both contexts.
|
|
//
|
|
|
|
|
|
SecStatus = DeleteSecurityContext( &ClientContextHandle );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "DeleteSecurityContext failed: " );
|
|
PrintStatus( SecStatus );
|
|
return;
|
|
}
|
|
|
|
SecStatus = DeleteSecurityContext( &ServerContextHandle );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "DeleteSecurityContext failed: " );
|
|
PrintStatus( SecStatus );
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Free both credential handles
|
|
//
|
|
|
|
if (AcquiredServerCred)
|
|
{
|
|
SecStatus = FreeCredentialsHandle( ServerCredHandle );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "FreeCredentialsHandle failed: " );
|
|
PrintStatus( SecStatus );
|
|
return;
|
|
}
|
|
ServerCredHandle = NULL;
|
|
|
|
}
|
|
|
|
SecStatus = FreeCredentialsHandle( &CredentialHandle2 );
|
|
|
|
if ( SecStatus != STATUS_SUCCESS ) {
|
|
printf( "FreeCredentialsHandle failed: " );
|
|
PrintStatus( SecStatus );
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// Final Cleanup
|
|
//
|
|
|
|
if ( NegotiateBuffer.pvBuffer != NULL ) {
|
|
(VOID) LocalFree( NegotiateBuffer.pvBuffer );
|
|
}
|
|
|
|
if ( ChallengeBuffer.pvBuffer != NULL ) {
|
|
(VOID) LocalFree( ChallengeBuffer.pvBuffer );
|
|
}
|
|
|
|
if ( AuthenticateBuffer.pvBuffer != NULL ) {
|
|
(VOID) LocalFree( AuthenticateBuffer.pvBuffer );
|
|
}
|
|
}
|
|
|
|
VOID
|
|
TestLogonRoutine(
|
|
IN LPSTR UserName,
|
|
IN LPSTR DomainName,
|
|
IN LPSTR Password
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
PKERB_INTERACTIVE_LOGON LogonInfo;
|
|
ULONG LogonInfoSize = sizeof(KERB_INTERACTIVE_LOGON);
|
|
BOOLEAN WasEnabled;
|
|
STRING Name;
|
|
ULONG Dummy;
|
|
HANDLE LogonHandle = NULL;
|
|
ULONG PackageId;
|
|
TOKEN_SOURCE SourceContext;
|
|
PKERB_INTERACTIVE_PROFILE Profile = NULL;
|
|
ULONG ProfileSize;
|
|
LUID LogonId;
|
|
HANDLE TokenHandle = NULL;
|
|
QUOTA_LIMITS Quotas;
|
|
NTSTATUS SubStatus;
|
|
WCHAR UserNameString[100];
|
|
ULONG NameLength = 100;
|
|
PUCHAR Where;
|
|
|
|
printf("Logging On %s\\%s %s\n",DomainName, UserName, Password);
|
|
LogonInfoSize += (strlen(UserName) + ((DomainName == NULL)? 0 : strlen(DomainName)) + strlen(Password) + 3 ) * sizeof(WCHAR);
|
|
|
|
LogonInfo = (PKERB_INTERACTIVE_LOGON) LocalAlloc(LMEM_ZEROINIT, LogonInfoSize);
|
|
|
|
LogonInfo->MessageType = KerbInteractiveLogon;
|
|
|
|
RtlInitString(
|
|
&Name,
|
|
UserName
|
|
);
|
|
|
|
Where = (PUCHAR) (LogonInfo + 1);
|
|
|
|
LogonInfo->UserName.Buffer = (LPWSTR) Where;
|
|
LogonInfo->UserName.MaximumLength = LogonInfoSize;
|
|
RtlAnsiStringToUnicodeString(
|
|
&LogonInfo->UserName,
|
|
&Name,
|
|
FALSE
|
|
);
|
|
Where += LogonInfo->UserName.Length + sizeof(WCHAR);
|
|
|
|
RtlInitString(
|
|
&Name,
|
|
DomainName
|
|
);
|
|
|
|
LogonInfo->LogonDomainName.Buffer = (LPWSTR) Where;
|
|
LogonInfo->LogonDomainName.MaximumLength = LogonInfoSize;
|
|
RtlAnsiStringToUnicodeString(
|
|
&LogonInfo->LogonDomainName,
|
|
&Name,
|
|
FALSE
|
|
);
|
|
Where += LogonInfo->LogonDomainName.Length + sizeof(WCHAR);
|
|
|
|
RtlInitString(
|
|
&Name,
|
|
Password
|
|
);
|
|
|
|
LogonInfo->Password.Buffer = (LPWSTR) Where;
|
|
LogonInfo->Password.MaximumLength = LogonInfoSize;
|
|
RtlAnsiStringToUnicodeString(
|
|
&LogonInfo->Password,
|
|
&Name,
|
|
FALSE
|
|
);
|
|
Where += LogonInfo->Password.Length + sizeof(WCHAR);
|
|
|
|
LogonInfo->MessageType = KerbInteractiveLogon;
|
|
LogonInfo->Flags = 0;
|
|
|
|
//
|
|
// Turn on the TCB privilege
|
|
//
|
|
|
|
Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, FALSE, &WasEnabled);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
printf("Failed to adjust privilege: 0x%x\n",Status);
|
|
return;
|
|
}
|
|
RtlInitString(
|
|
&Name,
|
|
"SspTest"
|
|
);
|
|
Status = LsaRegisterLogonProcess(
|
|
&Name,
|
|
&LogonHandle,
|
|
&Dummy
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
printf("Failed to register as a logon process: 0x%x\n",Status);
|
|
return;
|
|
}
|
|
|
|
strncpy(
|
|
SourceContext.SourceName,
|
|
"ssptest ",sizeof(SourceContext.SourceName)
|
|
);
|
|
NtAllocateLocallyUniqueId(
|
|
&SourceContext.SourceIdentifier
|
|
);
|
|
|
|
|
|
RtlInitString(
|
|
&Name,
|
|
MICROSOFT_KERBEROS_NAME_A
|
|
);
|
|
Status = LsaLookupAuthenticationPackage(
|
|
LogonHandle,
|
|
&Name,
|
|
&PackageId
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
printf("Failed to lookup package %Z: 0x%x\n",&Name, Status);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Now call LsaLogonUser
|
|
//
|
|
|
|
RtlInitString(
|
|
&Name,
|
|
"ssptest"
|
|
);
|
|
|
|
Status = LsaLogonUser(
|
|
LogonHandle,
|
|
&Name,
|
|
Interactive,
|
|
PackageId,
|
|
LogonInfo,
|
|
LogonInfoSize,
|
|
NULL, // no token groups
|
|
&SourceContext,
|
|
(PVOID *) &Profile,
|
|
&ProfileSize,
|
|
&LogonId,
|
|
&TokenHandle,
|
|
&Quotas,
|
|
&SubStatus
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
printf("lsalogonuser failed: 0x%x\n",Status);
|
|
return;
|
|
}
|
|
if (!NT_SUCCESS(SubStatus))
|
|
{
|
|
printf("LsalogonUser failed: substatus = 0x%x\n",SubStatus);
|
|
return;
|
|
}
|
|
|
|
ImpersonateLoggedOnUser( TokenHandle );
|
|
GetUserName(UserNameString,&NameLength);
|
|
printf("Username = %ws\n",UserNameString);
|
|
RevertToSelf();
|
|
NtClose(TokenHandle);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int __cdecl
|
|
main(
|
|
IN int argc,
|
|
IN char ** argv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Drive the NtLmSsp service
|
|
|
|
Arguments:
|
|
|
|
argc - the number of command-line arguments.
|
|
|
|
argv - an array of pointers to the arguments.
|
|
|
|
Return Value:
|
|
|
|
Exit status
|
|
|
|
--*/
|
|
{
|
|
LPSTR argument;
|
|
int i;
|
|
ULONG j;
|
|
ULONG Iterations;
|
|
LPSTR UserName,DomainName,Password;
|
|
|
|
|
|
|
|
|
|
enum {
|
|
NoAction,
|
|
#define TESTSSP_PARAM "/TestSsp"
|
|
TestSsp,
|
|
#define CONFIG_PARAM "/ConfigureService"
|
|
ConfigureService,
|
|
#define LOGON_PARAM "/Logon"
|
|
TestLogon,
|
|
} Action = NoAction;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Loop through the arguments handle each in turn
|
|
//
|
|
|
|
for ( i=1; i<argc; i++ ) {
|
|
|
|
argument = argv[i];
|
|
|
|
//
|
|
// Handle /ConfigureService
|
|
//
|
|
|
|
if ( _stricmp( argument, CONFIG_PARAM ) == 0 ) {
|
|
if ( Action != NoAction ) {
|
|
goto Usage;
|
|
}
|
|
|
|
Action = ConfigureService;
|
|
|
|
|
|
} else if ( _stricmp( argument, TESTSSP_PARAM ) == 0 ) {
|
|
if ( Action != NoAction ) {
|
|
goto Usage;
|
|
}
|
|
|
|
Action = TestSsp;
|
|
Iterations = 1;
|
|
|
|
|
|
} else if ( _stricmp( argument, LOGON_PARAM ) == 0 ) {
|
|
if ( Action != NoAction ) {
|
|
goto Usage;
|
|
}
|
|
|
|
Action = TestLogon;
|
|
Iterations = 1;
|
|
|
|
if (argc < i + 2)
|
|
{
|
|
goto Usage;
|
|
}
|
|
Password = argv[++i];
|
|
UserName = argv[++i];
|
|
if (i < argc)
|
|
{
|
|
DomainName = argv[++i];
|
|
}
|
|
else
|
|
{
|
|
DomainName = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Perform the action requested
|
|
//
|
|
|
|
switch ( Action ) {
|
|
|
|
case ConfigureService:
|
|
ConfigureServiceRoutine();
|
|
break;
|
|
|
|
case TestSsp: {
|
|
for ( j=0; j<Iterations ; j++ ) {
|
|
TestSspRoutine( );
|
|
}
|
|
break;
|
|
}
|
|
case TestLogon : {
|
|
TestLogonRoutine(
|
|
UserName,
|
|
DomainName,
|
|
Password
|
|
);
|
|
}
|
|
}
|
|
|
|
Usage:
|
|
return 0;
|
|
|
|
}
|
|
|