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.
913 lines
24 KiB
913 lines
24 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
aucred.c
|
|
|
|
Abstract:
|
|
|
|
This module provides credential management services within the
|
|
LSA subsystem. Some of these services are indirectly available for use
|
|
by authentication packages.
|
|
|
|
Author:
|
|
|
|
Jim Kelly (JimK) 27-February-1991
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <lsapch2.h>
|
|
|
|
RTL_RESOURCE AuCredLock ;
|
|
|
|
#define AuReadLockCreds() RtlAcquireResourceShared( &AuCredLock, TRUE );
|
|
#define AuWriteLockCreds() RtlAcquireResourceExclusive( &AuCredLock, TRUE );
|
|
#define AuUnlockCreds() RtlReleaseResource( &AuCredLock );
|
|
|
|
NTSTATUS
|
|
LsapInitializeCredentials(
|
|
VOID
|
|
)
|
|
{
|
|
__try {
|
|
RtlInitializeResource( &AuCredLock );
|
|
return STATUS_SUCCESS;
|
|
} __except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAddCredential(
|
|
IN PLUID LogonId,
|
|
IN ULONG AuthenticationPackage,
|
|
IN PSTRING PrimaryKeyValue,
|
|
IN PSTRING Credentials
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service is used by authentication packages to add credentials to a
|
|
logon session. These credentials may later be referenced using
|
|
GetCredentials().
|
|
|
|
This service acquires the AuLock.
|
|
|
|
Arguments:
|
|
|
|
LogonId - The session ID of logon session to add credentials to.
|
|
|
|
AuthenticationPackage - The authentication package ID of the
|
|
calling authentication package. This was received in the
|
|
InitializePackage() call during DLL initialization.
|
|
|
|
PrimaryKeyValue - Points to a string containing a value that the
|
|
authentication package will later want to reference as a
|
|
primary key of the credential data. This may be used, for
|
|
example, to keep the name of the domain or server the
|
|
credentials are related to. The format and meaning of this
|
|
string are authentication package-specific. Note that the
|
|
string value does not have to be unique, even for the
|
|
specified logon session. For example, there could be two
|
|
passwords for the same domain, each with the passwords stored
|
|
as credentials and the domain name stored as the primary key.
|
|
|
|
Credentials - Points to a string containing data representing
|
|
user credentials. The format and meaning of this string are
|
|
authentication package-specific.
|
|
|
|
Return Status:
|
|
|
|
STATUS_SUCCESS - The credentials were successfully added.
|
|
|
|
STATUS_NO_SUCH_LOGON_SESSION - The specified logon session could
|
|
not be found.
|
|
|
|
--*/
|
|
|
|
{
|
|
PLSAP_LOGON_SESSION LogonSession;
|
|
PLSAP_PACKAGE_CREDENTIALS Package;
|
|
PLSAP_CREDENTIALS NewCredentials = NULL;
|
|
USHORT MaxPrimary;
|
|
USHORT MaxCredentials;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
//
|
|
// Get a pointer to the logon session
|
|
//
|
|
|
|
LogonSession = LsapLocateLogonSession( LogonId );
|
|
|
|
if ( LogonSession == NULL ) {
|
|
|
|
return STATUS_NO_SUCH_LOGON_SESSION;
|
|
}
|
|
|
|
//
|
|
// Allocate blocks needed to represent this credential
|
|
// and copy the primary key and credential strings.
|
|
//
|
|
|
|
MaxPrimary = ROUND_UP_COUNT((PrimaryKeyValue->Length+sizeof(CHAR)), ALIGN_WORST);
|
|
MaxCredentials = ROUND_UP_COUNT((Credentials->Length+sizeof(CHAR)), ALIGN_WORST);
|
|
|
|
NewCredentials = LsapAllocatePrivateHeap( (ULONG)sizeof(LSAP_CREDENTIALS) +
|
|
MaxPrimary +
|
|
MaxCredentials
|
|
);
|
|
|
|
if ( NewCredentials == NULL )
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
NewCredentials->PrimaryKey.MaximumLength = MaxPrimary;
|
|
NewCredentials->PrimaryKey.Buffer = (PSTR)(NewCredentials+1);
|
|
|
|
NewCredentials->Credentials.MaximumLength = MaxCredentials;
|
|
NewCredentials->Credentials.Buffer = NewCredentials->PrimaryKey.Buffer +
|
|
NewCredentials->PrimaryKey.MaximumLength;
|
|
RtlCopyString( &NewCredentials->PrimaryKey, PrimaryKeyValue );
|
|
RtlCopyString( &NewCredentials->Credentials, Credentials );
|
|
|
|
//
|
|
// Now get a pointer to the Package's credentials
|
|
// (create one if necessary)
|
|
//
|
|
|
|
AuWriteLockCreds();
|
|
|
|
Package = LsapGetPackageCredentials(
|
|
LogonSession,
|
|
AuthenticationPackage,
|
|
TRUE
|
|
);
|
|
|
|
if ( !Package )
|
|
{
|
|
AuUnlockCreds();
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// insert new credentials in list.
|
|
//
|
|
|
|
NewCredentials->NextCredentials = Package->Credentials;
|
|
|
|
Package->Credentials = NewCredentials;
|
|
|
|
AuUnlockCreds();
|
|
LsapReleaseLogonSession( LogonSession );
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
Cleanup:
|
|
|
|
LsapReleaseLogonSession( LogonSession );
|
|
|
|
if ( NewCredentials )
|
|
{
|
|
if ( NewCredentials->PrimaryKey.Buffer )
|
|
{
|
|
ZeroMemory( NewCredentials->PrimaryKey.Buffer,
|
|
NewCredentials->PrimaryKey.Length );
|
|
}
|
|
|
|
if ( NewCredentials->Credentials.Buffer )
|
|
{
|
|
ZeroMemory( NewCredentials->Credentials.Buffer,
|
|
NewCredentials->Credentials.Length );
|
|
}
|
|
|
|
LsapFreePrivateHeap( NewCredentials );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapGetCredentials(
|
|
IN PLUID LogonId,
|
|
IN ULONG AuthenticationPackage,
|
|
IN OUT PULONG QueryContext,
|
|
IN BOOLEAN RetrieveAllCredentials,
|
|
IN PSTRING PrimaryKeyValue,
|
|
OUT PULONG PrimaryKeyLength,
|
|
IN PSTRING Credentials
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service is used by authentication packages to retrieve credentials
|
|
associated with a logon session. It is expected that each authentication
|
|
package will provide its own version of this service to its "clients".
|
|
For example, the MSV1_0 authentication package will provide services for
|
|
the LM Redirector to retrieve credentials (and probably establish them)
|
|
for remote accesses. These authentication package level services may be
|
|
implemented using the LsaCallAuthenticationPackage() API.
|
|
|
|
This service acquires the AuLock.
|
|
|
|
Arguments:
|
|
|
|
LogonId - The session ID of logon session from which credentials
|
|
are to be retrieved.
|
|
|
|
AuthenticationPackage - The authentication package ID of the
|
|
calling authentication package. Authentication packages
|
|
should only retrieve their own credentials.
|
|
|
|
QueryContext - A context value used across successive calls to
|
|
retrieve multiple credentials. The first time this service
|
|
is used, the value pointed to by this argument should be
|
|
zero. Thereafter, this value will be updated to allow
|
|
retrieval to continue where it left off. This value should,
|
|
therefore, not be changed until all credentials of a given
|
|
query operation have been retrieved.
|
|
|
|
RetrieveAllCredentials - A boolean value indicating whether all
|
|
credentials for the specified logon session should be
|
|
retrieved (TRUE), or only those matching the specified
|
|
PrimaryKeyValue (FALSE).
|
|
|
|
PrimaryKeyValue - This parameter serves two purposes. If the
|
|
RetrieveAllCredentials argument is FALSE, then this string
|
|
contains the value to use as a primary key lookup value. In
|
|
this case, only credentials whose primary key matches this
|
|
one (and belonging to the correct logon session) will be
|
|
retrieved. If, however, the RetrieveAllCredentials argument
|
|
is FALSE, then the value of this string are ignored. In this
|
|
case, the primary key value of each retrieved credential will
|
|
be returned in this string.
|
|
|
|
PrimaryKeyLength - If the RetrieveAllCredentials argument value
|
|
is FALSE, then this argument receives the length needed to
|
|
store the PrimaryKeyValue. If this value is larger than the
|
|
length of the PrimaryKeyValue string, then
|
|
STATUS_BUFFER_OVERFLOW is returned and no data is retrieved.
|
|
|
|
Credentials - Points to a string whose buffer is to be set to
|
|
contain the retrieved credential.
|
|
|
|
Return Status:
|
|
|
|
STATUS_MORE_ENTRIES - Credentials were successfully retrieved,
|
|
and there are more available.
|
|
|
|
STATUS_SUCCESS - Credentials were successfully retrieved and
|
|
there are no more available.
|
|
|
|
STATUS_UNSUCCESSFUL - No more credentials are available. If
|
|
returned on the first call, then there are no credentials
|
|
matching the selection criteria.
|
|
|
|
STATUS_NO_SUCH_LOGON_SESSION - The specified logon session could
|
|
not be found.
|
|
|
|
STATUS_BUFFER_OVERFLOW - Indicates the string provided to receive
|
|
the PrimaryKeyValue was not large enough to hold the data.
|
|
In this case, no data was retrieved. However, the length value
|
|
is returned so that appropriately sized buffer can be passed in
|
|
a successive call.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// NOTE: The QueryContext value is an index of the last retrieved
|
|
// credential matching the selection criteria. To continue
|
|
// a search for successive credentials, skip QueryContext
|
|
// number of entries first.
|
|
//
|
|
// This has the problem of changes between calls screwing
|
|
// up the result of successive calls. That's tough.
|
|
//
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PLSAP_LOGON_SESSION LogonSession;
|
|
PLSAP_PACKAGE_CREDENTIALS Package;
|
|
PLSAP_CREDENTIALS NextCredentials;
|
|
ULONG i;
|
|
BOOLEAN SelectionMatch;
|
|
|
|
//
|
|
// Get a pointer to the logon session
|
|
//
|
|
|
|
LogonSession = LsapLocateLogonSession( LogonId );
|
|
|
|
if ( LogonSession == NULL ) {
|
|
|
|
return STATUS_NO_SUCH_LOGON_SESSION;
|
|
}
|
|
|
|
AuReadLockCreds();
|
|
|
|
//
|
|
// Now get a pointer to the Package's credentials
|
|
//
|
|
|
|
Package = LsapGetPackageCredentials(
|
|
LogonSession,
|
|
AuthenticationPackage,
|
|
FALSE
|
|
);
|
|
|
|
if ( Package == NULL ) {
|
|
|
|
AuUnlockCreds();
|
|
|
|
LsapReleaseLogonSession( LogonSession );
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// skip the credentials already evaluated in previous calls...
|
|
//
|
|
|
|
i = (*QueryContext);
|
|
NextCredentials = Package->Credentials;
|
|
while ( i > 0 ) {
|
|
|
|
//
|
|
// See if we have reached the end of the list
|
|
//
|
|
|
|
if (NextCredentials == NULL) {
|
|
|
|
AuUnlockCreds();
|
|
|
|
LsapReleaseLogonSession( LogonSession );
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Nope, skip the next one...
|
|
//
|
|
|
|
NextCredentials = NextCredentials->NextCredentials;
|
|
i -= 1;
|
|
}
|
|
|
|
//
|
|
// Start evaluating each credential for a criteria match.
|
|
//
|
|
|
|
SelectionMatch = FALSE;
|
|
while ( NextCredentials != NULL && !SelectionMatch ) {
|
|
|
|
(*QueryContext) += 1;
|
|
|
|
if (RetrieveAllCredentials) {
|
|
|
|
SelectionMatch = TRUE;
|
|
Status = LsapReturnCredential(
|
|
NextCredentials,
|
|
Credentials,
|
|
TRUE,
|
|
PrimaryKeyValue,
|
|
PrimaryKeyLength
|
|
);
|
|
}
|
|
|
|
//
|
|
// Only retrieving credentials that match the specified primary
|
|
// key.
|
|
//
|
|
|
|
if ( RtlEqualString( &NextCredentials->PrimaryKey, PrimaryKeyValue, FALSE) ) {
|
|
|
|
SelectionMatch = TRUE;
|
|
Status = LsapReturnCredential(
|
|
NextCredentials,
|
|
Credentials,
|
|
FALSE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
NextCredentials = NextCredentials->NextCredentials;
|
|
}
|
|
|
|
AuUnlockCreds();
|
|
|
|
LsapReleaseLogonSession( LogonSession );
|
|
|
|
//
|
|
// Figure out what return value to send.
|
|
//
|
|
|
|
if (SelectionMatch) {
|
|
|
|
if ( Status == STATUS_BUFFER_OVERFLOW ) {
|
|
(*QueryContext) -= 1;
|
|
return STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
if ( Status == STATUS_SUCCESS) {
|
|
if ( NextCredentials == NULL ) {
|
|
return STATUS_SUCCESS;
|
|
} else {
|
|
return STATUS_MORE_ENTRIES;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// didn't find a credential matching the selection criteria.
|
|
//
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
return STATUS_UNSUCCESSFUL ;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapReturnCredential(
|
|
IN PLSAP_CREDENTIALS SourceCredentials,
|
|
IN PSTRING TargetCredentials,
|
|
IN BOOLEAN ReturnPrimaryKey,
|
|
IN PSTRING PrimaryKeyValue OPTIONAL,
|
|
OUT PULONG PrimaryKeyLength OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns a copy of the credentials in the specified
|
|
credential record. It also, optionally, returns a copy of the
|
|
primary key value.
|
|
|
|
Arguments:
|
|
|
|
SourceCredentials - Points to a credential record whose credential
|
|
string and, optionally, primary key are to be copied.
|
|
|
|
TargetCredentials - Points to a string whose buffer is to be set to
|
|
contain a copy of the credential. This copy will be allocated
|
|
using LsapAllocateLsaHeap().
|
|
|
|
ReturnPrimaryKey - A boolean indicating whether or not to return
|
|
a copy of the primary key. TRUE indicates a copy should be
|
|
returned. FALSE indicates a copy should not be returned.
|
|
|
|
PrimaryKeyValue - Points to a string whose buffer is to be set to
|
|
contain a copy of the primary key. This copy will be allocated
|
|
using LsapAllocateLsaHeap(). This parameter is ignored if the
|
|
ReturnPrimaryKey argument value is FALSE.
|
|
|
|
|
|
PrimaryKeyLength - Points to a value which will receive the
|
|
length of the primary key value. If this value is larger than the
|
|
length of the PrimaryKeyValue string, then STATUS_BUFFER_OVERFLOW
|
|
is returned and no data is retrieved.
|
|
|
|
|
|
|
|
Return Status:
|
|
|
|
STATUS_SUCCESS - Credentials were successfully returned.
|
|
|
|
STATUS_BUFFER_OVERFLOW - Indicates the string provided to receive
|
|
the PrimaryKeyValue was not large enough to hold the data.
|
|
In this case, no data was retrieved. However, the length value
|
|
is returned so that appropriately sized buffer can be passed in
|
|
a successive call.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Length;
|
|
|
|
//
|
|
// First try to return the primary key value, since we can encounter
|
|
// a buffer overflow situation in doing so that would prevent us from
|
|
// returning a copy of the credential string.
|
|
//
|
|
|
|
if (ReturnPrimaryKey) {
|
|
(*PrimaryKeyLength) = SourceCredentials->PrimaryKey.Length + 1;
|
|
if ( (*PrimaryKeyLength) > PrimaryKeyValue->MaximumLength ) {
|
|
return STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
//
|
|
// It fits
|
|
//
|
|
|
|
RtlCopyString( PrimaryKeyValue, &SourceCredentials->PrimaryKey );
|
|
}
|
|
|
|
//
|
|
// Now allocate and copy the credential string copy.
|
|
//
|
|
|
|
TargetCredentials->MaximumLength = SourceCredentials->Credentials.Length
|
|
+ (USHORT)1;
|
|
|
|
Length = (ULONG)TargetCredentials->MaximumLength;
|
|
|
|
TargetCredentials->Buffer = (PCHAR)LsapAllocateLsaHeap( Length );
|
|
|
|
if ( TargetCredentials->Buffer )
|
|
{
|
|
RtlCopyString( TargetCredentials, &SourceCredentials->Credentials );
|
|
|
|
return STATUS_SUCCESS ;
|
|
}
|
|
else
|
|
{
|
|
return STATUS_NO_MEMORY ;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapDeleteCredential(
|
|
IN PLUID LogonId,
|
|
IN ULONG AuthenticationPackage,
|
|
IN PSTRING PrimaryKeyValue
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service is used to delete an existing credential. This service
|
|
deletes the first credential it finds with a matching logon session,
|
|
authentication package ID, and primary key value. If thee are
|
|
multiple credentials that match this criteria, only one of them is
|
|
deleted.
|
|
|
|
This status acquires the AuLock.
|
|
|
|
Arguments:
|
|
|
|
LogonId - The session ID of logon session whose credentials are to be
|
|
deleted.
|
|
|
|
AuthenticationPackage - The authentication package ID of the
|
|
calling authentication package. This was received in the
|
|
InitializePackage() call during DLL initialization.
|
|
|
|
PrimaryKeyValue - Points to string containing the primary key value
|
|
of the credential to be deleted.
|
|
|
|
Return Status:
|
|
|
|
STATUS_SUCCESS - The credentials were successfully deleted.
|
|
|
|
STATUS_NO_SUCH_LOGON_SESSION - The specified logon session could
|
|
not be found.
|
|
|
|
STATUS_UNSUCCESSFUL - No such credential could be found.
|
|
|
|
--*/
|
|
|
|
{
|
|
PLSAP_LOGON_SESSION LogonSession;
|
|
PLSAP_PACKAGE_CREDENTIALS Package;
|
|
PLSAP_CREDENTIALS *NextCredentials, GoodByeCredentials;
|
|
|
|
//
|
|
// Get a pointer to the logon session
|
|
//
|
|
|
|
LogonSession = LsapLocateLogonSession( LogonId );
|
|
|
|
if ( LogonSession == NULL ) {
|
|
|
|
return STATUS_NO_SUCH_LOGON_SESSION;
|
|
}
|
|
|
|
AuWriteLockCreds();
|
|
|
|
//
|
|
// Now get a pointer to the Package's credentials
|
|
//
|
|
|
|
Package = LsapGetPackageCredentials(
|
|
LogonSession,
|
|
AuthenticationPackage,
|
|
FALSE
|
|
);
|
|
|
|
if ( Package == NULL ) {
|
|
|
|
AuUnlockCreds();
|
|
|
|
LsapReleaseLogonSession( LogonSession );
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Start evaluating each credential for a primary key value match.
|
|
//
|
|
|
|
NextCredentials = &Package->Credentials;
|
|
while ( (*NextCredentials) != NULL ) {
|
|
|
|
if ( RtlEqualString(
|
|
&(*NextCredentials)->PrimaryKey,
|
|
PrimaryKeyValue,
|
|
FALSE)
|
|
) {
|
|
|
|
//
|
|
// remove it from the list
|
|
//
|
|
|
|
GoodByeCredentials = (*NextCredentials);
|
|
(*NextCredentials) = GoodByeCredentials->NextCredentials;
|
|
|
|
AuUnlockCreds();
|
|
|
|
LsapReleaseLogonSession( LogonSession );
|
|
|
|
//
|
|
// Zero the contents of the credential record.
|
|
//
|
|
|
|
if( GoodByeCredentials->PrimaryKey.Buffer != NULL )
|
|
{
|
|
SecureZeroMemory( GoodByeCredentials->PrimaryKey.Buffer,
|
|
GoodByeCredentials->PrimaryKey.Length );
|
|
}
|
|
|
|
if( GoodByeCredentials->Credentials.Buffer != NULL )
|
|
{
|
|
SecureZeroMemory( GoodByeCredentials->Credentials.Buffer,
|
|
GoodByeCredentials->Credentials.Length );
|
|
}
|
|
|
|
//
|
|
// Free the credential record itself.
|
|
//
|
|
|
|
LsapFreePrivateHeap( GoodByeCredentials );
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NextCredentials = &(*NextCredentials)->NextCredentials;
|
|
}
|
|
|
|
AuUnlockCreds();
|
|
|
|
LsapReleaseLogonSession( LogonSession );
|
|
|
|
//
|
|
// Nothing matched
|
|
//
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
|
|
PLSAP_PACKAGE_CREDENTIALS
|
|
LsapGetPackageCredentials(
|
|
IN PLSAP_LOGON_SESSION LogonSession,
|
|
IN ULONG PackageId,
|
|
IN BOOLEAN CreateIfNecessary
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service returns a pointer to a specified package's credential
|
|
record. If no such record exists, one will optionally be created.
|
|
|
|
It is assumed that either the LogonSession record is not currently
|
|
in the logon session record list, or, if it is, that the AuLock
|
|
is currently held.
|
|
|
|
Arguments:
|
|
|
|
LogonSession - Pointer to a logon session record within which to
|
|
work.
|
|
|
|
PackageId - The authentication package ID to look for.
|
|
|
|
CreateIfNecessary - A boolean indicating whether or not the package
|
|
record is to be created if one does not already exist. TRUE
|
|
indicates the package is to be created if necessary, FALSE indicates
|
|
the record should not be created.
|
|
|
|
|
|
Return Status:
|
|
|
|
non-NULL - A pointer to the specified package record.
|
|
|
|
NULL - The specified package record does not exist (and one was not
|
|
created automatically).
|
|
|
|
--*/
|
|
|
|
{
|
|
PLSAP_PACKAGE_CREDENTIALS *NextPackage, TargetPackage;
|
|
|
|
//
|
|
// See if the session exists
|
|
//
|
|
|
|
NextPackage = &LogonSession->Packages;
|
|
|
|
while ( (*NextPackage) != NULL) {
|
|
|
|
if ( (*NextPackage)->PackageId == PackageId ) {
|
|
|
|
//
|
|
// Found it
|
|
//
|
|
|
|
TargetPackage = (*NextPackage);
|
|
|
|
return TargetPackage;
|
|
}
|
|
|
|
//
|
|
// Move on to next package.
|
|
//
|
|
|
|
NextPackage = &(*NextPackage)->NextPackage;
|
|
}
|
|
|
|
//
|
|
// No such package exists yet.
|
|
// Create one if necessary.
|
|
|
|
if ( !CreateIfNecessary ) {
|
|
|
|
return NULL;
|
|
}
|
|
|
|
TargetPackage = LsapAllocateLsaHeap( (ULONG)sizeof(LSAP_PACKAGE_CREDENTIALS) );
|
|
|
|
if ( TargetPackage )
|
|
{
|
|
TargetPackage->PackageId = PackageId;
|
|
TargetPackage->Credentials = NULL;
|
|
TargetPackage->NextPackage = LogonSession->Packages;
|
|
LogonSession->Packages = TargetPackage;
|
|
}
|
|
|
|
return TargetPackage;
|
|
}
|
|
|
|
|
|
VOID
|
|
LsapFreePackageCredentialList(
|
|
IN PLSAP_PACKAGE_CREDENTIALS PackageCredentialList
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service frees a list of packge credential records. This service
|
|
is not expected to be exposed to authentication packages.
|
|
|
|
This service expects not to have to acquire the AuLock. This may be
|
|
because it is already held, or because the credentials being freed
|
|
are no longer accessible via the global variables.
|
|
|
|
Arguments:
|
|
|
|
PackageCredentialList - Is a pointer to a list of LSA_PACKAGE_CREDENTIALS
|
|
data structures.
|
|
|
|
|
|
Return Status:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PLSAP_PACKAGE_CREDENTIALS NextPackage, GoodByePackage;
|
|
|
|
//
|
|
// Get rid of each PACKAGE_CREDENTIAL record.
|
|
//
|
|
|
|
NextPackage = PackageCredentialList;
|
|
while ( NextPackage != NULL ) {
|
|
|
|
//
|
|
// Save a pointer to the next package
|
|
//
|
|
|
|
GoodByePackage = NextPackage;
|
|
NextPackage = GoodByePackage->NextPackage;
|
|
|
|
LsapFreeCredentialList( GoodByePackage->Credentials );
|
|
|
|
//
|
|
// Free the package record itself.
|
|
//
|
|
|
|
LsapFreeLsaHeap( GoodByePackage );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
LsapFreeCredentialList(
|
|
IN PLSAP_CREDENTIALS CredentialList
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service frees a list of credential records. This service is not
|
|
expected to be exposed to authentication packages.
|
|
|
|
This service expects not to have to acquire the AuLock. This may be
|
|
because it is already held, or because the credentials being freed
|
|
are no longer accessible via the global variables.
|
|
|
|
Arguments:
|
|
|
|
CredentialList - Is a pointer to a list of LSA_CREDENTIALS data
|
|
structures.
|
|
|
|
|
|
Return Status:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PLSAP_CREDENTIALS NextCredentials, GoodByeCredentials;
|
|
|
|
//
|
|
// Get rid of each PACKAGE_CREDENTIAL record.
|
|
//
|
|
|
|
NextCredentials = CredentialList;
|
|
while ( NextCredentials != NULL ) {
|
|
|
|
//
|
|
// Save a pointer to the next credential
|
|
//
|
|
|
|
GoodByeCredentials = NextCredentials;
|
|
NextCredentials = GoodByeCredentials->NextCredentials;
|
|
|
|
//
|
|
// Zero the contents of this credential record.
|
|
//
|
|
|
|
if( GoodByeCredentials->PrimaryKey.Buffer != NULL )
|
|
{
|
|
SecureZeroMemory( GoodByeCredentials->PrimaryKey.Buffer,
|
|
GoodByeCredentials->PrimaryKey.Length );
|
|
}
|
|
|
|
if( GoodByeCredentials->Credentials.Buffer != NULL )
|
|
{
|
|
SecureZeroMemory( GoodByeCredentials->Credentials.Buffer,
|
|
GoodByeCredentials->Credentials.Length );
|
|
}
|
|
|
|
//
|
|
// Free the credential record itself.
|
|
//
|
|
|
|
LsapFreePrivateHeap( GoodByeCredentials );
|
|
|
|
}
|
|
|
|
return;
|
|
}
|