📄 credhand.cxx
字号:
//
// If we're using a common set of data, free the captured stuff
//
if ( Credential )
{
if ( (UserName) && (UserName->Buffer) )
{
NtLmFree( UserName->Buffer );
UserName->Buffer = NULL ;
}
if ( ( DomainName ) && (DomainName->Buffer) )
{
NtLmFree( DomainName->Buffer );
DomainName->Buffer = NULL ;
}
if ( ( Password ) && ( Password->Buffer ) )
{
ZeroMemory( Password->Buffer, Password->Length );
NtLmFree( Password->Buffer );
Password->Buffer = NULL ;
}
}
}
//
// If we didn't just find a credential, create one now.
//
if (Credential == NULL) {
//
// Allocate a credential block and initialize it.
//
Credential = (PSSP_CREDENTIAL)NtLmAllocate(sizeof(SSP_CREDENTIAL) );
if ( Credential == NULL ) {
Status = STATUS_NO_MEMORY;
SspPrint((SSP_CRITICAL, "Error from NtLmAllocate 0x%lx\n", Status));
goto Cleanup;
}
Credential->References = 1;
Credential->ClientProcessID = ClientProcessID;
Credential->CredentialUseFlags = CredentialUseFlags;
Credential->Unlinked = FALSE;
if ( ( CallInfo.Attributes & SECPKG_CALL_KERNEL_MODE ) != 0 )
{
Credential->KernelClient = TRUE ;
}
else
{
Credential->KernelClient = FALSE ;
}
//
// Stick the token and logon ID in the credential
//
Credential->ClientTokenHandle = *TokenHandle;
//
// If the supplied access token is NULL, and the supplied LogonId
// specifies the SYSTEM account, then we need to pickup a copy of
// the SYSTEM access token. This is required so subsequent calls
// so usage of that credential can be treated as Local. Otherwise,
// subsequent calls in this scenario get treated as Anonymous
// (no accesstoken, null creds)
// See SsprHandleFirstCall() where it checks for NULL ClientTokenHandle
// and NULL buffers for logic behind local calls.
//
if( Credential->ClientTokenHandle == NULL ) {
LUID LogonIdSystem = SYSTEM_LUID ;
//
// do this only for SYSTEM originated calls when no creds specified.
//
if( RtlEqualLuid( LogonId, &LogonIdSystem ) &&
NtLmGlobalAccessTokenSystem &&
DomainName && DomainName->Buffer == NULL &&
UserName && UserName->Buffer == NULL &&
Password && Password->Buffer == NULL
) {
Status = SspDuplicateToken(
NtLmGlobalAccessTokenSystem,
SecurityImpersonation,
&(Credential->ClientTokenHandle)
);
}
}
//
// for loopback, enable all privileges in token to be consistent
// with kerberos and ntlm network logon.
//
if( (Credential->ClientTokenHandle != NULL) &&
!(CredentialUseFlags & NTLM_CRED_NULLSESSION) &&
(DomainName == NULL || DomainName->Length == 0) &&
(UserName == NULL || UserName->Length == 0) &&
(Password == NULL || Password->Length == 0)
)
{
if(!EnableAllPrivileges( Credential->ClientTokenHandle )) {
SspPrint((SSP_CRITICAL, "Failed to EnableAllPrivileges for loopback logon %lx\n", Credential->ClientTokenHandle));
}
}
//
// so we don't close it in SpAcquireCredentialsHandle
//
if( NT_SUCCESS( Status ) )
*TokenHandle = NULL;
Credential->LogonId = *LogonId;
//
// Stick the supplemental credentials into the credential.
//
if (ARGUMENT_PRESENT(DomainName))
{
Credential->DomainName = *DomainName;
}
if (ARGUMENT_PRESENT(UserName))
{
Credential->UserName = *UserName;
}
if (ARGUMENT_PRESENT(Password))
{
SspHidePassword(Password);
Credential->Password = *Password;
}
//
// Add it to the list of valid credential handles.
//
EnterCriticalSection( &SspCredentialCritSect );
InsertHeadList( &SspCredentialList, &Credential->Next );
LeaveCriticalSection( &SspCredentialCritSect );
SspPrint((SSP_API_MORE, "Added Credential 0x%lx\n", Credential ));
//
// Don't bother dereferencing because we already set the
// reference count to 1.
//
}
//
// Return output parameters to the caller.
//
*CredentialHandle = (LSA_SEC_HANDLE) Credential;
*Lifetime = NtLmGlobalForever;
Cleanup:
if ( !NT_SUCCESS(Status) ) {
if ( Credential != NULL ) {
(VOID)NtLmFree( Credential );
}
}
SspPrint((SSP_API_MORE, "Leaving SsprAcquireCredentialHandle\n"));
return Status;
}
NTSTATUS
SsprFreeCredentialHandle(
IN ULONG_PTR CredentialHandle
)
/*++
Routine Description:
This API is used to notify the security system that the credentials are
no longer needed and allows the application to free the handle acquired
in the call described above. When all references to this credential
set has been removed then the credentials may themselves be removed.
Arguments:
CredentialHandle - Credential Handle obtained through
AcquireCredentialHandle.
Return Value:
STATUS_SUCCESS -- Call completed successfully
SEC_E_NO_SPM -- Security Support Provider is not running
STATUS_INVALID_HANDLE -- Credential Handle is invalid
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PSSP_CREDENTIAL Credential;
SspPrint(( SSP_API_MORE, "SspFreeCredentialHandle Entered\n" ));
//
// Find the referenced credential and delink it.
//
Status = SspCredentialReferenceCredential(
CredentialHandle,
TRUE, // remove the instance of the credential
FALSE,
&Credential );
if ( !NT_SUCCESS( 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 );
//
// Free and locally used resources.
//
Cleanup:
SspPrint(( SSP_API_MORE, "SspFreeCredentialHandle returns 0x%lx\n", Status ));
return Status;
}
NTSTATUS
SspCredentialInitialize(
VOID
)
/*++
Routine Description:
This function initializes this module.
Arguments:
None.
Return Value:
Status of the operation.
--*/
{
//
// Initialize the Credential list to be empty.
//
InitializeCriticalSection(&SspCredentialCritSect);
InitializeListHead( &SspCredentialList );
return STATUS_SUCCESS;
}
VOID
SspCredentialTerminate(
VOID
)
/*++
Routine Description:
This function cleans up any dangling credentials.
Arguments:
None.
Return Value:
Status of the operation.
--*/
{
NTSTATUS Status ;
//
// Drop any lingering Credentials
//
EnterCriticalSection( &SspCredentialCritSect );
while ( !IsListEmpty( &SspCredentialList ) ) {
ULONG_PTR CredentialHandle;
PSSP_CREDENTIAL Credential;
CredentialHandle =
(LSA_SEC_HANDLE) CONTAINING_RECORD( SspCredentialList.Flink,
SSP_CREDENTIAL,
Next );
//
// note: we don't need to release and re-enter critsec because
// the same thread can Enter and Leave a critical section multiple
// times without dead-locking.
//
Status = SspCredentialReferenceCredential(
CredentialHandle,
TRUE,
TRUE,
&Credential ); // Remove Credential
if ( Credential != NULL ) {
SspCredentialDereferenceCredential(Credential);
}
}
LeaveCriticalSection( &SspCredentialCritSect );
//
// Delete the critical section
//
DeleteCriticalSection(&SspCredentialCritSect);
return;
}
BOOL
EnableAllPrivileges(
IN HANDLE ClientTokenHandle
)
{
PTOKEN_PRIVILEGES pPrivileges;
BYTE FastBuffer[ 512 ];
PBYTE SlowBuffer = NULL;
DWORD cbPrivileges;
BOOL fSuccess;
pPrivileges = (PTOKEN_PRIVILEGES)FastBuffer;
cbPrivileges = sizeof( FastBuffer );
fSuccess = GetTokenInformation(
ClientTokenHandle,
TokenPrivileges,
pPrivileges,
cbPrivileges,
&cbPrivileges
);
if( !fSuccess ) {
if( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
return FALSE;
SlowBuffer = (PBYTE)NtLmAllocate( cbPrivileges );
if( SlowBuffer == NULL )
return FALSE;
pPrivileges = (PTOKEN_PRIVILEGES)SlowBuffer;
fSuccess = GetTokenInformation(
ClientTokenHandle,
TokenPrivileges,
pPrivileges,
cbPrivileges,
&cbPrivileges
);
}
if( fSuccess && pPrivileges->PrivilegeCount != 0 ) {
DWORD indexPrivilege;
for( indexPrivilege = 0 ;
indexPrivilege < pPrivileges->PrivilegeCount ;
indexPrivilege ++ )
{
pPrivileges->Privileges[ indexPrivilege ].Attributes |=
SE_PRIVILEGE_ENABLED;
}
fSuccess = AdjustTokenPrivileges(
ClientTokenHandle,
FALSE,
pPrivileges,
0,
NULL,
NULL
);
if( fSuccess && GetLastError() != ERROR_SUCCESS )
fSuccess = FALSE;
}
if( SlowBuffer )
NtLmFree( SlowBuffer );
return fSuccess;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -