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.
530 lines
14 KiB
530 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cachelogon.cxx
|
|
|
|
Abstract:
|
|
|
|
cachelogon
|
|
|
|
Author:
|
|
|
|
Larry Zhu (LZhu) December 1, 2001 Created
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include <logonmsv.h>
|
|
#include <tchar.h>
|
|
|
|
#include "cachelogon.hxx"
|
|
|
|
EXTERN_C
|
|
NTSTATUS NTAPI
|
|
LsaICallPackage(
|
|
IN PUNICODE_STRING AuthenticationPackage,
|
|
IN PVOID ProtocolSubmitBuffer,
|
|
IN ULONG SubmitBufferLength,
|
|
OUT PVOID *ProtocolReturnBuffer,
|
|
OUT PULONG ReturnBufferLength,
|
|
OUT PNTSTATUS ProtocolStatus
|
|
);
|
|
|
|
BOOL
|
|
DllMain(
|
|
IN HANDLE hModule,
|
|
IN DWORD dwReason,
|
|
IN DWORD dwReserved
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
switch (dwReason)
|
|
{
|
|
case DLL_THREAD_ATTACH:
|
|
break;
|
|
|
|
case DLL_THREAD_DETACH:
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
|
|
case DLL_PROCESS_ATTACH:
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
bRet = DllMainDefaultHandler(hModule, dwReason, dwReserved);
|
|
|
|
DebugPrintf(SSPI_LOG, "DllMain leaving %#x\n", bRet);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
int
|
|
RunIt(
|
|
IN ULONG cbParameters,
|
|
IN VOID* pvParameters
|
|
)
|
|
{
|
|
//
|
|
// RunItDefaultHandler calls Start() and adds try except
|
|
//
|
|
|
|
DWORD dwErr;
|
|
|
|
dwErr = RunItDefaultHandler(cbParameters, pvParameters);
|
|
|
|
DebugPrintf(SSPI_LOG, "RunIt leaving %#x\n", dwErr);
|
|
|
|
return dwErr;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
CacheLogonInformation(
|
|
IN PUNICODE_STRING pUserName,
|
|
IN PUNICODE_STRING pDomainName,
|
|
IN OPTIONAL PUNICODE_STRING pPassword,
|
|
IN OPTIONAL PUNICODE_STRING pDnsDomainName,
|
|
IN OPTIONAL PUNICODE_STRING pUpn,
|
|
IN ULONG ParameterControl,
|
|
IN BOOLEAN bIsMitLogon,
|
|
IN ULONG CacheRequestFlags,
|
|
IN OPTIONAL PNETLOGON_VALIDATION_SAM_INFO3 pValidationInfo,
|
|
IN OPTIONAL PVOID pSupplementalCreds,
|
|
IN OPTIONAL ULONG cbSupplementalCredSize
|
|
)
|
|
{
|
|
TNtStatus Status = STATUS_SUCCESS;
|
|
|
|
ULONG cbCacheRequest = 0;
|
|
HANDLE hLsa = NULL;
|
|
ULONG PackageId = 0;
|
|
|
|
MSV1_0_CACHE_LOGON_REQUEST* pCacheRequest = NULL;
|
|
NETLOGON_VALIDATION_SAM_INFO4* pValidationInfoToUse = NULL;
|
|
NETLOGON_INTERACTIVE_INFO* pMsvLogonInfo = NULL;
|
|
|
|
PVOID pOutputBuffer = NULL;
|
|
ULONG cbOutputBufferSize = NULL;
|
|
|
|
PVOID pSupplementalMitCreds = NULL;
|
|
ULONG cbSupplementalMitCredSize = 0;
|
|
WCHAR szWorkStation[256] = {0};
|
|
UNICODE_STRING Workstation = {0, sizeof(szWorkStation), szWorkStation};
|
|
UNICODE_STRING MsvPackageName = CONSTANT_UNICODE_STRING(TEXT(MSV1_0_PACKAGE_NAME));
|
|
|
|
NTSTATUS SubStatus = STATUS_UNSUCCESSFUL;
|
|
|
|
WCHAR* pWhere = NULL;
|
|
ULONG cchWorkstation = COUNTOF(szWorkStation);
|
|
|
|
(VOID) GetComputerNameW(szWorkStation, &cchWorkstation);
|
|
|
|
Workstation.Length = (USHORT) cchWorkstation * sizeof(WCHAR);
|
|
|
|
SspiPrint(SSPI_LOG,
|
|
TEXT("CacheLogonInformation workstation %wZ, User %wZ, Domain %wZ, Password %wZ, DnsDomain %wZ, Upn %wZ, ")
|
|
TEXT("ParameterControl %#x, bIsMitLogon %#x, CacheRequestFlags %#x, pValidationInfo %p, ")
|
|
TEXT("pSupplementalCreds %p, cbSupplementalCredSize %#x\n"),
|
|
&Workstation, pUserName, pDomainName, pPassword, pDnsDomainName, pUpn,
|
|
ParameterControl, bIsMitLogon, CacheRequestFlags, pValidationInfo,
|
|
pSupplementalCreds, cbSupplementalCredSize);
|
|
|
|
cbCacheRequest = ROUND_UP_COUNT(sizeof(NETLOGON_INTERACTIVE_INFO), sizeof(ULONG_PTR))
|
|
+ ROUND_UP_COUNT(pDomainName->Length + sizeof(WCHAR), sizeof(ULONG_PTR))
|
|
+ ROUND_UP_COUNT(Workstation.Length + sizeof(WCHAR), sizeof(ULONG_PTR))
|
|
+ ROUND_UP_COUNT(pUserName->Length + sizeof(WCHAR), sizeof(ULONG_PTR)) + 10 * sizeof(ULONG_PTR);
|
|
|
|
if (bIsMitLogon)
|
|
{
|
|
cbSupplementalMitCredSize = (2 * ROUND_UP_COUNT(sizeof(UNICODE_STRING), sizeof(ULONG_PTR)))
|
|
+ ROUND_UP_COUNT(pUserName->Length + sizeof(WCHAR), sizeof(ULONG_PTR))
|
|
+ ROUND_UP_COUNT(pDomainName->Length + sizeof(WCHAR), sizeof(ULONG_PTR));
|
|
cbCacheRequest = cbSupplementalMitCredSize;
|
|
}
|
|
else
|
|
{
|
|
cbCacheRequest += ROUND_UP_COUNT(cbSupplementalCredSize, sizeof(ULONG_PTR));
|
|
}
|
|
|
|
cbCacheRequest += ROUND_UP_COUNT(sizeof(NETLOGON_VALIDATION_SAM_INFO4), sizeof(ULONG_PTR));
|
|
if (pDnsDomainName)
|
|
{
|
|
cbCacheRequest += ROUND_UP_COUNT(pDnsDomainName->Length + sizeof(WCHAR), sizeof(ULONG_PTR));
|
|
}
|
|
|
|
pCacheRequest = (MSV1_0_CACHE_LOGON_REQUEST*) new CHAR[cbCacheRequest];
|
|
Status DBGCHK = pCacheRequest ? STATUS_SUCCESS : STATUS_NO_MEMORY;
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
RtlZeroMemory(pCacheRequest, cbCacheRequest);
|
|
pCacheRequest->MessageType = MsV1_0CacheLogon;
|
|
|
|
pMsvLogonInfo = (NETLOGON_INTERACTIVE_INFO*) ROUND_UP_POINTER(((PCHAR)pCacheRequest) + ROUND_UP_COUNT(sizeof(*pCacheRequest), sizeof(ULONG_PTR)), sizeof(ULONG_PTR));
|
|
|
|
pCacheRequest->LogonInformation = pMsvLogonInfo;
|
|
|
|
pWhere = (WCHAR*) (((PCHAR) pMsvLogonInfo) + ROUND_UP_COUNT(sizeof(*pMsvLogonInfo), sizeof(ULONG_PTR)));
|
|
|
|
pMsvLogonInfo->Identity.ParameterControl = ParameterControl;
|
|
|
|
PackUnicodeStringAsUnicodeStringZ(pDomainName, &pWhere, &pMsvLogonInfo->Identity.LogonDomainName);
|
|
PackUnicodeStringAsUnicodeStringZ(pUserName, &pWhere, &pMsvLogonInfo->Identity.UserName);
|
|
PackUnicodeStringAsUnicodeStringZ(&Workstation, &pWhere, &pMsvLogonInfo->Identity.Workstation);
|
|
|
|
if (pPassword)
|
|
{
|
|
Status DBGCHK = RtlCalculateNtOwfPassword(
|
|
pPassword,
|
|
&pMsvLogonInfo->NtOwfPassword
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If this was a logon to an MIT realm that we know about,
|
|
// then add the MIT username (upn?) & realm to the supplemental data
|
|
//
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (bIsMitLogon)
|
|
{
|
|
SspiPrint(SSPI_LOG, TEXT("Using MIT caching\n"));
|
|
|
|
pCacheRequest->RequestFlags = MSV1_0_CACHE_LOGON_REQUEST_MIT_LOGON | CacheRequestFlags;
|
|
|
|
pSupplementalMitCreds = ROUND_UP_POINTER(pWhere, sizeof(ULONG_PTR));
|
|
|
|
pWhere += /* 2 * */ ROUND_UP_COUNT(sizeof(UNICODE_STRING), sizeof(ULONG_PTR));
|
|
|
|
PackUnicodeStringAsUnicodeStringZ(pUserName, &pWhere, (UNICODE_STRING*) pSupplementalMitCreds);
|
|
PackUnicodeStringAsUnicodeStringZ(pDomainName, &pWhere, ((UNICODE_STRING*) pSupplementalMitCreds) + 1);
|
|
|
|
pCacheRequest->SupplementalCacheData = pSupplementalMitCreds;
|
|
pCacheRequest->SupplementalCacheDataLength = cbSupplementalMitCredSize;
|
|
}
|
|
else
|
|
{
|
|
pCacheRequest->RequestFlags = CacheRequestFlags;
|
|
|
|
pCacheRequest->SupplementalCacheData = ROUND_UP_POINTER(pWhere, sizeof(ULONG_PTR));
|
|
pCacheRequest->SupplementalCacheDataLength = cbSupplementalCredSize;
|
|
pWhere = (WCHAR*) ROUND_UP_POINTER(((CHAR*) pWhere) + sizeof(ULONG_PTR) + cbSupplementalCredSize, sizeof(ULONG_PTR));
|
|
if (pSupplementalCreds)
|
|
{
|
|
RtlCopyMemory(pCacheRequest->SupplementalCacheData, pSupplementalCreds, cbSupplementalCredSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
pValidationInfoToUse = (NETLOGON_VALIDATION_SAM_INFO4*) ROUND_UP_POINTER(pWhere, sizeof(ULONG_PTR));
|
|
|
|
pCacheRequest->ValidationInformation = pValidationInfoToUse;
|
|
pCacheRequest->RequestFlags |= MSV1_0_CACHE_LOGON_REQUEST_INFO4;
|
|
|
|
pWhere = (WCHAR*) ROUND_UP_POINTER(pValidationInfoToUse, sizeof(ULONG_PTR));
|
|
|
|
if (pValidationInfo)
|
|
{
|
|
RtlCopyMemory(pValidationInfoToUse,
|
|
pValidationInfo,
|
|
sizeof(*pValidationInfo));
|
|
}
|
|
|
|
if (pDnsDomainName)
|
|
{
|
|
PackUnicodeStringAsUnicodeStringZ(pDnsDomainName, &pWhere, &pValidationInfoToUse->DnsLogonDomainName);
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
SspiPrintHex(SSPI_LOG, TEXT("CacheRequest"), cbCacheRequest, pCacheRequest);
|
|
|
|
Status DBGCHK = GetLsaHandleAndPackageId(MSV1_0_PACKAGE_NAME, &hLsa, &PackageId);
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status DBGCHK = LsaICallPackage(
|
|
&MsvPackageName,
|
|
pCacheRequest,
|
|
sizeof(MSV1_0_CACHE_LOGON_REQUEST), // cbCacheRequest,
|
|
&pOutputBuffer,
|
|
&cbOutputBufferSize,
|
|
&SubStatus
|
|
);
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status DBGCHK = SubStatus;
|
|
}
|
|
|
|
if (pCacheRequest)
|
|
{
|
|
delete [] pCacheRequest;
|
|
}
|
|
|
|
if (pOutputBuffer)
|
|
{
|
|
LsaFreeReturnBuffer(pOutputBuffer);
|
|
}
|
|
|
|
if (hLsa)
|
|
{
|
|
LsaDeregisterLogonProcess(hLsa);
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
Return Values for Start():
|
|
|
|
ERROR_NO_MORE_USER_HANDLES unload repeatedly
|
|
ERROR_SERVER_HAS_OPEN_HANDLES no unload at all
|
|
others unload once
|
|
|
|
#endif 0
|
|
|
|
int
|
|
Start(
|
|
IN ULONG cbParameters,
|
|
IN VOID* pvParameters
|
|
)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
CHAR* pNlpCacheEncryptionKey = NULL;
|
|
LIST_ENTRY** ppNlpActiveCtes = NULL;
|
|
|
|
SspiPrintHex(SSPI_LOG, TEXT("Start Parameters"), cbParameters, pvParameters);
|
|
|
|
if (cbParameters >= 3)
|
|
{
|
|
TNtStatus Status;
|
|
|
|
UNICODE_STRING UserName = {0};
|
|
UNICODE_STRING DomainName = {0};
|
|
|
|
ULONG ParameterControl = RPC_C_AUTHN_GSS_KERBEROS;
|
|
ULONG CacheRequestFlags = MSV1_0_CACHE_LOGON_DELETE_ENTRY;
|
|
|
|
Status DBGCHK = CreateUnicodeStringFromAsciiz((CHAR*)pvParameters, &UserName);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status DBGCHK = CreateUnicodeStringFromAsciiz(((CHAR*) pvParameters) + strlen((CHAR*) pvParameters) + 1, &DomainName);
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status DBGCHK = CacheLogonInformation(
|
|
&UserName,
|
|
&DomainName,
|
|
NULL, // no password
|
|
NULL, // no dns domain
|
|
NULL, // no upn
|
|
ParameterControl,
|
|
FALSE, // not MIT
|
|
CacheRequestFlags, // flags
|
|
NULL, // no validation info
|
|
NULL, // no supplemental creds
|
|
0 // sizeof supplemental cred is 0
|
|
);
|
|
|
|
}
|
|
|
|
RtlFreeUnicodeString(&UserName);
|
|
RtlFreeUnicodeString(&DomainName);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
SspiPrint(SSPI_LOG, TEXT("Operation succeeded\n"));
|
|
}
|
|
else
|
|
{
|
|
SspiPrint(SSPI_LOG, TEXT("Operation failed\n"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
SspiPrint(SSPI_LOG, TEXT("Start received invalid parameter\n"));
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
#if 0
|
|
|
|
VOID
|
|
Usage(
|
|
IN PCTSTR pszApp
|
|
)
|
|
{
|
|
SspiPrint(SSPI_ERROR,
|
|
TEXT("\n\nUsage: %s -u<user> -d<domain> [-c<ParameterControl>] [-f<CacheRequestFlags>]\n\n"),
|
|
pszApp);
|
|
exit(-1);
|
|
}
|
|
|
|
VOID __cdecl
|
|
_tmain(
|
|
IN INT argc,
|
|
IN PTSTR argv[]
|
|
)
|
|
{
|
|
TNtStatus Status = STATUS_SUCCESS;
|
|
|
|
UNICODE_STRING ClientName = {0};
|
|
UNICODE_STRING ClientRealm = {0};
|
|
ULONG ParameterControl = RPC_C_AUTHN_GSS_KERBEROS;
|
|
ULONG CacheRequestFlags = MSV1_0_CACHE_LOGON_DELETE_ENTRY;
|
|
|
|
AUTO_LOG_OPEN(TEXT("cachelogon.exe"));
|
|
|
|
for (INT i = 1; NT_SUCCESS(Status) && (i < argc); i++)
|
|
{
|
|
if ((*argv[i] == TEXT('-')) || (*argv[i] == TEXT('/')))
|
|
{
|
|
switch (argv[i][1])
|
|
{
|
|
case TEXT('u'):
|
|
RtlInitUnicodeString(&ClientName, argv[i] + 2);
|
|
break;
|
|
|
|
case TEXT('d'):
|
|
RtlInitUnicodeString(&ClientRealm, argv[i] + 2);
|
|
break;
|
|
|
|
case TEXT('c'):
|
|
ParameterControl = wcstol(argv[i] + 2, NULL, 0);
|
|
break;
|
|
|
|
case TEXT('f'):
|
|
CacheRequestFlags = wcstol(argv[i] + 2, NULL, 0);
|
|
break;
|
|
|
|
case TEXT('h'):
|
|
case TEXT('?'):
|
|
default:
|
|
Usage(argv[0]);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Usage(argv[0]);
|
|
}
|
|
}
|
|
|
|
Status DBGCHK = CacheLogonInformation(
|
|
&ClientName,
|
|
&ClientRealm,
|
|
NULL, // no password
|
|
NULL, // no dns domain
|
|
NULL, // no upn
|
|
ParameterControl,
|
|
FALSE, // not MIT
|
|
CacheRequestFlags, // flags
|
|
NULL, // no validation info
|
|
NULL, // no supplemental creds
|
|
0 // sizeof supplemental cred is 0
|
|
);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
SspiPrint(SSPI_LOG, TEXT("Operation succeeded\n"));
|
|
}
|
|
else
|
|
{
|
|
SspiPrint(SSPI_ERROR, TEXT("Operation failed\n"));
|
|
}
|
|
|
|
AUTO_LOG_CLOSE();
|
|
}
|
|
|
|
#endif
|
|
|
|
Init(
|
|
IN ULONG argc,
|
|
IN PCSTR argv[],
|
|
OUT ULONG* pcbParameters,
|
|
OUT VOID** ppvParameters
|
|
)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
CHAR Parameters[REMOTE_PACKET_SIZE] = {0};
|
|
ULONG cbBuffer = sizeof(Parameters);
|
|
ULONG cbParameter = 0;
|
|
|
|
CHAR* pNlpCacheEncryptionKey = NULL;
|
|
LIST_ENTRY** ppNlpActiveCtes = NULL;
|
|
|
|
*pcbParameters = 0;
|
|
*ppvParameters = NULL;
|
|
|
|
if (argc == 2)
|
|
{
|
|
DebugPrintf(SSPI_LOG, "argv[0] %s, argv[1] %s\n", argv[0], argv[1]);
|
|
|
|
pNlpCacheEncryptionKey = (CHAR*) (ULONG_PTR) strtol(argv[0], NULL, 0);
|
|
ppNlpActiveCtes = (LIST_ENTRY**) (ULONG_PTR) strtol(argv[1], NULL, 0);
|
|
|
|
SspiPrint(SSPI_LOG, TEXT("msv1_0!NlpCacheEncryptionKey %p, addr of msv1_0!NlpActiveCtes %p\n"), pNlpCacheEncryptionKey, ppNlpActiveCtes);
|
|
|
|
memcpy(Parameters, argv[0], strlen(argv[0]) + 1);
|
|
cbParameter = strlen(argv[0]) + 1;
|
|
|
|
memcpy(Parameters + cbParameter, argv[1], strlen(argv[1]) + 1);
|
|
cbParameter += strlen(argv[1]) + 1;
|
|
cbParameter++; // add a NULL
|
|
}
|
|
else // return "Usage" in ppvParameters, must be a NULL terminated string
|
|
{
|
|
strcpy(Parameters, "<user name> <domain name>");
|
|
cbParameter = strlen(Parameters) + 1;
|
|
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
*ppvParameters = new CHAR[cbParameter];
|
|
if (*ppvParameters)
|
|
{
|
|
*pcbParameters = cbParameter;
|
|
memcpy(*ppvParameters, Parameters, *pcbParameters);
|
|
}
|
|
else
|
|
{
|
|
dwErr = ERROR_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
return dwErr;
|
|
}
|
|
|