|
|
//+-----------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (c) Microsoft Corporation 1992 - 1994
//
// File: stubs.cxx
//
// Contents: user-mode stubs for security API
//
//
// History: 3/5/94 MikeSw Created
//
//------------------------------------------------------------------------
#include <sspdrv.h>
#pragma alloc_text(PAGE, AcquireCredentialsHandleW)
#pragma alloc_text(PAGE, FreeCredentialsHandle)
#pragma alloc_text(PAGE, InitializeSecurityContextW)
#pragma alloc_text(PAGE, AcceptSecurityContext)
#pragma alloc_text(PAGE, DeleteSecurityContext)
#pragma alloc_text(PAGE, ApplyControlToken)
#pragma alloc_text(PAGE, EnumerateSecurityPackagesW)
#pragma alloc_text(PAGE, QuerySecurityPackageInfoW)
#pragma alloc_text(PAGE, FreeContextBuffer)
static CtxtHandle NullContext = {0,0}; static CredHandle NullCredential = {0,0}; static LUID lFake = {0, 0}; static SECURITY_STRING sFake = {0, 0, NULL}; static TOKEN_SOURCE KsecTokenSource = {"KSecDD", {0, 0} };
#define NTLMSSP_REQUIRED_NEGOTIATE_FLAGS ( NTLMSSP_NEGOTIATE_UNICODE | \
NTLMSSP_REQUEST_INIT_RESPONSE )
//+-------------------------------------------------------------------------
//
// Function: AcquireCredentialsHandleW
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleW( PSECURITY_STRING pssPrincipal, // Name of principal
PSECURITY_STRING pssPackageName, // Name of package
unsigned long fCredentialUse, // Flags indicating use
void SEC_FAR * pvLogonId, // Pointer to logon ID
void SEC_FAR * pAuthData, // Package specific data
SEC_GET_KEY_FN pGetKeyFn, // Pointer to GetKey() func
void SEC_FAR * pvGetKeyArgument, // Value to pass to GetKey()
PCredHandle phCredential, // (out) Cred Handle
PTimeStamp ptsExpiry // (out) Lifetime (optional)
) { SECURITY_STATUS scRet; SECURITY_STRING Principal; TimeStamp OptionalTimeStamp; UNICODE_STRING PackageName;
PAGED_CODE();
if (!pssPackageName) { return(SEC_E_SECPKG_NOT_FOUND); }
//
// We don't accept principal names either.
//
if (pssPrincipal) { return(SEC_E_UNKNOWN_CREDENTIALS); }
//
// Make sure they want the NTLM security package
//
RtlInitUnicodeString( &PackageName, NTLMSP_NAME );
if (!RtlEqualUnicodeString( pssPackageName, &PackageName, TRUE)) { return(SEC_E_SECPKG_NOT_FOUND); }
//
// The credential handle is the logon id
//
if (fCredentialUse & SECPKG_CRED_OUTBOUND) { if (pvLogonId != NULL) { *phCredential = *(PCredHandle) pvLogonId; } else { return(SEC_E_UNKNOWN_CREDENTIALS); }
} else if (fCredentialUse & SECPKG_CRED_INBOUND) { //
// For inbound credentials, we will accept a logon id but
// we don't require it.
//
if (pvLogonId != NULL) { *phCredential = *(PCredHandle) pvLogonId; } else { *phCredential = NullCredential; }
} else { return(SEC_E_UNSUPPORTED_FUNCTION); }
return(SEC_E_OK);
}
//+-------------------------------------------------------------------------
//
// Function: FreeCredentialsHandle
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY FreeCredentialsHandle( PCredHandle phCredential // Handle to free
) { PAGED_CODE();
//
// Since the credential handle is just the LogonId, do nothing.
//
return(SEC_E_OK); }
VOID PutString( OUT PSTRING Destination, IN PSTRING Source, IN PVOID Base, IN OUT PUCHAR * Where ) { Destination->Buffer = (PCHAR) *Where - (ULONG) Base; Destination->Length = Source->Length; Destination->MaximumLength = Source->Length;
RtlCopyMemory( *Where, Source->Buffer, Source->Length ); *Where += Source->Length; }
//+-------------------------------------------------------------------------
//
// Function: InitializeSecurityContextW
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY InitializeSecurityContextW( PCredHandle phCredential, // Cred to base context
PCtxtHandle phContext, // Existing context (OPT)
PSECURITY_STRING pssTargetName, // Name of target
unsigned long fContextReq, // Context Requirements
unsigned long Reserved1, // Reserved, MBZ
unsigned long TargetDataRep, // Data rep of target
PSecBufferDesc pInput, // Input Buffers
unsigned long Reserved2, // Reserved, MBZ
PCtxtHandle phNewContext, // (out) New Context handle
PSecBufferDesc pOutput, // (inout) Output Buffers
unsigned long SEC_FAR * pfContextAttr, // (out) Context attrs
PTimeStamp ptsExpiry // (out) Life span (OPT)
) { SECURITY_STATUS scRet; PMSV1_0_GETCHALLENRESP_REQUEST ChallengeRequest = NULL; ULONG ChallengeRequestSize; PMSV1_0_GETCHALLENRESP_RESPONSE ChallengeResponse = NULL; ULONG ChallengeResponseSize; PCHALLENGE_MESSAGE ChallengeMessage = NULL; ULONG ChallengeMessageSize; PNTLM_CHALLENGE_MESSAGE NtlmChallengeMessage = NULL; ULONG NtlmChallengeMessageSize; PAUTHENTICATE_MESSAGE AuthenticateMessage = NULL; ULONG AuthenticateMessageSize; PNTLM_INITIALIZE_RESPONSE NtlmInitializeResponse = NULL; PClient Client = NULL; UNICODE_STRING PasswordToUse; UNICODE_STRING UserNameToUse; UNICODE_STRING DomainNameToUse; ULONG ParameterControl = USE_PRIMARY_PASSWORD | RETURN_PRIMARY_USERNAME | RETURN_PRIMARY_LOGON_DOMAINNAME;
NTSTATUS FinalStatus = STATUS_SUCCESS; PUCHAR Where; PSecBuffer AuthenticationToken = NULL; PSecBuffer InitializeResponseToken = NULL; BOOLEAN UseSuppliedCreds = FALSE;
PAGED_CODE();
RtlInitUnicodeString( &PasswordToUse, NULL );
RtlInitUnicodeString( &UserNameToUse, NULL );
RtlInitUnicodeString( &DomainNameToUse, NULL );
//
// Check for valid sizes, pointers, etc.:
//
if (!phCredential) { return(SEC_E_INVALID_HANDLE); }
//
// Check that we can indeed call the LSA and get the client
// handle to it.
//
scRet = IsOkayToExec(&Client); if (!NT_SUCCESS(scRet)) { return(scRet); }
//
// Locate the buffers with the input data
//
if (!GetTokenBuffer( pInput, 0, // get the first security token
(PVOID *) &ChallengeMessage, &ChallengeMessageSize, TRUE // may be readonly
)) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; }
//
// If we are using supplied creds, get them now too.
//
if (fContextReq & ISC_REQ_USE_SUPPLIED_CREDS) { if (!GetTokenBuffer( pInput, 1, // get the second security token
(PVOID *) &NtlmChallengeMessage, &NtlmChallengeMessageSize, TRUE // may be readonly
)) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; } else { UseSuppliedCreds = TRUE; }
}
//
// Get the output tokens
//
if (!GetSecurityToken( pOutput, 0, &AuthenticationToken) || !GetSecurityToken( pOutput, 1, &InitializeResponseToken ) ) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; }
//
// Make sure the sizes are o.k.
//
if ((ChallengeMessageSize < sizeof(CHALLENGE_MESSAGE)) || (UseSuppliedCreds && !(NtlmChallengeMessageSize < sizeof(NTLM_CHALLENGE_MESSAGE)))) { scRet = SEC_E_INVALID_TOKEN; }
//
// Make sure the caller wants us to allocate memory:
//
if (!(fContextReq & ISC_REQ_ALLOCATE_MEMORY)) { scRet = SEC_E_UNSUPPORTED_FUNCTION; goto Cleanup; }
//
// BUGBUG: allow calls requesting PROMPT_FOR_CREDS to go through.
// We won't prompt, but we will setup a context properly.
//
// if ((fContextReq & ISC_REQ_PROMPT_FOR_CREDS) != 0)
// {
// scRet = SEC_E_UNSUPPORTED_FUNCTION;
// goto Cleanup;
// }
//
// Verify the validity of the challenge message.
//
if (strncmp( ChallengeMessage->Signature, NTLMSSP_SIGNATURE, sizeof(NTLMSSP_SIGNATURE))) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; }
if (ChallengeMessage->MessageType != NtLmChallenge) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; }
if (ChallengeMessage->NegotiateFlags & NTLMSSP_REQUIRED_NEGOTIATE_FLAGS != NTLMSSP_REQUIRED_NEGOTIATE_FLAGS) { scRet = SEC_E_UNSUPPORTED_FUNCTION; goto Cleanup; }
if ((ChallengeMessage->NegotiateFlags & NTLMSSP_REQUEST_NON_NT_SESSION_KEY) != 0) { ParameterControl |= RETURN_NON_NT_USER_SESSION_KEY; }
if ((fContextReq & ISC_REQ_USE_SUPPLIED_CREDS) != 0) { if ( NtlmChallengeMessage->Password.Buffer != NULL) { ParameterControl &= ~USE_PRIMARY_PASSWORD; PasswordToUse = NtlmChallengeMessage->Password; PasswordToUse.Buffer = (LPWSTR) ((PCHAR) PasswordToUse.Buffer + (ULONG) NtlmChallengeMessage); }
if (NtlmChallengeMessage->UserName.Length != 0) { UserNameToUse = NtlmChallengeMessage->UserName; UserNameToUse.Buffer = (LPWSTR) ((PCHAR) UserNameToUse.Buffer + (ULONG) NtlmChallengeMessage); ParameterControl &= ~RETURN_PRIMARY_USERNAME; } if (NtlmChallengeMessage->DomainName.Length != 0) { DomainNameToUse = NtlmChallengeMessage->DomainName; DomainNameToUse.Buffer = (LPWSTR) ((PCHAR) DomainNameToUse.Buffer + (ULONG) NtlmChallengeMessage); ParameterControl &= ~RETURN_PRIMARY_LOGON_DOMAINNAME; }
}
//
// Package up the parameter for a call to the LSA.
//
ChallengeRequestSize = sizeof(MSV1_0_GETCHALLENRESP_REQUEST) + PasswordToUse.Length;
scRet = ZwAllocateVirtualMemory( NtCurrentProcess(), &ChallengeRequest, 0L, &ChallengeRequestSize, MEM_COMMIT, PAGE_READWRITE ); if (!NT_SUCCESS(scRet)) { goto Cleanup; }
//
// Build the challenge request message.
//
ChallengeRequest->MessageType = MsV1_0Lm20GetChallengeResponse; ChallengeRequest->ParameterControl = ParameterControl; ChallengeRequest->LogonId = * (PLUID) phCredential; RtlCopyMemory( ChallengeRequest->ChallengeToClient, ChallengeMessage->Challenge, MSV1_0_CHALLENGE_LENGTH ); if ((ParameterControl & USE_PRIMARY_PASSWORD) == 0) { ChallengeRequest->Password.Buffer = (LPWSTR) (ChallengeRequest+1); RtlCopyMemory( ChallengeRequest->Password.Buffer, PasswordToUse.Buffer, PasswordToUse.Length ); ChallengeRequest->Password.Length = PasswordToUse.Length; ChallengeRequest->Password.MaximumLength = PasswordToUse.Length; }
//
// Call the LSA to get the challenge response.
//
scRet = LsaCallAuthenticationPackage( Client->hPort, PackageId, ChallengeRequest, ChallengeRequestSize, &ChallengeResponse, &ChallengeResponseSize, &FinalStatus ); if (!NT_SUCCESS(scRet)) { goto Cleanup; } if (!NT_SUCCESS(FinalStatus)) { scRet = FinalStatus; goto Cleanup; }
ASSERT(ChallengeResponse->MessageType == MsV1_0Lm20GetChallengeResponse); //
// Now prepare the output message.
//
if (UserNameToUse.Buffer == NULL) { UserNameToUse = ChallengeResponse->UserName; } if (DomainNameToUse.Buffer == NULL) { DomainNameToUse = ChallengeResponse->LogonDomainName; }
AuthenticateMessageSize = sizeof(AUTHENTICATE_MESSAGE) + UserNameToUse.Length + DomainNameToUse.Length + ChallengeResponse->CaseSensitiveChallengeResponse.Length + ChallengeResponse->CaseInsensitiveChallengeResponse.Length;
//
// BUGBUG: where do I get the workstation name from?
//
AuthenticateMessage = (PAUTHENTICATE_MESSAGE) SecAllocate(AuthenticateMessageSize); if (AuthenticateMessage == NULL) { scRet = SEC_E_INSUFFICIENT_MEMORY; goto Cleanup; }
Where = (PUCHAR) (AuthenticateMessage + 1); RtlCopyMemory( AuthenticateMessage->Signature, NTLMSSP_SIGNATURE, sizeof(NTLMSSP_SIGNATURE) ); AuthenticateMessage->MessageType = NtLmAuthenticate;
PutString( &AuthenticateMessage->LmChallengeResponse, &ChallengeResponse->CaseInsensitiveChallengeResponse, AuthenticateMessage, &Where );
PutString( &AuthenticateMessage->NtChallengeResponse, &ChallengeResponse->CaseSensitiveChallengeResponse, AuthenticateMessage, &Where );
PutString( &AuthenticateMessage->DomainName, (PSTRING) &DomainNameToUse, AuthenticateMessage, &Where );
PutString( &AuthenticateMessage->UserName, (PSTRING) &UserNameToUse, AuthenticateMessage, &Where );
//
// BUGBUG: no workstation name to fill in.
//
AuthenticateMessage->Workstation.Length = 0; AuthenticateMessage->Workstation.MaximumLength = 0; AuthenticateMessage->Workstation.Buffer = NULL;
//
// Build the initialize response.
//
NtlmInitializeResponse = (PNTLM_INITIALIZE_RESPONSE) SecAllocate(sizeof(NTLM_INITIALIZE_RESPONSE)); if (NtlmInitializeResponse == NULL) { scRet = SEC_E_INSUFFICIENT_MEMORY; goto Cleanup; }
RtlCopyMemory( NtlmInitializeResponse->UserSessionKey, ChallengeResponse->UserSessionKey, MSV1_0_USER_SESSION_KEY_LENGTH );
RtlCopyMemory( NtlmInitializeResponse->LanmanSessionKey, ChallengeResponse->LanmanSessionKey, MSV1_0_LANMAN_SESSION_KEY_LENGTH );
//
// Fill in the output buffers now.
//
AuthenticationToken->pvBuffer = AuthenticateMessage; AuthenticationToken->cbBuffer = AuthenticateMessageSize; InitializeResponseToken->pvBuffer = NtlmInitializeResponse; InitializeResponseToken->cbBuffer = sizeof(NTLM_INITIALIZE_RESPONSE);
//
// Make a local context for this
//
scRet = NtlmInitKernelContext( NtlmInitializeResponse->UserSessionKey, NtlmInitializeResponse->LanmanSessionKey, NULL, // no token,
phNewContext );
if (!NT_SUCCESS(scRet)) { goto Cleanup; } scRet = SEC_E_OK;
Cleanup:
if (ChallengeRequest != NULL) { ZwFreeVirtualMemory( NtCurrentProcess(), &ChallengeRequest, &ChallengeRequestSize, MEM_RELEASE ); }
if (ChallengeResponse != NULL) { LsaFreeReturnBuffer( ChallengeResponse ); }
if (!NT_SUCCESS(scRet)) { if (AuthenticateMessage != NULL) { SecFree(AuthenticateMessage); } if (NtlmInitializeResponse != NULL) { SecFree(NtlmInitializeResponse); } } return(scRet); }
//+-------------------------------------------------------------------------
//
// Function: AcceptSecurityContext
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY AcceptSecurityContext( PCredHandle phCredential, // Cred to base context
PCtxtHandle phContext, // Existing context (OPT)
PSecBufferDesc pInput, // Input buffer
unsigned long fContextReq, // Context Requirements
unsigned long TargetDataRep, // Target Data Rep
PCtxtHandle phNewContext, // (out) New context handle
PSecBufferDesc pOutput, // (inout) Output buffers
unsigned long SEC_FAR * pfContextAttr, // (out) Context attributes
PTimeStamp ptsExpiry // (out) Life span (OPT)
) { SECURITY_STATUS scRet; NTSTATUS SubStatus; PAUTHENTICATE_MESSAGE AuthenticateMessage; ULONG AuthenticateMessageSize; PNTLM_AUTHENTICATE_MESSAGE NtlmAuthenticateMessage; ULONG NtlmAuthenticateMessageSize; PNTLM_ACCEPT_RESPONSE NtlmAcceptResponse = NULL; PMSV1_0_LM20_LOGON LogonBuffer = NULL; ULONG LogonBufferSize; PMSV1_0_LM20_LOGON_PROFILE LogonProfile = NULL; ULONG LogonProfileSize; PSecBuffer AcceptResponseToken = NULL; PClient Client = NULL; ANSI_STRING SourceName; LUID LogonId; LUID UNALIGNED * TempLogonId; LARGE_INTEGER UNALIGNED * TempKickoffTime; HANDLE TokenHandle = NULL; QUOTA_LIMITS Quotas; PUCHAR Where; STRING DomainName; STRING UserName; STRING Workstation; STRING NtChallengeResponse; STRING LmChallengeResponse; ULONG EffectivePackageId;
RtlInitString( &SourceName, NULL );
PAGED_CODE();
//
// Check for valid sizes, pointers, etc.:
//
if (!phCredential) { return(SEC_E_INVALID_HANDLE); }
//
// Check that we can indeed call the LSA and get the client
// handle to it.
//
scRet = IsOkayToExec(&Client); if (!NT_SUCCESS(scRet)) { return(scRet); }
//
// Locate the buffers with the input data
//
if (!GetTokenBuffer( pInput, 0, // get the first security token
(PVOID *) &AuthenticateMessage, &AuthenticateMessageSize, TRUE // may be readonly
) || (!GetTokenBuffer( pInput, 1, // get the second security token
(PVOID *) &NtlmAuthenticateMessage, &NtlmAuthenticateMessageSize, TRUE // may be readonly
))) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; }
//
// Get the output tokens
//
if (!GetSecurityToken( pOutput, 0, &AcceptResponseToken ) ) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; }
//
// Make sure the sizes are o.k.
//
if ((AuthenticateMessageSize < sizeof(AUTHENTICATE_MESSAGE)) || (NtlmAuthenticateMessageSize < sizeof(NTLM_AUTHENTICATE_MESSAGE))) { scRet = SEC_E_INVALID_TOKEN; }
//
// Make sure the caller does not want us to allocate memory:
//
if (fContextReq & ISC_REQ_ALLOCATE_MEMORY) { scRet = SEC_E_UNSUPPORTED_FUNCTION; goto Cleanup; }
if (AcceptResponseToken->cbBuffer < sizeof(NTLM_ACCEPT_RESPONSE)) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; }
//
// Verify the validity of the Authenticate message.
//
if (strncmp( AuthenticateMessage->Signature, NTLMSSP_SIGNATURE, sizeof(NTLMSSP_SIGNATURE))) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; }
if (AuthenticateMessage->MessageType != NtLmAuthenticate) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; }
//
// Fixup the buffer pointers
//
UserName = AuthenticateMessage->UserName; UserName.Buffer = UserName.Buffer + (ULONG) AuthenticateMessage;
DomainName = AuthenticateMessage->DomainName; DomainName.Buffer = DomainName.Buffer + (ULONG) AuthenticateMessage;
Workstation = AuthenticateMessage->Workstation; Workstation.Buffer = Workstation.Buffer + (ULONG) AuthenticateMessage;
NtChallengeResponse = AuthenticateMessage->NtChallengeResponse; NtChallengeResponse.Buffer = NtChallengeResponse.Buffer + (ULONG) AuthenticateMessage;
LmChallengeResponse = AuthenticateMessage->LmChallengeResponse; LmChallengeResponse.Buffer = LmChallengeResponse.Buffer + (ULONG) AuthenticateMessage;
//
// Allocate a buffer to pass into LsaLogonUser
//
LogonBufferSize = sizeof(MSV1_0_LM20_LOGON) + UserName.Length + DomainName.Length + Workstation.Length + LmChallengeResponse.Length + NtChallengeResponse.Length;
scRet = ZwAllocateVirtualMemory( NtCurrentProcess(), &LogonBuffer, 0L, &LogonBufferSize, MEM_COMMIT, PAGE_READWRITE );
if (!NT_SUCCESS(scRet)) { goto Cleanup; }
//
// Fill in the fixed-length portions
//
LogonBuffer->MessageType = MsV1_0NetworkLogon;
RtlCopyMemory( LogonBuffer->ChallengeToClient, NtlmAuthenticateMessage->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH );
//
// Fill in the variable length pieces
//
Where = (PUCHAR) (LogonBuffer + 1);
PutString( (PSTRING) &LogonBuffer->LogonDomainName, &DomainName, 0, &Where );
PutString( (PSTRING) &LogonBuffer->UserName, &UserName, 0, &Where );
PutString( (PSTRING) &LogonBuffer->Workstation, &Workstation, 0, &Where );
PutString( (PSTRING) &LogonBuffer->CaseSensitiveChallengeResponse, &NtChallengeResponse, 0, &Where );
PutString( (PSTRING) &LogonBuffer->CaseInsensitiveChallengeResponse, &LmChallengeResponse, 0, &Where );
LogonBuffer->ParameterControl = MSV1_0_CLEARTEXT_PASSWORD_ALLOWED | NtlmAuthenticateMessage->ParameterControl;
scRet = RtlUnicodeStringToAnsiString( &SourceName, (PUNICODE_STRING) &Workstation, TRUE );
if (!NT_SUCCESS(scRet)) { goto Cleanup; }
if ( fContextReq & ASC_REQ_LICENSING ) { EffectivePackageId = PackageId | LSA_CALL_LICENSE_SERVER ; } else { EffectivePackageId = PackageId ; }
scRet = LsaLogonUser( Client->hPort, &SourceName, Network, EffectivePackageId, LogonBuffer, LogonBufferSize, NULL, // token groups
&KsecTokenSource, (PVOID *) &LogonProfile, &LogonProfileSize, &LogonId, &TokenHandle, &Quotas, &SubStatus );
if (scRet == STATUS_ACCOUNT_RESTRICTION) { scRet = SubStatus; } if (!NT_SUCCESS(scRet)) { //
// LsaLogonUser returns garbage for the token if it fails,
// so zero it now so we don't try to close it later.
//
TokenHandle = NULL; goto Cleanup; }
//
// Create the kernel context
//
scRet = NtlmInitKernelContext( LogonProfile->UserSessionKey, LogonProfile->LanmanSessionKey, TokenHandle, phNewContext );
if (!NT_SUCCESS(scRet)) { goto Cleanup; }
TokenHandle = NULL;
//
// Allocate the return buffer.
//
NtlmAcceptResponse = (PNTLM_ACCEPT_RESPONSE) AcceptResponseToken->pvBuffer; if (NtlmAcceptResponse == NULL) { scRet = SEC_E_INSUFFICIENT_MEMORY; goto Cleanup; }
TempLogonId = (LUID UNALIGNED *) &NtlmAcceptResponse->LogonId; *TempLogonId = LogonId; NtlmAcceptResponse->UserFlags = LogonProfile->UserFlags;
RtlCopyMemory( NtlmAcceptResponse->UserSessionKey, LogonProfile->UserSessionKey, MSV1_0_USER_SESSION_KEY_LENGTH );
RtlCopyMemory( NtlmAcceptResponse->LanmanSessionKey, LogonProfile->LanmanSessionKey, MSV1_0_LANMAN_SESSION_KEY_LENGTH );
TempKickoffTime = (LARGE_INTEGER UNALIGNED *) &NtlmAcceptResponse->KickoffTime; *TempKickoffTime = LogonProfile->KickOffTime;
AcceptResponseToken->cbBuffer = sizeof(NTLM_ACCEPT_RESPONSE);
if ( fContextReq & ASC_REQ_LICENSING ) { *pfContextAttr = ASC_RET_ALLOCATED_MEMORY | ASC_RET_LICENSING ; } else { *pfContextAttr = ASC_RET_ALLOCATED_MEMORY; }
*ptsExpiry = LogonProfile->LogoffTime; scRet = SEC_E_OK;
Cleanup: if (SourceName.Buffer != NULL) { RtlFreeAnsiString(&SourceName); }
if (LogonBuffer != NULL) { ZwFreeVirtualMemory( NtCurrentProcess(), &LogonBuffer, &LogonBufferSize, MEM_RELEASE ); }
if (LogonProfile != NULL) { LsaFreeReturnBuffer(LogonProfile); }
if (TokenHandle != NULL) { NtClose(TokenHandle); }
return(scRet);
}
//+-------------------------------------------------------------------------
//
// Function: DeleteSecurityContext
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY DeleteSecurityContext( PCtxtHandle phContext // Context to delete
) { SECURITY_STATUS scRet;
PAGED_CODE();
// For now, just delete the LSA context:
if (!phContext) { return(SEC_E_INVALID_HANDLE); }
scRet = NtlmDeleteKernelContext(phContext);
return(scRet);
}
//+-------------------------------------------------------------------------
//
// Function: ApplyControlToken
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY ApplyControlToken( PCtxtHandle phContext, // Context to modify
PSecBufferDesc pInput // Input token to apply
) { PAGED_CODE();
return(SEC_E_UNSUPPORTED_FUNCTION);
}
//+-------------------------------------------------------------------------
//
// Function: EnumerateSecurityPackagesW
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY EnumerateSecurityPackagesW( unsigned long SEC_FAR * pcPackages, // Receives num. packages
PSecPkgInfo SEC_FAR * ppPackageInfo // Receives array of info
) { ULONG PackageInfoSize; PSecPkgInfoW PackageInfo = NULL; PUCHAR Where;
PAGED_CODE();
//
// Figure out the size of the returned data
//
PackageInfoSize = sizeof(SecPkgInfoW) + sizeof(NTLMSP_NAME) + sizeof(NTLMSP_COMMENT);
PackageInfo = (PSecPkgInfoW) SecAllocate(PackageInfoSize);
if (PackageInfo == NULL) { return(SEC_E_INSUFFICIENT_MEMORY); }
//
// Fill in the fixed length fields
//
PackageInfo->fCapabilities = SECPKG_FLAG_CONNECTION | SECPKG_FLAG_TOKEN_ONLY; PackageInfo->wVersion = NTLMSP_VERSION; PackageInfo->wRPCID = NTLMSP_RPCID; PackageInfo->cbMaxToken = NTLMSSP_MAX_MESSAGE_SIZE;
//
// Fill in the fields
//
Where = (PUCHAR) (PackageInfo+1); PackageInfo->Name = (LPWSTR) Where; RtlCopyMemory( PackageInfo->Name, NTLMSP_NAME, sizeof(NTLMSP_NAME) ); Where += sizeof(NTLMSP_NAME);
PackageInfo->Comment = (LPWSTR) Where; RtlCopyMemory( PackageInfo->Comment, NTLMSP_COMMENT, sizeof(NTLMSP_COMMENT) ); Where += sizeof(NTLMSP_COMMENT);
*pcPackages = 1; *ppPackageInfo = PackageInfo; return(SEC_E_OK); }
//+-------------------------------------------------------------------------
//
// Function: QuerySecurityPackageInfoW
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoW( PSECURITY_STRING pssPackageName, // Name of package
PSecPkgInfo * ppPackageInfo // Receives package info
) {
UNICODE_STRING PackageName; ULONG PackageCount;
PAGED_CODE();
RtlInitUnicodeString( &PackageName, NTLMSP_NAME );
if (!RtlEqualUnicodeString( pssPackageName, &PackageName, TRUE // case insensitive
)) { return(SEC_E_SECPKG_NOT_FOUND); }
return(EnumerateSecurityPackages(&PackageCount,ppPackageInfo));
}
//+-------------------------------------------------------------------------
//
// Function: FreeContextBuffer
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY FreeContextBuffer( void SEC_FAR * pvContextBuffer ) { PAGED_CODE();
SecFree(pvContextBuffer);
return(SEC_E_OK); }
//+-------------------------------------------------------------------------
//
// Function: GetSecurityUserData
//
// Synopsis: retrieves information about a logged on user.
//
// Effects: allocates memory to be freed with FreeContextBuffer
//
// Arguments: pLogonId - Logon id of the user in question
// fFlags - Indicates whether the caller want Cairo style names
// or NT styles names. For NT, this is ignored.
// ppUserInfo - Recieves information about user
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
SECURITY_STATUS SEC_ENTRY GetSecurityUserInfo( IN PLUID pLogonId, IN ULONG fFlags, OUT PSecurityUserData * ppUserInfo) { NTSTATUS Status, FinalStatus; PVOID GetInfoBuffer = NULL; PVOID GetInfoResponseBuffer = NULL; PMSV1_0_GETUSERINFO_REQUEST GetInfoRequest; PMSV1_0_GETUSERINFO_RESPONSE GetInfoResponse; ULONG ResponseSize; ULONG RegionSize = sizeof(MSV1_0_GETUSERINFO_REQUEST); PSecurityUserData UserInfo = NULL; ULONG UserInfoSize; PUCHAR Where; SECURITY_STATUS scRet; PClient Client = NULL;
scRet = IsOkayToExec(&Client); if (!NT_SUCCESS(scRet)) { return(scRet); }
//
// Allocate virtual memory for the response buffer.
//
Status = ZwAllocateVirtualMemory( NtCurrentProcess(), &GetInfoBuffer, 0L, &RegionSize, MEM_COMMIT, PAGE_READWRITE );
GetInfoRequest = GetInfoBuffer;
if (!NT_SUCCESS(Status)) { scRet = Status; goto Cleanup; }
GetInfoRequest->MessageType = MsV1_0GetUserInfo;
RtlCopyLuid(&GetInfoRequest->LogonId, pLogonId);
Status = LsaCallAuthenticationPackage( Client->hPort, PackageId, GetInfoRequest, RegionSize, &GetInfoResponseBuffer, &ResponseSize, &FinalStatus);
GetInfoResponse = GetInfoResponseBuffer;
if (!NT_SUCCESS(Status)) { GetInfoResponseBuffer = NULL; scRet = Status; goto Cleanup; }
if (!NT_SUCCESS(FinalStatus)) { scRet = FinalStatus; goto Cleanup; }
ASSERT(GetInfoResponse->MessageType == MsV1_0GetUserInfo);
//
// Build a SecurityUserData
//
UserInfoSize = sizeof(SecurityUserData) + GetInfoResponse->UserName.MaximumLength + GetInfoResponse->LogonDomainName.MaximumLength + GetInfoResponse->LogonServer.MaximumLength + RtlLengthSid(GetInfoResponse->UserSid);
scRet = ZwAllocateVirtualMemory( NtCurrentProcess(), &UserInfo, 0L, &UserInfoSize, MEM_COMMIT, PAGE_READWRITE ); if (!NT_SUCCESS(scRet)) { goto Cleanup; }
//
// Pack in the SID first, to respectalignment boundaries.
//
Where = (PUCHAR) (UserInfo + 1); UserInfo->pSid = (PSID) (Where); RtlCopySid( UserInfoSize, Where, GetInfoResponse->UserSid ); Where += RtlLengthSid(Where);
//
// Pack in the strings
//
PutString( (PSTRING) &UserInfo->UserName, (PSTRING) &GetInfoResponse->UserName, 0, &Where );
PutString( (PSTRING) &UserInfo->LogonDomainName, (PSTRING) &GetInfoResponse->LogonDomainName, 0, &Where );
PutString( (PSTRING) &UserInfo->LogonServer, (PSTRING) &GetInfoResponse->LogonServer, 0, &Where );
*ppUserInfo = UserInfo; UserInfo = NULL; scRet = STATUS_SUCCESS;
Cleanup: if (GetInfoRequest != NULL) { ZwFreeVirtualMemory( NtCurrentProcess(), &GetInfoRequest, &RegionSize, MEM_RELEASE );
}
if (UserInfo != NULL) { FreeContextBuffer(UserInfo); }
if (GetInfoResponseBuffer != NULL) { LsaFreeReturnBuffer(GetInfoResponseBuffer); }
return(scRet); }
|