Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1163 lines
36 KiB

/*++
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;
}