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.
1408 lines
44 KiB
1408 lines
44 KiB
//+-----------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (c) Microsoft Corporation 1992 - 1996
|
|
//
|
|
// File: credapi.cxx
|
|
//
|
|
// Contents: Code for credentials APIs for the NtLm package
|
|
// Main entry points into this dll:
|
|
// SpAcceptCredentials
|
|
// SpAcquireCredentialsHandle
|
|
// SpFreeCredentialsHandle
|
|
// SpQueryCredentialsAttributes
|
|
// SpSaveCredentials
|
|
// SpGetCredentials
|
|
// SpDeleteCredentials
|
|
//
|
|
// Helper functions:
|
|
// CopyClientString
|
|
//
|
|
// History: ChandanS 26-Jul-1996 Stolen from kerberos\client2\credapi.cxx
|
|
//
|
|
//------------------------------------------------------------------------
|
|
#define NTLM_CREDAPI
|
|
#include <global.h>
|
|
|
|
extern "C"
|
|
{
|
|
#include <nlp.h>
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CopyClientString
|
|
//
|
|
// Synopsis: copies a client string to local memory, including
|
|
// allocating space for it locally.
|
|
//
|
|
// Arguments:
|
|
// SourceString - Could be Oem or Wchar in client process
|
|
// SourceLength - bytes
|
|
// DoUnicode - whether the string is Wchar
|
|
//
|
|
// Returns:
|
|
// DestinationString - Unicode String in Lsa Process
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
HRESULT
|
|
CopyClientString(
|
|
IN PWSTR SourceString,
|
|
IN ULONG SourceLength,
|
|
IN BOOLEAN DoUnicode,
|
|
OUT PUNICODE_STRING DestinationString
|
|
)
|
|
{
|
|
SspPrint((SSP_API_MORE,"Entering CopyClientString\n"));
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
STRING TemporaryString;
|
|
ULONG SourceSize = 0;
|
|
ULONG CharacterSize = sizeof(CHAR);
|
|
|
|
//
|
|
// First initialize the string to zero, in case the source is a null
|
|
// string
|
|
//
|
|
|
|
DestinationString->Length = DestinationString->MaximumLength = 0;
|
|
DestinationString->Buffer = NULL;
|
|
TemporaryString.Buffer = NULL;
|
|
|
|
|
|
if (SourceString != NULL)
|
|
{
|
|
|
|
//
|
|
// If the length is zero, allocate one byte for a "\0" terminator
|
|
//
|
|
|
|
if (SourceLength == 0)
|
|
{
|
|
DestinationString->Buffer = (LPWSTR) NtLmAllocate(sizeof(WCHAR));
|
|
if (DestinationString->Buffer == NULL)
|
|
{
|
|
SspPrint((SSP_CRITICAL,"CopyClientString, Error from NtLmAllocate is 0x%lx\n", Status));
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
DestinationString->MaximumLength = sizeof(WCHAR);
|
|
*DestinationString->Buffer = L'\0';
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Allocate a temporary buffer to hold the client string. We may
|
|
// then create a buffer for the unicode version. The length
|
|
// is the length in characters, so possible expand to hold unicode
|
|
// characters and a null terminator.
|
|
//
|
|
|
|
if (DoUnicode)
|
|
{
|
|
CharacterSize = sizeof(WCHAR);
|
|
}
|
|
|
|
SourceSize = (SourceLength + 1) * CharacterSize;
|
|
|
|
//
|
|
// insure no overflow aggainst UNICODE_STRING
|
|
//
|
|
|
|
if ( (SourceSize > 0xFFFF) ||
|
|
((SourceSize - CharacterSize) > 0xFFFF)
|
|
)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
SspPrint((SSP_CRITICAL,"CopyClientString, SourceSize is too large\n"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
TemporaryString.Buffer = (LPSTR) NtLmAllocate(SourceSize);
|
|
if (TemporaryString.Buffer == NULL)
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
SspPrint((SSP_CRITICAL,"CopyClientString, Error from NtLmAllocate is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
TemporaryString.Length = (USHORT) (SourceSize - CharacterSize);
|
|
TemporaryString.MaximumLength = (USHORT) SourceSize;
|
|
|
|
|
|
//
|
|
// Finally copy the string from the client
|
|
//
|
|
|
|
Status = LsaFunctions->CopyFromClientBuffer(
|
|
NULL,
|
|
SourceSize - CharacterSize,
|
|
TemporaryString.Buffer,
|
|
SourceString
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SspPrint((SSP_CRITICAL,"CopyClientString, Error from LsaFunctions->CopyFromClientBuffer is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// If we are doing unicode, finish up now
|
|
//
|
|
if (DoUnicode)
|
|
{
|
|
DestinationString->Buffer = (LPWSTR) TemporaryString.Buffer;
|
|
DestinationString->Length = (USHORT) (SourceSize - CharacterSize);
|
|
DestinationString->MaximumLength = (USHORT) SourceSize;
|
|
|
|
TemporaryString.Buffer = NULL;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// allocate enough space based on the size of the original Unicode input.
|
|
// required so that we can use our own allocation scheme.
|
|
//
|
|
|
|
DestinationString->Buffer = (LPWSTR)NtLmAllocate( SourceSize*sizeof(WCHAR) );
|
|
if( DestinationString->Buffer == NULL )
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
SspPrint((SSP_CRITICAL,"Error from NtLmAllocate\n"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
DestinationString->Length = (USHORT)(SourceSize - CharacterSize);
|
|
DestinationString->MaximumLength = (USHORT)SourceSize * sizeof(WCHAR);
|
|
|
|
Status = RtlOemStringToUnicodeString(
|
|
DestinationString,
|
|
&TemporaryString,
|
|
FALSE
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SspPrint((SSP_CRITICAL,"CopyClientString, Error from RtlOemStringToUnicodeString is 0x%lx\n", Status));
|
|
// set to STATUS_NO_MEMORY, as it's unlikely that locale error code would be useful.
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if (TemporaryString.Buffer != NULL)
|
|
{
|
|
NtLmFree(TemporaryString.Buffer);
|
|
}
|
|
|
|
SspPrint((SSP_API_MORE,"Leaving CopyClientString\n"));
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpAcceptCredentials
|
|
//
|
|
// Synopsis: This routine is called after another package has logged
|
|
// a user on. The other package provides a user name and
|
|
// password and the NtLm package will create a logon
|
|
// session for this user.
|
|
//
|
|
// Effects: Creates a logon session
|
|
//
|
|
// Arguments: LogonType - Type of logon, such as network or interactive
|
|
// Accountname - Name of the account that logged on
|
|
// PrimaryCredentials - Primary credentials for the account,
|
|
// containing a domain name, password, SID, etc.
|
|
// SupplementalCredentials - NtLm -Specific blob of
|
|
// supplemental credentials.
|
|
//
|
|
// Returns: None
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
NTSTATUS NTAPI
|
|
SpAcceptCredentials(
|
|
IN SECURITY_LOGON_TYPE LogonType,
|
|
IN PUNICODE_STRING AccountName,
|
|
IN PSECPKG_PRIMARY_CRED PrimaryCredentials,
|
|
IN PSECPKG_SUPPLEMENTAL_CRED SupplementalCredentials
|
|
)
|
|
{
|
|
NTSTATUS Status = S_OK;
|
|
SspPrint((SSP_API,"Entering SpAcceptCredentials\n"));
|
|
|
|
Status = SspAcceptCredentials(
|
|
LogonType,
|
|
PrimaryCredentials,
|
|
SupplementalCredentials
|
|
);
|
|
|
|
SspPrint((SSP_API,"Leaving SpAcceptCredentials\n"));
|
|
|
|
return(SspNtStatusToSecStatus(Status, SEC_E_INTERNAL_ERROR));
|
|
UNREFERENCED_PARAMETER( AccountName );
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpAcquireCredentialsHandle
|
|
//
|
|
// Synopsis: Contains NtLm Code for AcquireCredentialsHandle which
|
|
// creates a Credential associated with a logon session.
|
|
//
|
|
// Effects: Creates a SSP_CREDENTIAL
|
|
//
|
|
// Arguments: PrincipalName - Name of logon session for which to create credential
|
|
// CredentialUseFlags - Flags indicating whether the credentials
|
|
// is for inbound or outbound use.
|
|
// LogonId - The logon ID of logon session for which to create
|
|
// a credential.
|
|
// AuthorizationData - Unused blob of NtLm-specific data
|
|
// GetKeyFunction - Unused function to retrieve a session key
|
|
// GetKeyArgument - Argument for GetKeyFunction
|
|
// CredentialHandle - Receives handle to new credential
|
|
// ExpirationTime - Receives expiration time for credential
|
|
//
|
|
// Returns:
|
|
// STATUS_SUCCESS -- Call completed successfully
|
|
// SEC_E_NO_SPM -- Security Support Provider is not running
|
|
// SEC_E_PACKAGE_UNKNOWN -- Package being queried is not this package
|
|
// SEC_E_PRINCIPAL_UNKNOWN -- No such principal
|
|
// SEC_E_NOT_OWNER -- caller does not own the specified credentials
|
|
// SEC_E_INSUFFICIENT_MEMORY -- Not enough memory
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
NTSTATUS NTAPI
|
|
SpAcquireCredentialsHandle(
|
|
IN OPTIONAL PUNICODE_STRING PrincipalName,
|
|
IN ULONG CredentialUseFlags,
|
|
IN OPTIONAL PLUID LogonId,
|
|
IN PVOID AuthorizationData,
|
|
IN PVOID GetKeyFunction,
|
|
IN PVOID GetKeyArgument,
|
|
OUT PULONG_PTR CredentialHandle,
|
|
OUT PTimeStamp ExpirationTime
|
|
)
|
|
{
|
|
SspPrint((SSP_API,"Entering SpAcquireCredentialsHandle\n"));
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
UNICODE_STRING UserName;
|
|
UNICODE_STRING DomainName;
|
|
UNICODE_STRING Password;
|
|
ULONG NewCredentialUseFlags = CredentialUseFlags;
|
|
PSEC_WINNT_AUTH_IDENTITY pAuthIdentity = NULL;
|
|
BOOLEAN DoUnicode = TRUE;
|
|
PSEC_WINNT_AUTH_IDENTITY_EXW pAuthIdentityEx = NULL;
|
|
|
|
PSEC_WINNT_AUTH_IDENTITY_W TmpCredentials = NULL;
|
|
ULONG CredSize = 0;
|
|
ULONG Offset = 0;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
|
|
RtlInitUnicodeString(
|
|
&UserName,
|
|
NULL);
|
|
|
|
RtlInitUnicodeString(
|
|
&DomainName,
|
|
NULL);
|
|
|
|
RtlInitUnicodeString(
|
|
&Password,
|
|
NULL);
|
|
|
|
//
|
|
// Validate the arguments
|
|
//
|
|
|
|
if ( (CredentialUseFlags & (SECPKG_CRED_OUTBOUND |SECPKG_CRED_INBOUND)) == 0)
|
|
{
|
|
Status = SEC_E_INVALID_CREDENTIAL_USE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if ( ARGUMENT_PRESENT(GetKeyFunction) ) {
|
|
Status = SEC_E_UNSUPPORTED_FUNCTION;
|
|
SspPrint((SSP_CRITICAL,"Error from SpAquireCredentialsHandle is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
|
|
// RDR2 passes in a 1 while talking to down level clients
|
|
|
|
if ( ARGUMENT_PRESENT(GetKeyArgument) && (GetKeyArgument != (PVOID) 1)) {
|
|
Status = SEC_E_UNSUPPORTED_FUNCTION;
|
|
SspPrint((SSP_CRITICAL,"Error from SpAquireCredentialsHandle is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// First get information about the caller.
|
|
//
|
|
|
|
SECPKG_CLIENT_INFO ClientInfo;
|
|
PLUID LogonIdToUse;
|
|
|
|
Status = LsaFunctions->GetClientInfo(&ClientInfo);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SspPrint((SSP_CRITICAL,"SpAcquireCredentialsHandle, Error from LsaFunctions->GetClientInfo is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// If the caller supplied a logon ID, and it doesn't match the caller,
|
|
// they must have the TCB privilege
|
|
//
|
|
|
|
|
|
if (ARGUMENT_PRESENT(LogonId) &&
|
|
((LogonId->LowPart != 0) || (LogonId->HighPart != 0)) &&
|
|
!RtlEqualLuid( LogonId, &ClientInfo.LogonId)
|
|
)
|
|
{
|
|
if (!ClientInfo.HasTcbPrivilege)
|
|
{
|
|
Status = STATUS_PRIVILEGE_NOT_HELD;
|
|
SspPrint((SSP_CRITICAL,"SpAcquireCredentialsHandle, Error from ClientInfo.HasTcbPrivilege is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
|
|
LogonIdToUse = LogonId;
|
|
|
|
// note: there is a special case where the LogonIdToUse specifies
|
|
// the SYSTEM token, and there may not be a credential (and access token)
|
|
// for that Luid yet. This special case is handled in SsprAcquireCredentialsHandle()
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Use the callers logon id.
|
|
//
|
|
|
|
LogonIdToUse = &ClientInfo.LogonId;
|
|
}
|
|
|
|
//
|
|
// Got to have an impersonation level token in order to call ACH.
|
|
// This check used to be in lsa, but moved here to enable
|
|
// some S4Uproxy scenarios to work w/o tcb.
|
|
//
|
|
if (ClientInfo.ImpersonationLevel <= SecurityIdentification)
|
|
{
|
|
SspPrint((SSP_CRITICAL, "Trying to acquire credentials with an token no better than SecurityIdentification\n"));
|
|
Status = SEC_E_NO_CREDENTIALS;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Copy over the authorization data into out address
|
|
// space and make a local copy of the strings.
|
|
//
|
|
|
|
|
|
if (AuthorizationData != NULL)
|
|
{
|
|
SECPKG_CALL_INFO CallInfo ;
|
|
SEC_WINNT_AUTH_IDENTITY32 Cred32 = {0};
|
|
SEC_WINNT_AUTH_IDENTITY_EX32 CredEx32 ;
|
|
|
|
if(!LsaFunctions->GetCallInfo( &CallInfo ))
|
|
{
|
|
Status = STATUS_INTERNAL_ERROR;
|
|
SspPrint((SSP_CRITICAL,"SpAcquireCredentialsHandle, Error from LsaFunctions->GetCallInfo is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
|
|
pAuthIdentityEx = (PSEC_WINNT_AUTH_IDENTITY_EXW) NtLmAllocate(sizeof(SEC_WINNT_AUTH_IDENTITY_EXW));
|
|
|
|
if (pAuthIdentityEx != NULL)
|
|
{
|
|
if ( CallInfo.Attributes & SECPKG_CALL_WOWCLIENT )
|
|
{
|
|
|
|
Status = LsaFunctions->CopyFromClientBuffer(
|
|
NULL,
|
|
sizeof( Cred32 ),
|
|
pAuthIdentityEx,
|
|
AuthorizationData );
|
|
|
|
if ( NT_SUCCESS( Status ) )
|
|
{
|
|
RtlCopyMemory( &Cred32, pAuthIdentityEx, sizeof( Cred32 ) );
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
Status = LsaFunctions->CopyFromClientBuffer(
|
|
NULL,
|
|
sizeof(SEC_WINNT_AUTH_IDENTITY),
|
|
pAuthIdentityEx,
|
|
AuthorizationData);
|
|
}
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SspPrint((SSP_CRITICAL,"SpAcquireCredentialsHandle, Error from LsaFunctions->CopyFromClientBuffer is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
SspPrint((SSP_CRITICAL,"SpAcquireCredentialsHandle, Error from NtLmAllocate is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Check for the ex version
|
|
//
|
|
|
|
if (pAuthIdentityEx->Version == SEC_WINNT_AUTH_IDENTITY_VERSION)
|
|
{
|
|
//
|
|
// It's an EX structure.
|
|
//
|
|
|
|
if ( CallInfo.Attributes & SECPKG_CALL_WOWCLIENT )
|
|
{
|
|
Status = LsaFunctions->CopyFromClientBuffer(
|
|
NULL,
|
|
sizeof( CredEx32 ),
|
|
&CredEx32,
|
|
AuthorizationData );
|
|
|
|
if ( NT_SUCCESS( Status ) )
|
|
{
|
|
pAuthIdentityEx->Version = CredEx32.Version ;
|
|
pAuthIdentityEx->Length = (CredEx32.Length < sizeof( SEC_WINNT_AUTH_IDENTITY_EX ) ?
|
|
(ULONG) sizeof( SEC_WINNT_AUTH_IDENTITY_EX ) : CredEx32.Length );
|
|
|
|
pAuthIdentityEx->User = (PWSTR) UlongToPtr( CredEx32.User );
|
|
pAuthIdentityEx->UserLength = CredEx32.UserLength ;
|
|
pAuthIdentityEx->Domain = (PWSTR) UlongToPtr( CredEx32.Domain );
|
|
pAuthIdentityEx->DomainLength = CredEx32.DomainLength ;
|
|
pAuthIdentityEx->Password = (PWSTR) UlongToPtr( CredEx32.Password );
|
|
pAuthIdentityEx->PasswordLength = CredEx32.PasswordLength ;
|
|
pAuthIdentityEx->Flags = CredEx32.Flags ;
|
|
pAuthIdentityEx->PackageList = (PWSTR) UlongToPtr( CredEx32.PackageList );
|
|
pAuthIdentityEx->PackageListLength = CredEx32.PackageListLength ;
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
Status = LsaFunctions->CopyFromClientBuffer(
|
|
NULL,
|
|
sizeof(SEC_WINNT_AUTH_IDENTITY_EXW),
|
|
pAuthIdentityEx,
|
|
AuthorizationData);
|
|
|
|
}
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SspPrint((SSP_CRITICAL,"SpAcquireCredentialsHandle, Error from LsaFunctions->CopyFromClientBuffer is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
pAuthIdentity = (PSEC_WINNT_AUTH_IDENTITY) &pAuthIdentityEx->User;
|
|
CredSize = pAuthIdentityEx->Length;
|
|
Offset = FIELD_OFFSET(SEC_WINNT_AUTH_IDENTITY_EXW, User);
|
|
}
|
|
else
|
|
{
|
|
pAuthIdentity = (PSEC_WINNT_AUTH_IDENTITY_W) pAuthIdentityEx;
|
|
|
|
if ( CallInfo.Attributes & SECPKG_CALL_WOWCLIENT )
|
|
{
|
|
pAuthIdentity->User = (PWSTR) UlongToPtr( Cred32.User );
|
|
pAuthIdentity->UserLength = Cred32.UserLength ;
|
|
pAuthIdentity->Domain = (PWSTR) UlongToPtr( Cred32.Domain );
|
|
pAuthIdentity->DomainLength = Cred32.DomainLength ;
|
|
pAuthIdentity->Password = (PWSTR) UlongToPtr( Cred32.Password );
|
|
pAuthIdentity->PasswordLength = Cred32.PasswordLength ;
|
|
pAuthIdentity->Flags = Cred32.Flags ;
|
|
}
|
|
CredSize = sizeof(SEC_WINNT_AUTH_IDENTITY_W);
|
|
}
|
|
|
|
if ((pAuthIdentity->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI) != 0)
|
|
{
|
|
DoUnicode = FALSE;
|
|
//
|
|
// Turn off the marshalled flag because we don't support marshalling
|
|
// with ansi.
|
|
//
|
|
|
|
pAuthIdentity->Flags &= ~SEC_WINNT_AUTH_IDENTITY_MARSHALLED;
|
|
}
|
|
else if ((pAuthIdentity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE) == 0)
|
|
{
|
|
Status = SEC_E_INVALID_TOKEN;
|
|
SspPrint((SSP_CRITICAL,"SpAcquireCredentialsHandle, Error from pAuthIdentity->Flags is 0x%lx\n", pAuthIdentity->Flags));
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
// This is the only place where we can figure out whether null
|
|
// session was requested
|
|
|
|
if ((pAuthIdentity->UserLength == 0) &&
|
|
(pAuthIdentity->DomainLength == 0) &&
|
|
(pAuthIdentity->PasswordLength == 0) &&
|
|
(pAuthIdentity->User != NULL) &&
|
|
(pAuthIdentity->Domain != NULL) &&
|
|
(pAuthIdentity->Password != NULL))
|
|
{
|
|
NewCredentialUseFlags |= NTLM_CRED_NULLSESSION;
|
|
}
|
|
|
|
if(
|
|
// UserName may include a marshalled credential > UNLEN
|
|
pAuthIdentity->UserLength > 0xFFFC || // MAX_USHORT - NULL
|
|
pAuthIdentity->PasswordLength > PWLEN ||
|
|
pAuthIdentity->DomainLength > DNS_MAX_NAME_LENGTH ) {
|
|
|
|
SspPrint((SSP_CRITICAL,"Supplied credentials illegal length.\n"));
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Copy over the strings
|
|
//
|
|
if( (pAuthIdentity->Flags & SEC_WINNT_AUTH_IDENTITY_MARSHALLED) != 0 ) {
|
|
ULONG TmpCredentialSize;
|
|
ULONG_PTR EndOfCreds;
|
|
ULONG_PTR TmpUser;
|
|
ULONG_PTR TmpDomain;
|
|
ULONG_PTR TmpPassword;
|
|
|
|
|
|
//
|
|
// The callers can set the length of field to n chars, but they
|
|
// will really occupy n+1 chars (null-terminator).
|
|
//
|
|
|
|
TmpCredentialSize = CredSize +
|
|
( pAuthIdentity->UserLength +
|
|
pAuthIdentity->DomainLength +
|
|
pAuthIdentity->PasswordLength +
|
|
(((pAuthIdentity->User != NULL) ? 1 : 0) +
|
|
((pAuthIdentity->Domain != NULL) ? 1 : 0) +
|
|
((pAuthIdentity->Password != NULL) ? 1 : 0)) ) * (ULONG) sizeof(WCHAR);
|
|
|
|
EndOfCreds = (ULONG_PTR) AuthorizationData + TmpCredentialSize;
|
|
|
|
//
|
|
// Verify that all the offsets are valid and no overflow will happen
|
|
//
|
|
|
|
TmpUser = (ULONG_PTR) pAuthIdentity->User;
|
|
|
|
if ((TmpUser != NULL) &&
|
|
( (TmpUser < (ULONG_PTR) AuthorizationData) ||
|
|
(TmpUser > EndOfCreds) ||
|
|
((TmpUser + (pAuthIdentity->UserLength) * sizeof(WCHAR)) > EndOfCreds ) ||
|
|
((TmpUser + (pAuthIdentity->UserLength * sizeof(WCHAR))) < TmpUser)))
|
|
{
|
|
SspPrint((SSP_CRITICAL,"Username in supplied credentials has invalid pointer or length.\n"));
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
TmpDomain = (ULONG_PTR) pAuthIdentity->Domain;
|
|
|
|
if ((TmpDomain != NULL) &&
|
|
( (TmpDomain < (ULONG_PTR) AuthorizationData) ||
|
|
(TmpDomain > EndOfCreds) ||
|
|
((TmpDomain + (pAuthIdentity->DomainLength) * sizeof(WCHAR)) > EndOfCreds ) ||
|
|
((TmpDomain + (pAuthIdentity->DomainLength * sizeof(WCHAR))) < TmpDomain)))
|
|
{
|
|
SspPrint((SSP_CRITICAL,"Domainname in supplied credentials has invalid pointer or length.\n"));
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
TmpPassword = (ULONG_PTR) pAuthIdentity->Password;
|
|
|
|
if ((TmpPassword != NULL) &&
|
|
( (TmpPassword < (ULONG_PTR) AuthorizationData) ||
|
|
(TmpPassword > EndOfCreds) ||
|
|
((TmpPassword + (pAuthIdentity->PasswordLength) * sizeof(WCHAR)) > EndOfCreds ) ||
|
|
((TmpPassword + (pAuthIdentity->PasswordLength * sizeof(WCHAR))) < TmpPassword)))
|
|
{
|
|
SspPrint((SSP_CRITICAL,"Password in supplied credentials has invalid pointer or length.\n"));
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Allocate a chunk of memory for the credentials
|
|
//
|
|
|
|
TmpCredentials = (PSEC_WINNT_AUTH_IDENTITY_W) NtLmAllocate(TmpCredentialSize - Offset);
|
|
if (TmpCredentials == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Copy the credentials from the client
|
|
//
|
|
|
|
Status = LsaFunctions->CopyFromClientBuffer(
|
|
NULL,
|
|
TmpCredentialSize - Offset,
|
|
TmpCredentials,
|
|
(PUCHAR) AuthorizationData + Offset
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SspPrint((SSP_CRITICAL,"Failed to copy whole auth identity\n"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Now convert all the offsets to pointers.
|
|
//
|
|
|
|
if (TmpCredentials->User != NULL)
|
|
{
|
|
USHORT cbUser;
|
|
|
|
TmpCredentials->User = (LPWSTR) RtlOffsetToPointer(
|
|
TmpCredentials->User,
|
|
(PUCHAR) TmpCredentials - (PUCHAR) AuthorizationData - Offset
|
|
);
|
|
|
|
ASSERT( (TmpCredentials->UserLength*sizeof(WCHAR)) <= 0xFFFF );
|
|
|
|
cbUser = (USHORT)(TmpCredentials->UserLength * sizeof(WCHAR));
|
|
UserName.Buffer = (PWSTR)NtLmAllocate( cbUser );
|
|
|
|
if (UserName.Buffer == NULL ) {
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Cleanup;
|
|
}
|
|
|
|
CopyMemory( UserName.Buffer, TmpCredentials->User, cbUser );
|
|
UserName.Length = cbUser;
|
|
UserName.MaximumLength = cbUser;
|
|
}
|
|
|
|
if (TmpCredentials->Domain != NULL)
|
|
{
|
|
USHORT cbDomain;
|
|
|
|
TmpCredentials->Domain = (LPWSTR) RtlOffsetToPointer(
|
|
TmpCredentials->Domain,
|
|
(PUCHAR) TmpCredentials - (PUCHAR) AuthorizationData - Offset
|
|
);
|
|
|
|
ASSERT( (TmpCredentials->DomainLength*sizeof(WCHAR)) <= 0xFFFF );
|
|
cbDomain = (USHORT)(TmpCredentials->DomainLength * sizeof(WCHAR));
|
|
DomainName.Buffer = (PWSTR)NtLmAllocate( cbDomain );
|
|
|
|
if (DomainName.Buffer == NULL ) {
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Cleanup;
|
|
}
|
|
|
|
CopyMemory( DomainName.Buffer, TmpCredentials->Domain, cbDomain );
|
|
DomainName.Length = cbDomain;
|
|
DomainName.MaximumLength = cbDomain;
|
|
}
|
|
|
|
if (TmpCredentials->Password != NULL)
|
|
{
|
|
USHORT cbPassword;
|
|
|
|
TmpCredentials->Password = (LPWSTR) RtlOffsetToPointer(
|
|
TmpCredentials->Password,
|
|
(PUCHAR) TmpCredentials - (PUCHAR) AuthorizationData - Offset
|
|
);
|
|
|
|
|
|
ASSERT( (TmpCredentials->PasswordLength*sizeof(WCHAR)) <= 0xFFFF );
|
|
cbPassword = (USHORT)(TmpCredentials->PasswordLength * sizeof(WCHAR));
|
|
Password.Buffer = (PWSTR)NtLmAllocate( cbPassword );
|
|
|
|
if (Password.Buffer == NULL ) {
|
|
ZeroMemory( TmpCredentials->Password, cbPassword );
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Cleanup;
|
|
}
|
|
|
|
CopyMemory( Password.Buffer, TmpCredentials->Password, cbPassword );
|
|
Password.Length = cbPassword;
|
|
Password.MaximumLength = cbPassword;
|
|
|
|
ZeroMemory( TmpCredentials->Password, cbPassword );
|
|
}
|
|
|
|
} else {
|
|
|
|
if (pAuthIdentity->Password != NULL)
|
|
{
|
|
Status = CopyClientString(
|
|
pAuthIdentity->Password,
|
|
pAuthIdentity->PasswordLength,
|
|
DoUnicode,
|
|
&Password
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SspPrint((SSP_CRITICAL,"SpAcquireCredentialsHandle, Error from CopyClientString is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
|
|
}
|
|
|
|
if (pAuthIdentity->User != NULL)
|
|
{
|
|
Status = CopyClientString(
|
|
pAuthIdentity->User,
|
|
pAuthIdentity->UserLength,
|
|
DoUnicode,
|
|
&UserName
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SspPrint((SSP_CRITICAL, "SpAcquireCredentialsHandle, Error from CopyClientString is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
|
|
}
|
|
|
|
if (pAuthIdentity->Domain != NULL)
|
|
{
|
|
Status = CopyClientString(
|
|
pAuthIdentity->Domain,
|
|
pAuthIdentity->DomainLength,
|
|
DoUnicode,
|
|
&DomainName
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SspPrint((SSP_CRITICAL, "SpAcquireCredentialsHandle, Error from CopyClientString is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Make sure that the domain name length is not greater
|
|
// than the allowed dns domain name
|
|
//
|
|
|
|
if (DomainName.Length > DNS_MAX_NAME_LENGTH * sizeof(WCHAR))
|
|
{
|
|
SspPrint((SSP_CRITICAL, "SpAcquireCredentialsHandle: Invalid supplied domain name %wZ\n",
|
|
&DomainName ));
|
|
Status = SEC_E_UNKNOWN_CREDENTIALS;
|
|
goto Cleanup;
|
|
}
|
|
|
|
}
|
|
}
|
|
} // AuthorizationData != NULL
|
|
|
|
#if 0
|
|
//
|
|
// Handle UPN and composite NETBIOS syntax
|
|
//
|
|
{
|
|
UNICODE_STRING User = UserName;
|
|
UNICODE_STRING Domain = DomainName;
|
|
|
|
Status =
|
|
NtLmParseName(
|
|
&User,
|
|
&Domain,
|
|
TRUE); // If successful, this will allocate and free buffers
|
|
if(NT_SUCCESS(Status)){
|
|
|
|
UserName = User;
|
|
DomainName = Domain;
|
|
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if( Password.Length != 0 )
|
|
{
|
|
UNICODE_STRING OldPassword = Password;
|
|
|
|
Status = NtLmDuplicatePassword( &Password, &OldPassword );
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
ZeroMemory( OldPassword.Buffer, OldPassword.Length );
|
|
NtLmFree( OldPassword.Buffer );
|
|
}
|
|
|
|
Status = SsprAcquireCredentialHandle(
|
|
LogonIdToUse,
|
|
&ClientInfo,
|
|
NewCredentialUseFlags,
|
|
CredentialHandle,
|
|
ExpirationTime,
|
|
&DomainName,
|
|
&UserName,
|
|
&Password );
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SspPrint((SSP_CRITICAL, "SpAcquireCredentialsHandle, Error from SsprAcquireCredentialsHandle is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
|
|
// These will be kept in the Credential structure and freed
|
|
// when the Credential structure is freed
|
|
|
|
if (DomainName.Buffer != NULL)
|
|
{
|
|
DomainName.Buffer = NULL;
|
|
}
|
|
|
|
if (UserName.Buffer != NULL)
|
|
{
|
|
UserName.Buffer = NULL;
|
|
}
|
|
|
|
if (Password.Buffer != NULL)
|
|
{
|
|
Password.Buffer = NULL;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if (TmpCredentials != NULL)
|
|
{
|
|
NtLmFree(TmpCredentials);
|
|
}
|
|
|
|
if (DomainName.Buffer != NULL)
|
|
{
|
|
NtLmFree(DomainName.Buffer);
|
|
}
|
|
|
|
if (UserName.Buffer != NULL)
|
|
{
|
|
NtLmFree(UserName.Buffer);
|
|
}
|
|
|
|
if (Password.Buffer != NULL)
|
|
{
|
|
ZeroMemory(Password.Buffer, Password.Length);
|
|
NtLmFree(Password.Buffer);
|
|
}
|
|
|
|
if (pAuthIdentityEx != NULL)
|
|
{
|
|
NtLmFree(pAuthIdentityEx);
|
|
}
|
|
|
|
SspPrint((SSP_API, "Leaving SpAcquireCredentialsHandle, Status is %d\n", Status));
|
|
return(SspNtStatusToSecStatus(Status, SEC_E_INTERNAL_ERROR));
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SpFreeCredentialsHandle
|
|
//
|
|
// Synopsis: Frees a credential created by AcquireCredentialsHandle.
|
|
//
|
|
// Effects: Unlinks the credential from the global list and the list
|
|
// for this client.
|
|
//
|
|
// Arguments: CredentialHandle - Handle to the credential to free
|
|
// (acquired through AcquireCredentialsHandle)
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns: STATUS_SUCCESS on success,
|
|
// SEC_E_INVALID_HANDLE if the handle is not valid
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
NTSTATUS NTAPI
|
|
SpFreeCredentialsHandle(
|
|
IN ULONG_PTR CredentialHandle
|
|
)
|
|
{
|
|
SspPrint((SSP_API, "Entering SpFreeCredentialsHandle\n"));
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PSSP_CREDENTIAL Credential;
|
|
|
|
//
|
|
// Find the referenced credential and delink it.
|
|
//
|
|
|
|
Status = SspCredentialReferenceCredential(
|
|
CredentialHandle,
|
|
TRUE, // remove the instance of the credential
|
|
&Credential );
|
|
|
|
if ( !NT_SUCCESS( Status ) ) {
|
|
SspPrint((SSP_CRITICAL, "SpFreeCredentialsHandle, Error from SspCredentialReferenceCredential is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Dereferencing the Credential will remove the client's reference
|
|
// to it, causing it to be rundown if nobody else is using it.
|
|
//
|
|
|
|
SspCredentialDereferenceCredential( Credential );
|
|
|
|
Cleanup:
|
|
|
|
//
|
|
// Catch spurious INVALID_HANDLE being returned to RPC.
|
|
//
|
|
|
|
ASSERT( NT_SUCCESS(Status) );
|
|
|
|
SspPrint((SSP_API, "Leaving SpFreeCredentialsHandle\n"));
|
|
return(SspNtStatusToSecStatus(Status, SEC_E_INTERNAL_ERROR));
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
SpQueryCredentialsAttributes(
|
|
IN LSA_SEC_HANDLE CredentialHandle,
|
|
IN ULONG CredentialAttribute,
|
|
IN OUT PVOID Buffer
|
|
)
|
|
{
|
|
PSSP_CREDENTIAL pCredential = NULL;
|
|
SecPkgCredentials_NamesW Names;
|
|
LUID LogonId;
|
|
BOOLEAN bActiveLogonsAreLocked = FALSE;
|
|
|
|
LPWSTR pszContextNames = NULL;
|
|
LPWSTR pWhere;
|
|
|
|
LPWSTR pszUserName = NULL;
|
|
LPWSTR pszDomainName = NULL;
|
|
DWORD cchUserName = 0;
|
|
DWORD cchDomainName = 0;
|
|
ULONG Length;
|
|
|
|
BOOLEAN CalledLsaLookup = FALSE;
|
|
PLSAPR_REFERENCED_DOMAIN_LIST ReferencedDomain = NULL;
|
|
LSAPR_TRANSLATED_NAMES ReferencedUser;
|
|
|
|
#if _WIN64
|
|
SECPKG_CALL_INFO CallInfo;
|
|
#endif
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
SspPrint((SSP_API,"In SpQueryCredentialsAttributes\n"));
|
|
|
|
|
|
Names.sUserName = NULL;
|
|
|
|
if (CredentialAttribute != SECPKG_CRED_ATTR_NAMES)
|
|
{
|
|
SspPrint((SSP_MISC, "Asked for illegal info level in QueryCredAttr: %d\n",
|
|
CredentialAttribute));
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status = SspCredentialReferenceCredential(
|
|
CredentialHandle,
|
|
FALSE,
|
|
&pCredential );
|
|
|
|
if ( !NT_SUCCESS( Status ) ) {
|
|
SspPrint((SSP_CRITICAL, "SpQueryCredentialsAttributes, Error from SspCredentialReferenceCredential is 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
|
|
#if _WIN64
|
|
if(!LsaFunctions->GetCallInfo( &CallInfo ))
|
|
{
|
|
Status = STATUS_INTERNAL_ERROR;
|
|
SspPrint((SSP_CRITICAL, "SpQueryCredentialsAttributes, failed to get callinfo 0x%lx\n", Status));
|
|
goto Cleanup;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
//
|
|
// The logon id of the credential is constant, so it is o.k.
|
|
// to use it without locking the credential
|
|
//
|
|
|
|
LogonId = pCredential->LogonId;
|
|
|
|
|
|
//
|
|
// credentials were either specified when cred built, or, they were defaulted.
|
|
//
|
|
|
|
if ( pCredential->UserName.Buffer == NULL &&
|
|
pCredential->DomainName.Buffer == NULL )
|
|
{
|
|
PACTIVE_LOGON pActiveLogon = NULL;
|
|
|
|
//
|
|
// defaulted creds: pickup info from active logon table.
|
|
//
|
|
|
|
NlpLockActiveLogonsRead();
|
|
bActiveLogonsAreLocked = TRUE;
|
|
|
|
pActiveLogon = NlpFindActiveLogon(&LogonId);
|
|
|
|
if (pActiveLogon)
|
|
{
|
|
//
|
|
// found an active logon entry.
|
|
//
|
|
|
|
pszUserName = pActiveLogon->UserName.Buffer;
|
|
cchUserName = pActiveLogon->UserName.Length / sizeof(WCHAR);
|
|
pszDomainName = pActiveLogon->LogonDomainName.Buffer;
|
|
cchDomainName = pActiveLogon->LogonDomainName.Length / sizeof(WCHAR);
|
|
}
|
|
else
|
|
{
|
|
PTOKEN_USER pTokenInfo;
|
|
BYTE FastBuffer[ 256 ];
|
|
DWORD cbTokenInfo;
|
|
HANDLE ClientTokenHandle;
|
|
|
|
BOOL fSuccess = FALSE;
|
|
|
|
NlpUnlockActiveLogons();
|
|
bActiveLogonsAreLocked = FALSE;
|
|
|
|
|
|
//
|
|
// get a token associated with the logon session.
|
|
//
|
|
|
|
Status = LsaFunctions->OpenTokenByLogonId(
|
|
&LogonId,
|
|
&ClientTokenHandle
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SspPrint(( SSP_CRITICAL,
|
|
"SpQueryCredentialsAttributes: "
|
|
"Could not open client token 0x%lx\n",
|
|
Status ));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// get Sid associated with credential.
|
|
//
|
|
|
|
cbTokenInfo = sizeof(FastBuffer);
|
|
pTokenInfo = (PTOKEN_USER)FastBuffer;
|
|
|
|
|
|
fSuccess = GetTokenInformation(
|
|
ClientTokenHandle,
|
|
TokenUser,
|
|
pTokenInfo,
|
|
cbTokenInfo,
|
|
&cbTokenInfo
|
|
);
|
|
|
|
|
|
CloseHandle( ClientTokenHandle );
|
|
|
|
if ( fSuccess )
|
|
{
|
|
LSAPR_SID_ENUM_BUFFER SidEnumBuffer;
|
|
LSAPR_SID_INFORMATION SidInfo;
|
|
ULONG MappedCount;
|
|
|
|
SidEnumBuffer.Entries = 1;
|
|
SidEnumBuffer.SidInfo = &SidInfo;
|
|
|
|
SidInfo.Sid = (LSAPR_SID*)pTokenInfo->User.Sid;
|
|
|
|
ZeroMemory( &ReferencedUser, sizeof(ReferencedUser) );
|
|
CalledLsaLookup = TRUE;
|
|
|
|
Status = LsarLookupSids(
|
|
NtLmGlobalPolicyHandle,
|
|
&SidEnumBuffer,
|
|
&ReferencedDomain,
|
|
&ReferencedUser,
|
|
LsapLookupWksta,
|
|
&MappedCount
|
|
);
|
|
|
|
if ( !NT_SUCCESS( Status ) ||
|
|
(MappedCount == 0) ||
|
|
(ReferencedUser.Entries == 0) ||
|
|
(ReferencedDomain == NULL) ||
|
|
(ReferencedDomain->Entries == 0)
|
|
)
|
|
{
|
|
fSuccess = FALSE;
|
|
}
|
|
else
|
|
{
|
|
LONG Index = ReferencedUser.Names->DomainIndex;
|
|
|
|
pszUserName = ReferencedUser.Names->Name.Buffer;
|
|
cchUserName = ReferencedUser.Names->Name.Length / sizeof(WCHAR);
|
|
|
|
pszDomainName = ReferencedDomain->Domains[Index].Name.Buffer;
|
|
cchDomainName = ReferencedDomain->Domains[Index].Name.Length / sizeof(WCHAR);
|
|
}
|
|
}
|
|
|
|
if ( !fSuccess )
|
|
{
|
|
Status = STATUS_NO_SUCH_LOGON_SESSION;
|
|
SspPrint(( SSP_CRITICAL, "SpQueryCredentialsAtributes, NlpFindActiveLogon returns FALSE\n"));
|
|
goto Cleanup;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// specified creds.
|
|
//
|
|
|
|
pszUserName = pCredential->UserName.Buffer;
|
|
cchUserName = pCredential->UserName.Length / sizeof(WCHAR);
|
|
pszDomainName = pCredential->DomainName.Buffer;
|
|
cchDomainName = pCredential->DomainName.Length / sizeof(WCHAR);
|
|
}
|
|
|
|
Length = (cchUserName + 1 + cchDomainName + 1) * sizeof(WCHAR);
|
|
|
|
pszContextNames = (LPWSTR)NtLmAllocate( Length );
|
|
if ( pszContextNames == NULL )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
pWhere = pszContextNames;
|
|
|
|
if ( pszDomainName)
|
|
{
|
|
RtlCopyMemory( pszContextNames, pszDomainName, cchDomainName * sizeof(WCHAR) );
|
|
pszContextNames[ cchDomainName ] = L'\\';
|
|
pWhere += (cchDomainName+1);
|
|
}
|
|
|
|
|
|
if ( pszUserName )
|
|
{
|
|
RtlCopyMemory( pWhere, pszUserName, cchUserName * sizeof(WCHAR) );
|
|
}
|
|
|
|
pWhere[ cchUserName ] = L'\0';
|
|
|
|
if (bActiveLogonsAreLocked)
|
|
{
|
|
NlpUnlockActiveLogons();
|
|
bActiveLogonsAreLocked = FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Allocate memory in the client's address space
|
|
//
|
|
|
|
Status = LsaFunctions->AllocateClientBuffer(
|
|
NULL,
|
|
Length,
|
|
(PVOID *) &Names.sUserName
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Copy the string there
|
|
//
|
|
|
|
Status = LsaFunctions->CopyToClientBuffer(
|
|
NULL,
|
|
Length,
|
|
Names.sUserName,
|
|
pszContextNames
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Now copy the address of the string there
|
|
//
|
|
|
|
#if _WIN64
|
|
|
|
if ( CallInfo.Attributes & SECPKG_CALL_WOWCLIENT )
|
|
{
|
|
Status = LsaFunctions->CopyToClientBuffer(
|
|
NULL,
|
|
sizeof(ULONG),
|
|
Buffer,
|
|
&Names
|
|
);
|
|
}
|
|
else
|
|
{
|
|
Status = LsaFunctions->CopyToClientBuffer(
|
|
NULL,
|
|
sizeof(Names),
|
|
Buffer,
|
|
&Names
|
|
);
|
|
}
|
|
|
|
#else
|
|
|
|
Status = LsaFunctions->CopyToClientBuffer(
|
|
NULL,
|
|
sizeof(Names),
|
|
Buffer,
|
|
&Names
|
|
);
|
|
#endif
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if (bActiveLogonsAreLocked)
|
|
{
|
|
NlpUnlockActiveLogons();
|
|
}
|
|
|
|
if ( pCredential != NULL )
|
|
{
|
|
SspCredentialDereferenceCredential( pCredential );
|
|
}
|
|
|
|
if ( CalledLsaLookup )
|
|
{
|
|
if ( ReferencedDomain )
|
|
{
|
|
LsaIFree_LSAPR_REFERENCED_DOMAIN_LIST( ReferencedDomain );
|
|
}
|
|
|
|
LsaIFree_LSAPR_TRANSLATED_NAMES( &ReferencedUser );
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (Names.sUserName != NULL)
|
|
{
|
|
(VOID) LsaFunctions->FreeClientBuffer(
|
|
NULL,
|
|
Names.sUserName
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( pszContextNames )
|
|
{
|
|
NtLmFree( pszContextNames );
|
|
}
|
|
|
|
SspPrint((SSP_API, "Leaving SpQueryCredentialsAttributes\n"));
|
|
|
|
return (SspNtStatusToSecStatus(Status, SEC_E_INTERNAL_ERROR));
|
|
}
|
|
|
|
|
|
NTSTATUS NTAPI
|
|
SpSaveCredentials(
|
|
IN ULONG_PTR CredentialHandle,
|
|
IN PSecBuffer Credentials
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(CredentialHandle);
|
|
UNREFERENCED_PARAMETER(Credentials);
|
|
SspPrint((SSP_API,"In SpSaveCredentials\n"));
|
|
return(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
|
|
|
|
NTSTATUS NTAPI
|
|
SpGetCredentials(
|
|
IN ULONG_PTR CredentialHandle,
|
|
IN OUT PSecBuffer Credentials
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(CredentialHandle);
|
|
UNREFERENCED_PARAMETER(Credentials);
|
|
SspPrint((SSP_API,"In SpGetCredentials\n"));
|
|
return(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|
|
|
|
|
|
NTSTATUS NTAPI
|
|
SpDeleteCredentials(
|
|
IN ULONG_PTR CredentialHandle,
|
|
IN PSecBuffer Key
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(CredentialHandle);
|
|
UNREFERENCED_PARAMETER(Key);
|
|
SspPrint((SSP_API,"In SpDeleteCredentials\n"));
|
|
return(SEC_E_UNSUPPORTED_FUNCTION);
|
|
}
|