|
|
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
msvsharelevel.cxx
Abstract:
msvsharelevel
Author:
Larry Zhu (LZhu) January 1, 2002 Created
Environment:
User Mode
Revision History:
--*/
#include "precomp.hxx"
#pragma hdrstop
#include "msvsharelevel.hxx"
NTSTATUS GetNtlmChallengeMessage( IN OPTIONAL UNICODE_STRING* pPassword, IN OPTIONAL UNICODE_STRING* pUserName, IN OPTIONAL UNICODE_STRING* pDomainName, OUT ULONG* pcbNtlmChallengeMessage, OUT NTLM_CHALLENGE_MESSAGE** ppNtlmChallengeMessage ) { TNtStatus Status;
UCHAR* pWhere = NULL;
ULONG cbNtlmChallengeMessage = 0; NTLM_CHALLENGE_MESSAGE* pNtlmChallengeMessage = NULL;
*ppNtlmChallengeMessage = NULL; *pcbNtlmChallengeMessage = 0;
cbNtlmChallengeMessage = (pPassword ? pPassword->Length : 0) + (pUserName ? pUserName->Length : 0) + (pDomainName ? pDomainName->Length : 0) + ROUND_UP_COUNT(sizeof(NTLM_CHALLENGE_MESSAGE), sizeof(ULONG_PTR)); pNtlmChallengeMessage = (NTLM_CHALLENGE_MESSAGE*) new CHAR[cbNtlmChallengeMessage];
Status DBGCHK = pNtlmChallengeMessage ? STATUS_SUCCESS : STATUS_NO_MEMORY;
if (NT_SUCCESS(Status)) { RtlZeroMemory(pNtlmChallengeMessage, cbNtlmChallengeMessage); pWhere = (UCHAR*) (pNtlmChallengeMessage + 1); SspCopyStringAsString32( pNtlmChallengeMessage, (STRING*) pPassword, &pWhere, &pNtlmChallengeMessage->Password ); SspCopyStringAsString32( pNtlmChallengeMessage, (STRING*) pUserName, &pWhere, &pNtlmChallengeMessage->UserName ); SspCopyStringAsString32( pNtlmChallengeMessage, (STRING*) pDomainName, &pWhere, &pNtlmChallengeMessage->DomainName ); *ppNtlmChallengeMessage = pNtlmChallengeMessage; pNtlmChallengeMessage = NULL; *pcbNtlmChallengeMessage = cbNtlmChallengeMessage; }
if (pNtlmChallengeMessage) { delete [] pNtlmChallengeMessage; }
return Status; }
NTSTATUS GetNegociateMessage( IN OPTIONAL OEM_STRING* pOemDomainName, IN OPTIONAL OEM_STRING* pOemWorkstationName, IN ULONG NegotiateFlags, OUT ULONG* pcbNegotiateMessage, OUT NEGOTIATE_MESSAGE** ppNegotiateMessage ) { TNtStatus Status = STATUS_SUCCESS;
NEGOTIATE_MESSAGE* pNegotiateMessage = NULL; ULONG cbNegotiateMessage = 0;
PUCHAR pWhere = NULL;
*ppNegotiateMessage = NULL; *pcbNegotiateMessage = 0;
cbNegotiateMessage = sizeof(NEGOTIATE_MESSAGE);
if (pOemDomainName && pOemDomainName->Length && (NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED & NegotiateFlags)) { cbNegotiateMessage += pOemDomainName->MaximumLength; }
if (pOemWorkstationName && pOemWorkstationName->Length && (NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED & NegotiateFlags)) { cbNegotiateMessage += pOemWorkstationName->MaximumLength; }
pNegotiateMessage = (NEGOTIATE_MESSAGE*) new char[cbNegotiateMessage]; Status DBGCHK = pNegotiateMessage ? S_OK : E_OUTOFMEMORY;
if (NT_SUCCESS(Status)) { RtlZeroMemory(pNegotiateMessage, cbNegotiateMessage);
cbNegotiateMessage = sizeof(NEGOTIATE_MESSAGE); strcpy(reinterpret_cast<char*>(pNegotiateMessage->Signature), NTLMSSP_SIGNATURE); pNegotiateMessage->MessageType = NtLmNegotiate;
pWhere = (UCHAR*)(pNegotiateMessage + 1);
if (pOemDomainName && pOemDomainName->Length && (NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED & NegotiateFlags)) { SspCopyStringAsString32( pNegotiateMessage, (STRING*)pOemDomainName, &pWhere, &pNegotiateMessage->OemDomainName ); }
if (pOemWorkstationName && pOemWorkstationName->Length && (NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED & NegotiateFlags)) { SspCopyStringAsString32( pNegotiateMessage, (STRING*) pOemWorkstationName, &pWhere, &pNegotiateMessage->OemWorkstationName); }
pNegotiateMessage->NegotiateFlags = NegotiateFlags;
*ppNegotiateMessage = pNegotiateMessage; pNegotiateMessage = NULL; *pcbNegotiateMessage = cbNegotiateMessage; }
if (pNegotiateMessage) { delete [] pNegotiateMessage; }
return Status; }
NTSTATUS GetChallengeMessage( IN ULONG ContextReqFlags, IN OPTIONAL ULONG cbNegotiateMessage, IN ULONG TargetFlags, IN UNICODE_STRING* pTargetInfo, IN UNICODE_STRING* pTargetName, IN PNEGOTIATE_MESSAGE pNegotiateMessage, IN UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH], OUT PULONG pcbChallengeMessage, OUT CHALLENGE_MESSAGE** ppChallengeMessage, OUT PULONG pContextAttributes ) { TNtStatus Status = STATUS_SUCCESS;
ULONG ContextAttributes = 0;
STRING StringTargetName = {0}; ULONG ChallengeMessageTargetFlags = 0;
CHALLENGE_MESSAGE* pChallengeMessage = NULL; ULONG cbChallengeMessage = 0; PUCHAR pWhere = NULL;
STRING OemWorkstationName = {0}; STRING OemDomainName = {0};
ULONG NegotiateFlagsKeyStrength = NTLMSSP_NEGOTIATE_56;
*ppChallengeMessage = NULL; *pContextAttributes = 0;
if ((ContextReqFlags & ASC_REQ_IDENTIFY) != 0) { ContextAttributes |= ASC_RET_IDENTIFY; }
if ( (ContextReqFlags & ASC_REQ_DATAGRAM) != 0 ) { ContextAttributes |= ASC_RET_DATAGRAM; }
if ((ContextReqFlags & ASC_REQ_CONNECTION) != 0 ) { ContextAttributes |= ASC_RET_CONNECTION; }
if ((ContextReqFlags & ASC_REQ_INTEGRITY) != 0 ) { ContextAttributes |= ASC_RET_INTEGRITY; }
if ((ContextReqFlags & ASC_REQ_REPLAY_DETECT) != 0) { ContextAttributes |= ASC_RET_REPLAY_DETECT; }
if ( (ContextReqFlags & ASC_REQ_SEQUENCE_DETECT ) != 0) { ContextAttributes |= ASC_RET_SEQUENCE_DETECT; }
if ((ContextReqFlags & ASC_REQ_ALLOW_NON_USER_LOGONS ) != 0) { ContextAttributes |= ASC_RET_ALLOW_NON_USER_LOGONS; }
if ( ContextReqFlags & ASC_REQ_CONFIDENTIALITY ) { ContextAttributes|= ASC_RET_CONFIDENTIALITY; }
NegotiateFlagsKeyStrength |= NTLMSSP_NEGOTIATE_128;
//
// Get the pNegotiateMessage. If we are re-establishing a datagram
// context then there may not be one.
//
if ( cbNegotiateMessage >= sizeof(OLD_NEGOTIATE_MESSAGE) ) { //
// Compute the TargetName to return in the ChallengeMessage.
//
if ( pNegotiateMessage->NegotiateFlags & NTLMSSP_REQUEST_TARGET || pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2) {
Status DBGCHK = RtlDuplicateUnicodeString( RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING | RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, pTargetName, (UNICODE_STRING*) &StringTargetName );
if (NT_SUCCESS(Status) && ( 0 == (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE)) ) { Status DBGCHK = RtlUnicodeStringToOemString((POEM_STRING) &StringTargetName, (PCUNICODE_STRING)&StringTargetName, FALSE); }
//
// if client is NTLM2-aware, send it target info AV pairs
//
if (NT_SUCCESS(Status)) {
ChallengeMessageTargetFlags = TargetFlags | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO; } } else { ChallengeMessageTargetFlags = 0; }
//
// Allocate a Challenge message
//
if (NT_SUCCESS(Status)) { cbChallengeMessage = sizeof(*pChallengeMessage) + pTargetName->Length + pTargetInfo->Length;
pChallengeMessage = (CHALLENGE_MESSAGE*) new CHAR [cbChallengeMessage]; Status DBGCHK = pChallengeMessage ? STATUS_SUCCESS : STATUS_NO_MEMORY; }
if (NT_SUCCESS(Status)) { RtlZeroMemory(pChallengeMessage, cbChallengeMessage); pChallengeMessage->NegotiateFlags = 0;
//
// Check that both sides can use the same authentication model. For
// compatibility with beta 1 and 2 (builds 612 and 683), no requested
// authentication type is assumed to be NTLM. If NetWare is explicitly
// asked for, it is assumed that NTLM would have been also, so if it
// wasn't, return an error.
//
if ( (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NETWARE) && ((pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM) == 0) && ((pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2) == 0) ) { Status DBGCHK = STATUS_NOT_SUPPORTED; } else { pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; } }
//
// if client can do NTLM2, nuke LM_KEY
//
if (NT_SUCCESS(Status)) { if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2) { pNegotiateMessage->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM2; } else if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_LM_KEY) { pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY; }
//
// If the client wants to always sign messages, so be it.
//
if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN ) { pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; }
//
// If the caller wants identify level, so be it.
//
if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_IDENTIFY ) { pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_IDENTIFY;
ContextAttributes |= ASC_RET_IDENTIFY; }
//
// Determine if the caller wants OEM or UNICODE
//
// Prefer UNICODE if caller allows both.
//
if ( pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE ) { pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; } else if ( pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_OEM ) { pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_OEM; } else { Status DBGCHK = SEC_E_INVALID_TOKEN; } }
if (NT_SUCCESS(Status)) { //
// Client wants Sign capability, OK.
//
if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_SIGN) { pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
ContextAttributes |= (ASC_RET_SEQUENCE_DETECT | ASC_RET_REPLAY_DETECT); }
//
// Client wants Seal, OK.
//
if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_SEAL) { pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
ContextAttributes |= ASC_RET_CONFIDENTIALITY; }
if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH) { pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
}
if ( (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_56) && (NegotiateFlagsKeyStrength & NTLMSSP_NEGOTIATE_56) ) { pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_56; }
if ( (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_128) && (NegotiateFlagsKeyStrength & NTLMSSP_NEGOTIATE_128) ) { pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_128; }
//
// If the client supplied the Domain Name and User Name,
// and did not request datagram, see if the client is running
// on this local machine.
//
if ( ( (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_DATAGRAM) == 0) && ( (pNegotiateMessage->NegotiateFlags & (NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED| NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED)) == (NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED| NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED) ) ) {
//
// The client must pass the new negotiate message if they pass
// these flags
//
if (cbNegotiateMessage < sizeof(NEGOTIATE_MESSAGE)) { Status DBGCHK = SEC_E_INVALID_TOKEN; }
//
// Convert the names to absolute references so we
// can compare them
//
if (NT_SUCCESS(Status)) { Status DBGCHK = SspConvertRelativeToAbsolute( pNegotiateMessage, cbNegotiateMessage, &pNegotiateMessage->OemDomainName, FALSE, // No special alignment
FALSE, &OemDomainName ); } }
if (NT_SUCCESS(Status)) { Status DBGCHK = SspConvertRelativeToAbsolute( pNegotiateMessage, cbNegotiateMessage, &pNegotiateMessage->OemWorkstationName, FALSE, // No special alignment
FALSE, &OemWorkstationName ); } }
//
// Check if datagram is being negotiated
//
if ( NT_SUCCESS(Status) && ((pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_DATAGRAM) == NTLMSSP_NEGOTIATE_DATAGRAM) ) { pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_DATAGRAM; } } else { //
// No negotiate message. We need to check if the caller is asking
// for datagram.
//
SspiPrint(SSPI_WARN, TEXT("GetChallengeMessage get OLD_NEGOTIATE_MESSAGE\n")) ; if ((ContextReqFlags & ASC_REQ_DATAGRAM) == 0) { Status DBGCHK = SEC_E_INVALID_TOKEN; }
//
// always send target info -- new for NTLM3!
//
if (NT_SUCCESS(Status)) { ChallengeMessageTargetFlags = NTLMSSP_NEGOTIATE_TARGET_INFO;
cbChallengeMessage = sizeof(*pChallengeMessage) + pTargetInfo->Length;
pChallengeMessage = (CHALLENGE_MESSAGE*) new CHAR[cbChallengeMessage];
Status DBGCHK = pChallengeMessage ? S_OK : STATUS_NO_MEMORY; }
//
// Record in the context that we are doing datagram. We will tell
// the client everything we can negotiate and let it decide what
// to negotiate.
//
if (NT_SUCCESS(Status)) { RtlZeroMemory(pChallengeMessage, cbChallengeMessage);
pChallengeMessage->NegotiateFlags = NTLMSSP_NEGOTIATE_DATAGRAM | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_LM_KEY | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_IDENTIFY | NTLMSSP_NEGOTIATE_NTLM2 | NTLMSSP_NEGOTIATE_KEY_EXCH | NegotiateFlagsKeyStrength;
pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; } }
//
// Build the Challenge Message
//
if (NT_SUCCESS(Status)) { strcpy((PSTR) pChallengeMessage->Signature, NTLMSSP_SIGNATURE );
pChallengeMessage->MessageType = NtLmChallenge; RtlCopyMemory( pChallengeMessage->Challenge, ChallengeToClient, MSV1_0_CHALLENGE_LENGTH ); pWhere = (PUCHAR) (pChallengeMessage + 1);
SspCopyStringAsString32(pChallengeMessage, (PSTRING) pTargetName, &pWhere, &pChallengeMessage->TargetName);
SspCopyStringAsString32(pChallengeMessage, (PSTRING)pTargetInfo, &pWhere, &pChallengeMessage->TargetInfo);
pChallengeMessage->NegotiateFlags |= ChallengeMessageTargetFlags;
SspiPrint(SSPI_LOG, TEXT("GetChallengeMessage pNegotiateMessage->NegotiateFlags %#x, pChallengeMessage->NegotiateFlags %#x\n"), pNegotiateMessage->NegotiateFlags, pChallengeMessage->NegotiateFlags); SspiPrintHex(SSPI_LOG, TEXT("pNegotiateMessage"), cbNegotiateMessage, pNegotiateMessage); SspiPrintHex(SSPI_LOG, TEXT("pChallengeMessage"), cbChallengeMessage, pChallengeMessage);
*ppChallengeMessage = pChallengeMessage; pChallengeMessage = NULL; *pContextAttributes = ContextReqFlags; *pcbChallengeMessage = cbChallengeMessage; }
if (pChallengeMessage) { delete [] pChallengeMessage; }
RtlFreeUnicodeString((PUNICODE_STRING) &StringTargetName);
return Status; }
NTSTATUS GetAuthenticateMessage( IN PCredHandle phCredentialHandle, IN ULONG fContextReq, IN PTSTR pszTargetName, IN ULONG TargetDataRep, IN ULONG cbNtlmChallengeMessage, IN OPTIONAL NTLM_CHALLENGE_MESSAGE* pNtlmChallengeMessage, IN ULONG cbChallengeMessage, IN CHALLENGE_MESSAGE* pChallengeMessage, OUT PCtxtHandle phClientContextHandle, OUT ULONG* pfContextAttr, OUT ULONG* pcbAuthMessage, OUT AUTHENTICATE_MESSAGE** ppAuthMessage, OUT NTLM_INITIALIZE_RESPONSE* pInitResponse ) { TNtStatus Status = S_OK;
ULONG fContextAttr = 0; CtxtHandle hClientCtxtHandle;
SecBufferDesc InBuffDesc = {0}; SecBuffer InBuffs[2] = {0}; SecBufferDesc OutBuffDesc = {0}; SecBuffer OutBuffs[2] = {0};
TimeStamp Expiry = {0};
SecInvalidateHandle(&hClientCtxtHandle); SecInvalidateHandle(phClientContextHandle);
InBuffDesc.pBuffers = InBuffs; InBuffDesc.cBuffers = 1; InBuffDesc.ulVersion = 0; InBuffs[0].pvBuffer = pChallengeMessage; InBuffs[0].cbBuffer = cbChallengeMessage; InBuffs[0].BufferType = SECBUFFER_TOKEN;
if ((fContextReq & ISC_REQ_USE_SUPPLIED_CREDS) && (pNtlmChallengeMessage && cbNtlmChallengeMessage)) { InBuffDesc.cBuffers = 2; InBuffs[1].pvBuffer = pNtlmChallengeMessage; InBuffs[1].cbBuffer = cbNtlmChallengeMessage; InBuffs[1].BufferType = SECBUFFER_TOKEN;
if (0 == (fContextReq & ISC_REQ_USE_SUPPLIED_CREDS)) { fContextReq |= ISC_REQ_USE_SUPPLIED_CREDS; SspiPrint(SSPI_WARN, TEXT("Creds supplied but ISC_REQ_USE_SUPPLIED_CREDS was not set, added\n")); } }
OutBuffDesc.pBuffers = OutBuffs; OutBuffDesc.cBuffers = 2; OutBuffDesc.ulVersion = 0;
if (0 == (fContextReq & ISC_REQ_ALLOCATE_MEMORY)) { fContextReq |= ISC_REQ_ALLOCATE_MEMORY; SspiPrint(SSPI_LOG, TEXT("ISC_REQ_ALLOCATE_MEMORY was not set, added\n")); }
OutBuffs[0].pvBuffer = NULL; OutBuffs[0].cbBuffer = 0; OutBuffs[0].BufferType = SECBUFFER_TOKEN; OutBuffs[1].pvBuffer = NULL; OutBuffs[1].cbBuffer = 0; OutBuffs[1].BufferType = SECBUFFER_TOKEN;
SspiPrint(SSPI_LOG, TEXT("GetAuthenticateMessage calling InitializeSecurityContext pszTargetName (%s), fContextReq %#x, TargetDataRep %#x, hCred %#x:%#x\n"), pszTargetName, fContextReq, TargetDataRep, phCredentialHandle->dwUpper, phCredentialHandle->dwLower);
Status DBGCHK = InitializeSecurityContext( phCredentialHandle, NULL, pszTargetName, fContextReq, 0, TargetDataRep, &InBuffDesc, 0, &hClientCtxtHandle, &OutBuffDesc, &fContextAttr, &Expiry );
if (NT_SUCCESS(Status)) { *phClientContextHandle = hClientCtxtHandle; SecInvalidateHandle(&hClientCtxtHandle);
*pfContextAttr = fContextAttr;
*ppAuthMessage = (AUTHENTICATE_MESSAGE *) OutBuffs[0].pvBuffer; OutBuffs[0].pvBuffer = NULL;
*pcbAuthMessage = OutBuffs[0].cbBuffer;
ASSERT(sizeof(*pInitResponse) == OutBuffs[1].cbBuffer); RtlCopyMemory(pInitResponse, OutBuffs[1].pvBuffer, sizeof(*pInitResponse));
SspiPrint(SSPI_LOG, TEXT("ClientCtxtHandle is %#x:%#x, fContextAttr %#x\n"), phClientContextHandle->dwUpper, phClientContextHandle->dwLower, *pfContextAttr);
SspiPrintHex(SSPI_LOG, TEXT("AuthMessage"), *pcbAuthMessage, *ppAuthMessage); SspiPrintHex(SSPI_LOG, TEXT("UserSessionKey"), MSV1_0_USER_SESSION_KEY_LENGTH, pInitResponse->UserSessionKey); SspiPrintHex(SSPI_LOG, TEXT("LanmanSessionKey"), MSV1_0_LANMAN_SESSION_KEY_LENGTH, pInitResponse->LanmanSessionKey);
SspiPrintSysTimeAsLocalTime(SSPI_LOG, TEXT("Expiry"), &Expiry); }
if (OutBuffs[0].pvBuffer) { FreeContextBuffer(OutBuffs[0].pvBuffer); }
if (OutBuffs[1].pvBuffer) { FreeContextBuffer(OutBuffs[1].pvBuffer); }
return Status; }
NTSTATUS MsvChallenge( IN OPTIONAL PTSTR pszCredPrincipal, IN OPTIONAL LUID* pCredLogonID, IN OPTIONAL VOID* pAuthData, IN OEM_STRING* pOemDomainName, IN OEM_STRING* pOemWorkstationName, IN ULONG NegotiateFlags, IN ULONG TargetFlags, IN BOOLEAN bForceGuest, IN ULONG fContextAttr, IN ULONG TargetDataRep, IN UNICODE_STRING* pPassword, IN UNICODE_STRING* pUserName, IN UNICODE_STRING* pDomainName, IN UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH], IN OPTIONAL UNICODE_STRING* pDnsDomainName, IN OPTIONAL UNICODE_STRING* pDnsComputerName, IN OPTIONAL UNICODE_STRING* pDnsTreeName, IN OPTIONAL UNICODE_STRING* pComputerName, IN OPTIONAL UNICODE_STRING* pComputerDomainName, OUT ULONG* pcbAuthMessage, OUT AUTHENTICATE_MESSAGE** ppAuthMessage, OUT PCtxtHandle phCliCtxt, OUT ULONG* pfContextAttr ) {
TNtStatus Status; UNICODE_STRING TargetInfo = {0};
WCHAR ScratchBuffer[2 * DNS_MAX_NAME_LENGTH + 2] = {0}; UNICODE_STRING TargetName = {0, sizeof(ScratchBuffer), ScratchBuffer};
NTLM_CHALLENGE_MESSAGE* pNtlmChallengeMessage = NULL; ULONG cbNtlmChallengeMessage = 0;
NEGOTIATE_MESSAGE* pNegotiateMessage = NULL; ULONG cbNegotiateMessage = 0;
CHALLENGE_MESSAGE* pChallengeMesssage = NULL; ULONG cbChallengeMessage = 0;
AUTHENTICATE_MESSAGE* pAuthMessage = NULL; ULONG cbAuthMessage = 0;
NTLM_INITIALIZE_RESPONSE InitResponse = {0};
CtxtHandle hCliCtxt; CredHandle hCliCred;
SecInvalidateHandle(&hCliCred); SecInvalidateHandle(&hCliCtxt);
*pfContextAttr = 0; SecInvalidateHandle(phCliCtxt); *ppAuthMessage = NULL; *pcbAuthMessage = 0;
SspiPrint(SSPI_LOG, TEXT("MsvChallenge CredPrincipal %s, NegotiateFlags %#x, TargetFlags %#x, bForceGuest %#x") TEXT("fContextAttr %#x, TargetDataRep %#x, pAuthData %p, pCredLogonID %p\n"), pszCredPrincipal, NegotiateFlags, TargetFlags, bForceGuest, fContextAttr, TargetDataRep, pAuthData, pCredLogonID); DebugPrintf(SSPI_LOG, "OemDomainName (%s), OemWorkstation (%s)\n", pOemDomainName, pOemWorkstationName); SspiPrintHex(SSPI_LOG, TEXT("ChallengeToClient"), MSV1_0_CHALLENGE_LENGTH, ChallengeToClient); SspiPrint(SSPI_LOG, TEXT("pPassword %wZ, pUserName %wZ, pDomainName %wZ, pDnsDomainName %wZ, pDnsComputerName %wZ, pDnsTreeName %wZ, pComputerName %wZ, pComputerDomainName %wZ\n"), pPassword, pUserName, pDomainName, pDnsDomainName, pDnsComputerName, pDnsTreeName, pComputerName, pComputerDomainName);
if (pComputerDomainName && pComputerDomainName->Length) { //
// Target name is of form "domain name\0computer name"
//
RtlCopyMemory(ScratchBuffer, pComputerDomainName->Buffer, pComputerDomainName->Length); if (pComputerName && pComputerName->Length) { RtlCopyMemory(ScratchBuffer + (pComputerDomainName->Length / sizeof(WCHAR)) + 1, pComputerName->Buffer, pComputerName->Length);
TargetName.Length = pComputerDomainName->Length + pComputerName->Length + 1; } else { TargetName.Length = pComputerDomainName->Length; } } else if (pComputerName && pComputerName->Length) { RtlCopyMemory(ScratchBuffer, pComputerName->Buffer, pComputerName->Length); TargetName.Length = pComputerName->Length; }
SspiPrintHex(SSPI_LOG, TEXT("MsvChallenge TargetName"), TargetName.Length, TargetName.Buffer);
Status DBGCHK = GetNegociateMessage( pOemDomainName, pOemWorkstationName, NegotiateFlags, &cbNegotiateMessage, &pNegotiateMessage );
if (NT_SUCCESS(Status)) { Status DBGCHK = GetTargetInfo( TargetFlags, bForceGuest, pDnsDomainName, pDnsComputerName, pDnsTreeName, &TargetName, pComputerName, &TargetInfo ); }
if (NT_SUCCESS(Status)) { Status DBGCHK = GetChallengeMessage( fContextAttr, cbNegotiateMessage, TargetFlags, &TargetInfo, &TargetName, pNegotiateMessage, ChallengeToClient, &cbChallengeMessage, &pChallengeMesssage, &fContextAttr ); }
if (NT_SUCCESS(Status) && ((pPassword && pPassword->Length) || (pDomainName && pDomainName->Length) || (pUserName && pUserName->Length))) { if (0 == (fContextAttr & ISC_REQ_USE_SUPPLIED_CREDS)) { SspiPrint(SSPI_WARN, TEXT("MsvChallenge explicit cred supplied, but ISC_REQ_USE_SUPPLIED_CREDS was not set, added\n")); fContextAttr |= ISC_REQ_USE_SUPPLIED_CREDS; }
Status DBGCHK = GetNtlmChallengeMessage( pPassword, pUserName, pDomainName, &cbNtlmChallengeMessage, &pNtlmChallengeMessage ); }
if (NT_SUCCESS(Status)) { Status DBGCHK = GetCredHandle( pszCredPrincipal, pCredLogonID, TEXT("NTLM"), pAuthData, SECPKG_CRED_OUTBOUND, &hCliCred ); }
#if defined(UNICODE) || defined(_UNICODE)
if (NT_SUCCESS(Status)) { SspiPrint(SSPI_LOG, TEXT("MsvChallenge hCliCred %#x:%#x\n"), hCliCred.dwUpper, hCliCred.dwLower);
Status DBGCHK = GetAuthenticateMessage( &hCliCred, fContextAttr, TargetName.Buffer, TargetDataRep, cbNtlmChallengeMessage, pNtlmChallengeMessage, cbChallengeMessage, pChallengeMesssage, &hCliCtxt, &fContextAttr, &cbAuthMessage, &pAuthMessage, &InitResponse ); }
#else
ANSI_STRING AnsiTargetName = {0};
//
// RtlUnicodeStringToAnsiString appends the NULL
//
if (NT_SUCCESS(Status)) { Status DBGCHK = RtlUnicodeStringToAnsiString(&AnsiTargetName, &TargetName, TRUE); }
if (NT_SUCCESS(Status)) { SspiPrint(SSPI_LOG, TEXT("MsvChallenge hCliCred %#x:%#x\n"), hCliCred.dwUpper, hCliCred.dwLower);
Status DBGCHK = GetAuthenticateMessage( &hCliCred, fContextAttr, AnsiTargetName.Buffer, TargetDataRep, cbNtlmChallengeMessage, pNtlmChallengeMessage, cbChallengeMessage, pChallengeMesssage, &hCliCtxt, &fContextAttr, &cbAuthMessage, &pAuthMessage, &InitResponse ); }
RtlFreeAnsiString(&AnsiTargetName);
#endif
if (NT_SUCCESS(Status)) { *phCliCtxt = hCliCtxt; SecInvalidateHandle(&hCliCtxt); *ppAuthMessage = pAuthMessage;
pAuthMessage = NULL; *pcbAuthMessage = cbAuthMessage; *pfContextAttr = fContextAttr; }
if (SecIsValidHandle(&hCliCtxt)) { DeleteSecurityContext(&hCliCtxt); }
if (SecIsValidHandle(&hCliCred)) { DeleteSecurityContext(&hCliCred); }
if (pAuthMessage) { FreeContextBuffer(pAuthMessage); }
if (pNegotiateMessage) { delete[] pNegotiateMessage; }
if (pChallengeMesssage) { delete [] pChallengeMesssage; }
if (pNtlmChallengeMessage) { delete [] pNtlmChallengeMessage; }
return Status; }
NTSTATUS GetAuthenticateResponse( IN PCredHandle pServerCredHandle, IN ULONG fContextAttr, IN ULONG TargetDataRep, IN ULONG cbAuthMessage, IN AUTHENTICATE_MESSAGE* pAuthMessage, IN NTLM_AUTHENTICATE_MESSAGE* pNtlmAuthMessage, OUT PCtxtHandle phServerCtxtHandle, OUT ULONG* pfContextAttr, OUT NTLM_ACCEPT_RESPONSE* pAcceptResponse ) {
TNtStatus Status = STATUS_SUCCESS;
CtxtHandle hServerCtxtHandle;
SecBufferDesc InBuffDesc = {0}; SecBuffer InBuffs[2] = {0}; SecBufferDesc OutBuffDesc = {0}; SecBuffer OutBuff = {0};
TimeStamp Expiry = {0};
SecInvalidateHandle(&hServerCtxtHandle); SecInvalidateHandle(phServerCtxtHandle);
InBuffDesc.pBuffers = InBuffs; InBuffDesc.cBuffers = 2; InBuffDesc.ulVersion = 0; InBuffs[0].pvBuffer = pAuthMessage; InBuffs[0].cbBuffer = cbAuthMessage; InBuffs[0].BufferType = SECBUFFER_TOKEN; InBuffs[1].pvBuffer = pNtlmAuthMessage; InBuffs[1].cbBuffer = sizeof(*pNtlmAuthMessage); InBuffs[1].BufferType = SECBUFFER_TOKEN;
OutBuffDesc.pBuffers = &OutBuff; OutBuffDesc.cBuffers = 1; OutBuffDesc.ulVersion = 0; OutBuff.pvBuffer = pAcceptResponse; OutBuff.cbBuffer = sizeof(*pAcceptResponse); OutBuff.BufferType = SECBUFFER_TOKEN;
if (fContextAttr & ASC_REQ_ALLOCATE_MEMORY) { SspiPrint(SSPI_WARN, TEXT("Authenticate ASC_REQ_ALLOCATE_MEMORY was set, removed\n")); fContextAttr &= ~(ASC_REQ_ALLOCATE_MEMORY); }
SspiPrint(SSPI_LOG, TEXT("GetAuthenticateResponse calling AcceptSecurityContext fContextAttr %#x, TargetDataRep %#x, hCred %#x:%#x\n"), fContextAttr, TargetDataRep, pServerCredHandle->dwUpper, pServerCredHandle->dwLower);
Status DBGCHK = AcceptSecurityContext( pServerCredHandle, NULL, &InBuffDesc, fContextAttr, TargetDataRep, &hServerCtxtHandle, &OutBuffDesc, &fContextAttr, &Expiry ); if (NT_SUCCESS(Status)) { *phServerCtxtHandle = hServerCtxtHandle; SecInvalidateHandle(&hServerCtxtHandle); *pfContextAttr = fContextAttr;
ASSERT(sizeof(*pAcceptResponse) == OutBuff.cbBuffer); RtlCopyMemory(pAcceptResponse, OutBuff.pvBuffer, sizeof(*pAcceptResponse));
SspiPrint(SSPI_LOG, TEXT("ServerCtxtHandle is %#x:%#x, fContextAttr %#x\n"), phServerCtxtHandle->dwUpper, phServerCtxtHandle->dwLower, *pfContextAttr);
SspiPrint(SSPI_LOG, TEXT("Authenticate LogonId %#x:%#x, UserFlags %#x\n"), pAcceptResponse->LogonId.HighPart, pAcceptResponse->LogonId.LowPart, pAcceptResponse->UserFlags); SspiPrintSysTimeAsLocalTime(SSPI_LOG, TEXT("KickoffTime"), &pAcceptResponse->KickoffTime); SspiPrintHex(SSPI_LOG, TEXT("UserSessionKey"), MSV1_0_USER_SESSION_KEY_LENGTH, pAcceptResponse->UserSessionKey); SspiPrintHex(SSPI_LOG, TEXT("LanmanSessionKey"), MSV1_0_LANMAN_SESSION_KEY_LENGTH, pAcceptResponse->LanmanSessionKey); SspiPrintSysTimeAsLocalTime(SSPI_LOG, TEXT("Expiry"), &Expiry); }
if (SecIsValidHandle(&hServerCtxtHandle)) { DeleteSecurityContext(&hServerCtxtHandle); }
return Status; }
NTSTATUS MsvAuthenticate( IN OPTIONAL PTSTR pszCredPrincipal, IN OPTIONAL LUID* pCredLogonID, IN OPTIONAL VOID* pAuthData, IN ULONG fContextAttr, IN ULONG TargetDataRep, IN ULONG cbAuthMessage, IN AUTHENTICATE_MESSAGE* pAuthMessage, IN NTLM_AUTHENTICATE_MESSAGE* pNtlmAuthMessage, OUT PCtxtHandle phServerCtxt, OUT ULONG* pfContextAttr ) { TNtStatus Status;
CredHandle hServerCred; CtxtHandle hServerCtxt;
NTLM_ACCEPT_RESPONSE AcceptResponse = {0};
SecInvalidateHandle(&hServerCred); SecInvalidateHandle(&hServerCtxt);
SspiPrint(SSPI_LOG, TEXT("MsvAuthenticate pszCredPrincipal %s, fContextAttr %#x, TargetDataRep %#x, pCredLogonID %p, pAuthData %p\n"), pszCredPrincipal, fContextAttr, TargetDataRep, pCredLogonID, pAuthData); SspiPrintHex(SSPI_LOG, TEXT("pAuthMessage"), cbAuthMessage, pAuthMessage); SspiPrintHex(SSPI_LOG, TEXT("pNtlmAuthMessage->ChallengeToClient"), MSV1_0_CHALLENGE_LENGTH, pNtlmAuthMessage->ChallengeToClient); SspiPrint(SSPI_LOG, TEXT("pNtlmAuthMessage->ParameterControl %#x\n"), pNtlmAuthMessage->ParameterControl);
Status DBGCHK = GetCredHandle( pszCredPrincipal, pCredLogonID, TEXT("NTLM"), pAuthData, SECPKG_CRED_INBOUND, &hServerCred );
if (NT_SUCCESS(Status)) { Status DBGCHK = GetAuthenticateResponse( &hServerCred, fContextAttr, TargetDataRep, cbAuthMessage, pAuthMessage, pNtlmAuthMessage, &hServerCtxt, &fContextAttr, &AcceptResponse ); }
if (NT_SUCCESS(Status)) { *pfContextAttr = fContextAttr; *phServerCtxt = hServerCtxt; SecInvalidateHandle(&hServerCtxt); }
if (SecIsValidHandle(&hServerCtxt)) { DeleteSecurityContext(&hServerCtxt); }
if (SecIsValidHandle(&hServerCred)) { FreeCredentialsHandle(&hServerCred); }
return Status; }
|