Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3319 lines
81 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
adtifn.c
Abstract:
This file has functions exported to other trusted modules in LSA.
(LsaIAudit* functions)
Author:
16-August-2000 kumarp
--*/
#include <lsapch2.h>
#include "adtp.h"
#include "adtutil.h"
#include <md5.h>
#include <msobjs.h>
//
// local helper routines for filling in audit params
// from SAM's extended attributes.
//
VOID
LsapAdtAppendDomainAttrValues(
IN OUT PSE_ADT_PARAMETER_ARRAY pParameters,
IN PLSAP_AUDIT_DOMAIN_ATTR_VALUES pAttributes OPTIONAL
);
VOID
LsapAdtAppendUserAttrValues(
IN OUT PSE_ADT_PARAMETER_ARRAY pParameters,
IN PLSAP_AUDIT_USER_ATTR_VALUES pAttributes OPTIONAL,
IN BOOL MachineAudit
);
VOID
LsapAdtAppendGroupAttrValues(
IN OUT PSE_ADT_PARAMETER_ARRAY pParameters,
IN PLSAP_AUDIT_GROUP_ATTR_VALUES pAttributes OPTIONAL
);
//
// LSA interface functions.
//
NTSTATUS
LsaIGetLogonGuid(
IN PUNICODE_STRING pUserName,
IN PUNICODE_STRING pUserDomain,
IN PBYTE pBuffer,
IN UINT BufferSize,
OUT LPGUID pLogonGuid
)
/*++
Routine Description:
Concatenate pUserName->Buffer, pUserDomain->Buffer and pBuffer
into a single binary buffer. Get a MD5 hash of this concatenated
buffer and return it in the form of a GUID.
Arguments:
pUserName - name of user
pUserDomain - name of user domain
pBuffer - pointer to KERB_TIME structure. The caller casts this to
PBYTE and passes this to us. This allows us to keep KERB_TIME
structure private to kerberos and offer future extensibility,
should we decide to use another field from the ticket.
BufferSize - size of buffer (currently sizeof(KERB_TIME))
pLogonGuid - pointer to returned logon GUID
Return Value:
NTSTATUS - Standard Nt Result Code
Notes:
The generated GUID is recorded in the audit log in the form of
'Logon GUID' field in the following events:
* On client machine
-- SE_AUDITID_LOGON_USING_EXPLICIT_CREDENTIALS
* On KDC
-- SE_AUDITID_TGS_TICKET_REQUEST
* On target server
-- SE_AUDITID_NETWORK_LOGON
-- SE_AUDITID_SUCCESSFUL_LOGON
This allows us to correlate these events to aid in intrusion detection.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
UINT TempBufferLength=0;
//
// LSAI_TEMP_MD5_BUFFER_SIZE == UNLEN + DNS_MAX_NAME_LENGTH + sizeof(KERB_TIME) + padding
//
#define LSAI_TEMP_MD5_BUFFER_SIZE (256+256+16)
BYTE TempBuffer[LSAI_TEMP_MD5_BUFFER_SIZE];
MD5_CTX MD5Context = { 0 };
ASSERT( LsapIsValidUnicodeString( pUserName ) );
ASSERT( LsapIsValidUnicodeString( pUserDomain ) );
ASSERT( pBuffer && BufferSize );
#if DBG
// DbgPrint("LsaIGetLogonGuid: user: %wZ\\%wZ, buf: %I64x\n",
// pUserDomain, pUserName, *((ULONGLONG *) pBuffer));
#endif
TempBufferLength = pUserName->Length + pUserDomain->Length + BufferSize;
if ( TempBufferLength < LSAI_TEMP_MD5_BUFFER_SIZE )
{
//
// first concatenate user+domain+buffer and treat that as
// a contiguous buffer.
//
RtlCopyMemory( TempBuffer, pUserName->Buffer, pUserName->Length );
TempBufferLength = pUserName->Length;
RtlCopyMemory( TempBuffer + TempBufferLength,
pUserDomain->Buffer, pUserDomain->Length );
TempBufferLength += pUserDomain->Length;
RtlCopyMemory( TempBuffer + TempBufferLength,
pBuffer, BufferSize );
TempBufferLength += BufferSize;
//
// get MD5 hash of the concatenated buffer
//
MD5Init( &MD5Context );
MD5Update( &MD5Context, TempBuffer, TempBufferLength );
MD5Final( &MD5Context );
//
// return the hash as a GUID
//
RtlCopyMemory( pLogonGuid, MD5Context.digest, 16 );
Status = STATUS_SUCCESS;
}
else
{
ASSERT( FALSE && "LsaIGetLogonGuid: TempBuffer overflow");
Status = STATUS_BUFFER_OVERFLOW;
}
return Status;
}
VOID
LsaIAuditKerberosLogon(
IN NTSTATUS LogonStatus,
IN NTSTATUS LogonSubStatus,
IN PUNICODE_STRING AccountName,
IN PUNICODE_STRING AuthenticatingAuthority,
IN PUNICODE_STRING WorkstationName,
IN PSID UserSid, OPTIONAL
IN SECURITY_LOGON_TYPE LogonType,
IN PTOKEN_SOURCE TokenSource,
IN PLUID LogonId,
IN LPGUID LogonGuid,
IN PLSA_ADT_STRING_LIST TransittedServices
)
/*++
Routine Description/Arguments/Return value
See header comment for LsapAuditLogonHelper
Notes:
A new field (logon GUID) was added to this audit event.
In order to send this new field to LSA, we had two options:
1) add new function (AuditLogonEx) to LSA dispatch table
2) define a private (LsaI) function to do the job
option#2 was chosen because the logon GUID is a Kerberos only feature.
--*/
{
LsapAuditLogonHelper(
LogonStatus,
LogonSubStatus,
AccountName,
AuthenticatingAuthority,
WorkstationName,
UserSid,
LogonType,
TokenSource,
LogonId,
LogonGuid,
NULL, // caller logon-ID
NULL, // caller process-ID
TransittedServices
);
}
NTSTATUS
LsaIAuditLogonUsingExplicitCreds(
IN USHORT AuditEventType,
IN PLUID pUser1LogonId,
IN LPGUID pUser1LogonGuid, OPTIONAL
IN HANDLE User1ProcessId,
IN PUNICODE_STRING pUser2Name,
IN PUNICODE_STRING pUser2Domain,
IN LPGUID pUser2LogonGuid,
IN PUNICODE_STRING pTargetName, OPTIONAL
IN PUNICODE_STRING pTargetInfo OPTIONAL
)
/*++
Routine Description:
This event is generated by Kerberos package when a logged on user
(pUser1*) supplies explicit credentials of another user (pUser2*) and
creates a new logon session either locally or on a remote machine.
Parmeters:
AuditEventType - EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE
pUser1LogonId - logon-id of user1
pUser1LogonGuid - logon GUID of user1
This is NULL if user1 logged on using NTLM.
(NTLM does not support logon GUID)
pUser2Name - name of user2
NULL ==> ANONYMOUS
pUser2Domain - domain of user2
pUser2LogonGuid - logon-id of user2
pTargetName - name of the logon target machine
pTargetInfo - additional info (such as SPN) of the target
Return Value:
NTSTATUS - Standard Nt Result Code
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
SE_ADT_PARAMETER_ARRAY AuditParameters;
BOOLEAN bAudit;
PSID pUser1Sid = NULL;
PUNICODE_STRING pUser1Name = NULL;
PUNICODE_STRING pUser1Domain = NULL;
UNICODE_STRING usUser2Name = {0};
UNICODE_STRING usUser2Domain = {0};
PLSAP_LOGON_SESSION pUser1LogonSession = NULL;
GUID NullGuid = { 0 };
LUID LocalSystemLuid = SYSTEM_LUID;
LUID AnonymousLuid = ANONYMOUS_LOGON_LUID;
PLSA_CALL_INFO pCallInfo;
SOCKADDR* pSockAddr = NULL;
//
// get the IP address/port of the caller
//
pCallInfo = LsapGetCurrentCall();
DsysAssertMsg( pCallInfo != NULL, "LsapAuditLogon" );
pSockAddr = (SOCKADDR*) pCallInfo->IpAddress;
ASSERT( pUser1LogonId );
if ( pTargetName )
{
ASSERT( pTargetName->Buffer && pTargetName->Length );
}
if ( pTargetInfo )
{
ASSERT( pTargetInfo->Buffer && pTargetInfo->Length );
}
//
// if policy is not enabled then return quickly.
//
Status = LsapAdtAuditingEnabledByLogonId(
AuditCategoryLogon,
pUser1LogonId,
AuditEventType,
&bAudit);
if (!NT_SUCCESS(Status) || !bAudit)
{
goto Cleanup;
}
//
// Sanity check the strings we got passed since they might come from
// NTLM and not be validated yet.
//
if (pUser2Name)
{
usUser2Name = *pUser2Name;
usUser2Name.Length =
(USHORT)LsapSafeWcslen(usUser2Name.Buffer,
usUser2Name.MaximumLength);
}
pUser2Name = &usUser2Name;
if (pUser2Domain)
{
usUser2Domain = *pUser2Domain;
usUser2Domain.Length =
(USHORT)LsapSafeWcslen(usUser2Domain.Buffer,
usUser2Domain.MaximumLength);
}
pUser2Domain = &usUser2Domain;
//
// Locate the logon-session of user1 so that we can obtain
// name/domain/sid info from it.
//
pUser1LogonSession = LsapLocateLogonSession( pUser1LogonId );
if ( pUser1LogonSession )
{
pUser1Sid = pUser1LogonSession->UserSid;
pUser1Name = &pUser1LogonSession->AccountName;
pUser1Domain = &pUser1LogonSession->AuthorityName;
//
// We have implicit credentials if:
// 1) UserName and DomainName are NULL
// 2) and logon type is not NewCredentials
//
if (!pUser2Name->Buffer && !pUser2Domain->Buffer)
{
if (pUser1LogonSession->LogonType == NewCredentials)
{
pUser2Name = &pUser1LogonSession->NewAccountName;
pUser2Domain = &pUser1LogonSession->NewAuthorityName;
}
else
{
// not an explict cred
Status = STATUS_SUCCESS;
goto Cleanup;
}
}
//
// Handle ambiguous credentials where NTLM supplies NULL username or
// domain name.
//
if (!pUser2Name->Buffer)
{
pUser2Name = &pUser1LogonSession->AccountName;
}
if (!pUser2Domain->Buffer)
{
pUser2Domain = &pUser1LogonSession->AuthorityName;
}
//
// This is an additional check to see whether we are dealing with implicit creds.
// It works well for NTLM but might not catch all instances with Kerberos where
// DNS names are preferred.
//
if (RtlEqualUnicodeString(pUser2Name, &pUser1LogonSession->AccountName, TRUE)
&& RtlEqualUnicodeString(pUser2Domain, &pUser1LogonSession->AuthorityName, TRUE))
{
// not an explict cred
Status = STATUS_SUCCESS;
goto Cleanup;
}
if ( pUser1LogonGuid &&
memcmp( pUser1LogonGuid, &NullGuid, sizeof(GUID)) )
{
//
// if the logon GUID in the logon session is null and
// if the passed logon GUID is not null
// update its value using what is passed to this function
//
if ( !memcmp( &pUser1LogonSession->LogonGuid, &NullGuid, sizeof(GUID)))
{
Status = LsaISetLogonGuidInLogonSession(
pUser1LogonId,
pUser1LogonGuid
);
}
}
else
{
pUser1LogonGuid = &pUser1LogonSession->LogonGuid;
}
}
//
// skip the audits for local-system changing to local/network service
//
if ( RtlEqualLuid( pUser1LogonId, &LocalSystemLuid ) &&
LsapIsLocalOrNetworkService( pUser2Name, pUser2Domain ) )
{
Status = STATUS_SUCCESS;
goto Cleanup;
}
//
// skip the audits for anonymous changing to anonymous
//
// for anonymous user, the passed name/domain is null/empty
//
if ( RtlEqualLuid( pUser1LogonId, &AnonymousLuid ) )
{
if (((!pUser2Name || !pUser2Name->Length) && (!pUser2Domain || !pUser2Domain->Length)) ||
LsapIsAnonymous(pUser2Name, pUser2Domain))
{
Status = STATUS_SUCCESS;
goto Cleanup;
}
}
Status =
LsapAdtInitParametersArray(
&AuditParameters,
SE_CATEGID_LOGON,
SE_AUDITID_LOGON_USING_EXPLICIT_CREDENTIALS,
AuditEventType,
11, // there are 11 params to init
//
// User Sid
//
SeAdtParmTypeSid, pUser1Sid ? pUser1Sid : LsapLocalSystemSid,
//
// Subsystem name
//
SeAdtParmTypeString, &LsapSubsystemName,
//
// current user logon id
//
SeAdtParmTypeLogonId, *pUser1LogonId,
//
// user1 logon GUID
//
SeAdtParmTypeGuid, pUser1LogonGuid,
//
// user2 name
//
SeAdtParmTypeString, pUser2Name,
//
// user2 domain name
//
SeAdtParmTypeString, pUser2Domain,
//
// user2 logon GUID
//
SeAdtParmTypeGuid, pUser2LogonGuid,
//
// target server name
//
SeAdtParmTypeString, pTargetName,
//
// target server info (such as SPN)
//
SeAdtParmTypeString, pTargetInfo,
//
// Caller Process ID
//
SeAdtParmTypePtr, User1ProcessId,
//
// IP address/port info
//
SeAdtParmTypeSockAddr, pSockAddr
);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
( VOID ) LsapAdtWriteLog( &AuditParameters );
Cleanup:
if ( pUser1LogonSession )
{
LsapReleaseLogonSession( pUser1LogonSession );
}
if (!NT_SUCCESS(Status)) {
LsapAuditFailed( Status );
}
return Status;
}
NTSTATUS
LsaIAdtAuditingEnabledByCategory(
IN POLICY_AUDIT_EVENT_TYPE Category,
IN USHORT AuditEventType,
IN PSID pUserSid OPTIONAL,
IN PLUID pLogonId OPTIONAL,
OUT PBOOLEAN pbAudit
)
/*++
Routine Description:
Returns whether auditing is enabled for the given category - event
type - user combination. The user can be supplied as sid or logon id.
If none is supplied, the general settings (not user specific) are returned.
If both are supplied, the sid takes precedence and the logon id is ignored.
Parmeters:
Category - Category to be queried
AuditEventType - EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE
pUserSid - sid of user
pLogonId - logon-id of user
pbAudit - returns whether auditing is enabled for the requested parameters
Return Value:
NTSTATUS - Standard Nt Result Code
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
if (pUserSid)
{
Status = LsapAdtAuditingEnabledBySid(
Category,
pUserSid,
AuditEventType,
pbAudit
);
}
else if (pLogonId)
{
Status = LsapAdtAuditingEnabledByLogonId(
Category,
pLogonId,
AuditEventType,
pbAudit
);
}
else
{
*pbAudit = LsapAdtAuditingEnabledByCategory(
Category,
AuditEventType
);
}
return Status;
}
NTSTATUS
LsaIAuditKdcEvent(
IN ULONG AuditId,
IN PUNICODE_STRING ClientName,
IN PUNICODE_STRING ClientDomain,
IN PSID ClientSid,
IN PUNICODE_STRING ServiceName,
IN PSID ServiceSid,
IN PULONG KdcOptions,
IN PULONG KerbStatus,
IN PULONG EncryptionType,
IN PULONG PreauthType,
IN PBYTE ClientAddress,
IN LPGUID LogonGuid OPTIONAL,
IN PLSA_ADT_STRING_LIST TransittedServices OPTIONAL,
IN PUNICODE_STRING CertIssuerName OPTIONAL,
IN PUNICODE_STRING CertSerialNumber OPTIONAL,
IN PUNICODE_STRING CertThumbprint OPTIONAL
)
/*++
Abstract:
This routine produces an audit record representing a KDC
operation.
This routine goes through the list of parameters and adds a string
representation of each (in order) to an audit message. Note that
the full complement of account audit message formats is achieved by
selecting which optional parameters to include in this call.
In addition to any parameters passed below, this routine will ALWAYS
add the impersonation client's user name, domain, and logon ID as
the LAST parameters in the audit message.
Parmeters:
AuditId - Specifies the message ID of the audit being generated.
ClientName -
ClientDomain -
ClientSid -
ServiceName -
ServiceSid -
KdcOptions -
KerbStatus -
EncryptionType -
PreauthType -
ClientAddress -
LogonGuid -
TransittedServices -
CertIssuerName -
CertSerialNumber -
CertThumbprint -
--*/
{
SE_ADT_PARAMETER_ARRAY AuditParameters;
UNICODE_STRING AddressString;
WCHAR AddressBuffer[3*4+4]; // space for a dotted-quad IP address
NTSTATUS Status;
BOOLEAN bAudit;
RtlZeroMemory (
(PVOID) &AuditParameters,
sizeof( AuditParameters )
);
AuditParameters.CategoryId = SE_CATEGID_ACCOUNT_LOGON;
AuditParameters.AuditId = AuditId;
AuditParameters.Type = ((ARGUMENT_PRESENT(KerbStatus) &&
(*KerbStatus != 0)) ?
EVENTLOG_AUDIT_FAILURE :
EVENTLOG_AUDIT_SUCCESS );
Status = LsapAdtAuditingEnabledBySid(
AuditCategoryAccountLogon,
ClientSid ? ClientSid : LsapLocalSystemSid,
AuditParameters.Type,
&bAudit
);
if (!NT_SUCCESS(Status) || !bAudit)
{
goto Cleanup;
}
AuditParameters.ParameterCount = 0;
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, LsapLocalSystemSid );
AuditParameters.ParameterCount++;
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LsapSubsystemName );
AuditParameters.ParameterCount++;
if (ARGUMENT_PRESENT(ClientName)) {
//
// Add a UNICODE_STRING to the audit message
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, ClientName );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(ClientDomain)) {
//
// Add a UNICODE_STRING to the audit message
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, ClientDomain );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(ClientSid)) {
//
// Add a SID to the audit message
//
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, ClientSid );
AuditParameters.ParameterCount++;
} else if (AuditId == SE_AUDITID_AS_TICKET) {
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(ServiceName)) {
//
// Add a UNICODE_STRING to the audit message
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, ServiceName );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(ServiceSid)) {
//
// Add a SID to the audit message
//
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, ServiceSid );
AuditParameters.ParameterCount++;
} else if (AuditId == SE_AUDITID_AS_TICKET || AuditId == SE_AUDITID_TGS_TICKET_REQUEST) {
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(KdcOptions)) {
//
// Add a ULONG to the audit message
//
LsapSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, *KdcOptions );
AuditParameters.ParameterCount++;
}
//
// Failure code is the last parameter for SE_AUDITID_TGS_TICKET_REQUEST
//
if (AuditId != SE_AUDITID_TGS_TICKET_REQUEST)
{
if (ARGUMENT_PRESENT(KerbStatus)) {
//
// Add a ULONG to the audit message
//
LsapSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, *KerbStatus );
AuditParameters.ParameterCount++;
} else if (AuditId == SE_AUDITID_AS_TICKET) {
AuditParameters.ParameterCount++;
}
}
if (ARGUMENT_PRESENT(EncryptionType)) {
//
// Add a ULONG to the audit message
//
LsapSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, *EncryptionType );
AuditParameters.ParameterCount++;
} else if (AuditId == SE_AUDITID_AS_TICKET || AuditId == SE_AUDITID_TGS_TICKET_REQUEST) {
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(PreauthType)) {
//
// Add a ULONG to the audit message
//
LsapSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, *PreauthType );
AuditParameters.ParameterCount++;
} else if (AuditId == SE_AUDITID_AS_TICKET) {
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(ClientAddress)) {
AddressBuffer[0] = L'\0';
swprintf(AddressBuffer,L"%d.%d.%d.%d",
ClientAddress[0],
(ULONG) ClientAddress[1],
(ULONG) ClientAddress[2],
(ULONG) ClientAddress[3]
);
RtlInitUnicodeString(
&AddressString,
AddressBuffer
);
//
// IP address
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &AddressString );
AuditParameters.ParameterCount++;
}
//
// Transitted Services is the last parameter for SE_AUDITID_TGS_TICKET_REQUEST
//
if (AuditId == SE_AUDITID_TGS_TICKET_REQUEST)
{
if (ARGUMENT_PRESENT(KerbStatus)) {
//
// Add a ULONG to the audit message
//
LsapSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, *KerbStatus );
AuditParameters.ParameterCount++;
} else {
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(LogonGuid)) {
//
// Add the globally unique logon-id to the audit message
//
LsapSetParmTypeGuid( AuditParameters, AuditParameters.ParameterCount, LogonGuid );
AuditParameters.ParameterCount++;
}
else {
if (( AuditParameters.Type == EVENTLOG_AUDIT_SUCCESS ) &&
( AuditId == SE_AUDITID_TGS_TICKET_REQUEST )) {
ASSERT( FALSE && L"LsaIAuditKdcEvent: UniqueID not supplied to successful SE_AUDITID_TGS_TICKET_REQUEST audit event" );
}
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(TransittedServices)) {
//
// Transitted Services
//
LsapSetParmTypeStringList( AuditParameters, AuditParameters.ParameterCount, TransittedServices );
}
AuditParameters.ParameterCount++;
} else if (AuditId == SE_AUDITID_AS_TICKET) {
if (ARGUMENT_PRESENT(CertIssuerName)) {
//
// Certificate Issuer Name
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CertIssuerName );
}
AuditParameters.ParameterCount++;
if (ARGUMENT_PRESENT(CertSerialNumber)) {
//
// Certificate Serial Number
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CertSerialNumber );
}
AuditParameters.ParameterCount++;
if (ARGUMENT_PRESENT(CertThumbprint)) {
//
// Certificate Thumbprint
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CertThumbprint );
}
AuditParameters.ParameterCount++;
}
//
// Now write out the audit record to the audit log
//
( VOID ) LsapAdtWriteLog( &AuditParameters );
Cleanup:
if (!NT_SUCCESS(Status)) {
LsapAuditFailed(Status);
}
return Status;
}
NTSTATUS
LsaIAuditAccountLogon(
IN ULONG AuditId,
IN BOOLEAN Successful,
IN PUNICODE_STRING Source,
IN PUNICODE_STRING ClientName,
IN PUNICODE_STRING MappedName,
IN NTSTATUS LogonStatus
)
{
return LsaIAuditAccountLogonEx(
AuditId,
Successful,
Source,
ClientName,
MappedName,
LogonStatus,
NULL // client SID
);
}
NTSTATUS
LsaIAuditAccountLogonEx(
IN ULONG AuditId,
IN BOOLEAN Successful,
IN PUNICODE_STRING Source,
IN PUNICODE_STRING ClientName,
IN PUNICODE_STRING MappedName,
IN NTSTATUS LogonStatus,
IN PSID ClientSid
)
/*++
Abstract:
This routine produces an audit record representing the mapping of a
foreign principal name onto an NT account.
This routine goes through the list of parameters and adds a string
representation of each (in order) to an audit message. Note that
the full complement of account audit message formats is achieved by
selecting which optional parameters to include in this call.
Parmeters:
AuditId - Specifies the message ID of the audit being generated.
Successful - Indicates the code should generate a success audit
Source - Source module generating audit, such as SCHANNEL or KDC
ClientName - Name being mapped.
MappedName - Name of NT account to which the client name was mapped.
LogonStatus- NT Status code for any failures.
ClientSid - SID of the client
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN bAudit = FALSE;
SE_ADT_PARAMETER_ARRAY AuditParameters;
UNICODE_STRING LocalClientName;
UNICODE_STRING LocalMappedName;
RtlZeroMemory (
(PVOID) &AuditParameters,
sizeof( AuditParameters )
);
AuditParameters.CategoryId = SE_CATEGID_ACCOUNT_LOGON;
AuditParameters.AuditId = AuditId;
AuditParameters.Type = Successful ?
EVENTLOG_AUDIT_SUCCESS :
EVENTLOG_AUDIT_FAILURE ;
if ( ClientSid )
{
//
// if the client SID is specified use it for checking pua policy
//
Status = LsapAdtAuditingEnabledBySid(
AuditCategoryAccountLogon,
ClientSid,
AuditParameters.Type,
&bAudit
);
if (!NT_SUCCESS(Status) || !bAudit)
{
goto Cleanup;
}
}
else
{
//
// if the client SID is not supplied, check the global policy
//
if (AuditParameters.Type == EVENTLOG_AUDIT_SUCCESS) {
if (!(LsapAdtEventsInformation.EventAuditingOptions[AuditCategoryAccountLogon] & POLICY_AUDIT_EVENT_SUCCESS)) {
return( STATUS_SUCCESS );
}
} else {
if (!(LsapAdtEventsInformation.EventAuditingOptions[AuditCategoryAccountLogon] & POLICY_AUDIT_EVENT_FAILURE)) {
return( STATUS_SUCCESS );
}
}
}
AuditParameters.ParameterCount = 0;
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, ClientSid ? ClientSid : LsapLocalSystemSid );
AuditParameters.ParameterCount++;
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LsapSubsystemName );
AuditParameters.ParameterCount++;
if (ARGUMENT_PRESENT(Source)) {
//
// Add a UNICODE_STRING to the audit message
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, Source );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(ClientName)) {
//
// Add a UNICODE_STRING to the audit message
//
LocalClientName = *ClientName;
if ( !Successful ) {
//
// For failed logons the client name can be invalid (for example,
// with embedded NULLs). This causes the
// eventlog to reject the string and we drop the audit.
//
// To avoid this, adjust the length parameter if necessary.
//
LocalClientName.Length =
(USHORT) LsapSafeWcslen( LocalClientName.Buffer,
LocalClientName.MaximumLength );
}
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LocalClientName );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(MappedName)) {
//
// Add MappedName to the audit message
//
// This is somewhat overloaded. For SE_AUDITID_ACCOUNT_LOGON, the
// caller passes the workstation name in this param.
//
// The workstation name can be invalid (for example,
// with embedded NULLs). This causes the
// eventlog to reject the string and we drop the audit.
//
// To avoid this, adjust the length parameter if necessary.
//
LocalMappedName = *MappedName;
LocalMappedName.Length =
(USHORT) LsapSafeWcslen( LocalMappedName.Buffer,
LocalMappedName.MaximumLength );
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LocalMappedName );
AuditParameters.ParameterCount++;
}
//
// Add a ULONG to the audit message
//
LsapSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, LogonStatus );
AuditParameters.ParameterCount++;
//
// Now write out the audit record to the audit log
//
( VOID ) LsapAdtWriteLog( &AuditParameters );
Cleanup:
if (!NT_SUCCESS(Status))
{
LsapAuditFailed(Status);
}
return Status;
}
NTSTATUS NTAPI
LsaIAuditDPAPIEvent(
IN ULONG AuditId,
IN PSID UserSid,
IN PUNICODE_STRING MasterKeyID,
IN PUNICODE_STRING RecoveryServer,
IN PULONG Reason,
IN PUNICODE_STRING RecoverykeyID,
IN PULONG FailureReason
)
/*++
Abstract:
This routine produces an audit record representing a DPAPI
operation.
This routine goes through the list of parameters and adds a string
representation of each (in order) to an audit message. Note that
the full complement of account audit message formats is achieved by
selecting which optional parameters to include in this call.
In addition to any parameters passed below, this routine will ALWAYS
add the impersonation client's user name, domain, and logon ID as
the LAST parameters in the audit message.
Parmeters:
AuditId - Specifies the message ID of the audit being generated.
MasterKeyID -
RecoveryServer -
Reason -
RecoverykeyID -
FailureReason -
--*/
{
SE_ADT_PARAMETER_ARRAY AuditParameters;
NTSTATUS Status;
BOOLEAN bAudit;
RtlZeroMemory (
(PVOID) &AuditParameters,
sizeof( AuditParameters )
);
AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING;
AuditParameters.AuditId = AuditId;
AuditParameters.Type = ((ARGUMENT_PRESENT(FailureReason) &&
(*FailureReason != 0)) ?
EVENTLOG_AUDIT_FAILURE :
EVENTLOG_AUDIT_SUCCESS );
Status = LsapAdtAuditingEnabledBySid(
AuditCategoryDetailedTracking,
UserSid,
AuditParameters.Type,
&bAudit
);
if (!NT_SUCCESS(Status) || !bAudit)
{
goto Cleanup;
}
AuditParameters.ParameterCount = 0;
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid ? UserSid : LsapLocalSystemSid );
AuditParameters.ParameterCount++;
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LsapSubsystemName );
AuditParameters.ParameterCount++;
if (ARGUMENT_PRESENT(MasterKeyID)) {
//
// Add a UNICODE_STRING to the audit message
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, MasterKeyID );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(RecoveryServer)) {
//
// Add a UNICODE_STRING to the audit message
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, RecoveryServer );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(Reason)) {
//
// Add a ULONG to the audit message
//
LsapSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, *Reason );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(RecoverykeyID)) {
//
// Add a UNICODE_STRING to the audit message
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, RecoverykeyID );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(FailureReason)) {
//
// Add a ULONG to the audit message
//
LsapSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, *FailureReason );
AuditParameters.ParameterCount++;
}
//
// Now write out the audit record to the audit log
//
( VOID ) LsapAdtWriteLog( &AuditParameters );
Cleanup:
if (!NT_SUCCESS(Status))
{
LsapAuditFailed(Status);
}
return Status;
}
NTSTATUS
LsaIWriteAuditEvent(
IN PSE_ADT_PARAMETER_ARRAY AuditParameters,
IN ULONG Options
)
/*++
Abstract:
This routine writes an audit record to the log.
Parmeters:
AuditParameters - The audit record
Options - must be zero
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN bAudit = FALSE;
POLICY_AUDIT_EVENT_TYPE CategoryId;
if ( !ARGUMENT_PRESENT(AuditParameters) ||
(Options != 0) ||
!IsValidCategoryId( AuditParameters->CategoryId ) ||
!IsValidAuditId( AuditParameters->AuditId ) ||
!IsValidParameterCount( AuditParameters->ParameterCount ) ||
(AuditParameters->Parameters[0].Type != SeAdtParmTypeSid) ||
(AuditParameters->Parameters[1].Type != SeAdtParmTypeString))
{
return STATUS_INVALID_PARAMETER;
}
//
// LsapAdtEventsInformation.EventAuditingOptions needs to be indexed
// by one of enum POLICY_AUDIT_EVENT_TYPE values whereas the value
// of SE_ADT_PARAMETER_ARRAY.CategoryId must be one of SE_CATEGID_*
// values. The value of corresponding elements in the two types differ by 1.
// Subtract 1 from AuditParameters->CategoryId to get the right
// AuditCategory* value.
//
CategoryId = AuditParameters->CategoryId - 1;
Status = LsapAdtAuditingEnabledBySid(
CategoryId,
(PSID) AuditParameters->Parameters[0].Address,
AuditParameters->Type,
&bAudit
);
if (!NT_SUCCESS(Status) || !bAudit) {
goto Cleanup;
}
//
// Audit the event
//
Status = LsapAdtWriteLog( AuditParameters );
Cleanup:
return Status;
}
NTSTATUS
LsaIAuditNotifyPackageLoad(
PUNICODE_STRING PackageFileName
)
/*++
Routine Description:
Audits the loading of an notification package.
Arguments:
PackageFileName - The name of the package being loaded.
Return Value:
NTSTATUS.
--*/
{
SE_ADT_PARAMETER_ARRAY AuditParameters;
NTSTATUS Status;
BOOLEAN bAudit;
Status = LsapAdtAuditingEnabledBySid(
AuditCategorySystem,
LsapLocalSystemSid,
EVENTLOG_AUDIT_SUCCESS,
&bAudit
);
if (!NT_SUCCESS(Status) || !bAudit) {
goto Cleanup;
}
RtlZeroMemory (
(PVOID) &AuditParameters,
sizeof( AuditParameters )
);
AuditParameters.CategoryId = SE_CATEGID_SYSTEM;
AuditParameters.AuditId = SE_AUDITID_NOTIFY_PACKAGE_LOAD;
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
AuditParameters.ParameterCount = 0;
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, LsapLocalSystemSid );
AuditParameters.ParameterCount++;
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LsapSubsystemName );
AuditParameters.ParameterCount++;
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, PackageFileName );
AuditParameters.ParameterCount++;
( VOID ) LsapAdtWriteLog( &AuditParameters );
Cleanup:
if (!NT_SUCCESS(Status)) {
LsapAuditFailed(Status);
}
return Status;
}
NTSTATUS
LsaIAuditSamEvent(
IN NTSTATUS PassedStatus,
IN ULONG AuditId,
IN PSID DomainSid,
IN PUNICODE_STRING AdditionalInfo OPTIONAL,
IN PULONG MemberRid OPTIONAL,
IN PSID MemberSid OPTIONAL,
IN PUNICODE_STRING AccountName OPTIONAL,
IN PUNICODE_STRING DomainName,
IN PULONG AccountRid OPTIONAL,
IN PPRIVILEGE_SET Privileges OPTIONAL,
IN PVOID ExtendedInfo OPTIONAL
)
/*++
Abstract:
This routine produces an audit record representing an account
operation.
This routine goes through the list of parameters and adds a string
representation of each (in order) to an audit message. Note that
the full complement of account audit message formats is achieved by
selecting which optional parameters to include in this call.
In addition to any parameters passed below, this routine will ALWAYS
add the impersonation client's user name, domain, and logon ID as
the LAST parameters in the audit message.
Parmeters:
AuditId - Specifies the message ID of the audit being generated.
DomainSid - This parameter results in a SID string being generated
ONLY if neither the MemberRid nor AccountRid parameters are
passed. If either of those parameters are passed, this parameter
is used as a prefix of a SID.
AdditionalInfo - This optional parameter, if present, is used to
produce any additional inforamtion the caller wants to add.
Used by SE_AUDITID_USER_CHANGE and SE_AUDITID_GROUP_TYPE_CHANGE.
for user change, the additional info states the nature of the
change, such as Account Disable, unlocked or account Name Changed.
For Group type change, this parameter should state the group type
has been change from AAA to BBB.
MemberRid - This optional parameter, if present, is added to the end of
the DomainSid parameter to produce a "Member" sid. The resultant
member SID is then used to build a sid-string which is added to the
audit message following all preceeding parameters.
This parameter supports global group membership change audits, where
member IDs are always relative to a local domain.
MemberSid - This optional parameter, if present, is converted to a
SID string and added following preceeding parameters. This parameter
is generally used for describing local group (alias) members, where
the member IDs are not relative to a local domain.
AccountName - This optional parameter, if present, is added to the audit
message without change following any preceeding parameters.
This parameter is needed for almost all account audits and does not
need localization.
DomainName - This optional parameter, if present, is added to the audit
message without change following any preceeding parameters.
This parameter is needed for almost all account audits and does not
need localization.
AccountRid - This optional parameter, if present, is added to the end of
the DomainSid parameter to produce an "Account" sid. The resultant
Account SID is then used to build a sid-string which is added to the
audit message following all preceeding parameters.
This parameter supports audits that include "New account ID" or
"Target Account ID" fields.
Privileges - The privileges passed via this optional parameter,
if present, will be converted to string format and added to the
audit message following any preceeding parameters. NOTE: the
caller is responsible for freeing the privilege_set (in fact,
it may be on the stack). ALSO NOTE: The privilege set will be
destroyed by this call (due to use of the routine used to
convert the privilege values to privilege names).
ExtendedInfo - Pointer to an optional parameter containing extended
information about attributes of sam objects. This parameter gets typecast
to a structure describing the attributes, depending on the audit id.
--*/
{
NTSTATUS Status;
LUID LogonId = SYSTEM_LUID;
PSID NewAccountSid = NULL;
PSID NewMemberSid = NULL;
PSID SidPointer;
PSID ClientSid = NULL;
PTOKEN_USER TokenUserInformation = NULL;
SE_ADT_PARAMETER_ARRAY AuditParameters;
UCHAR AccountSidBuffer[256];
UCHAR MemberSidBuffer[256];
UCHAR SubAuthorityCount;
ULONG LengthRequired;
BOOLEAN bAudit;
if ( AuditId == SE_AUDITID_ACCOUNT_AUTO_LOCKED )
{
//
// In this case use LogonID as SYSTEM, SID is SYSTEM.
//
ClientSid = LsapLocalSystemSid;
} else {
Status = LsapQueryClientInfo(
&TokenUserInformation,
&LogonId
);
if ( !NT_SUCCESS( Status )) {
goto Cleanup;
}
ClientSid = TokenUserInformation->User.Sid;
}
RtlZeroMemory (
(PVOID) &AuditParameters,
sizeof( AuditParameters )
);
AuditParameters.CategoryId = SE_CATEGID_ACCOUNT_MANAGEMENT;
AuditParameters.AuditId = AuditId;
AuditParameters.Type = (NT_SUCCESS(PassedStatus) ? EVENTLOG_AUDIT_SUCCESS : EVENTLOG_AUDIT_FAILURE );
AuditParameters.ParameterCount = 0;
Status = LsapAdtAuditingEnabledByLogonId(
AuditCategoryAccountManagement,
&LogonId,
AuditParameters.Type,
&bAudit
);
if (!NT_SUCCESS(Status) || !bAudit)
{
goto Cleanup;
}
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, ClientSid );
AuditParameters.ParameterCount++;
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LsapSubsystemName );
AuditParameters.ParameterCount++;
if (ARGUMENT_PRESENT(AdditionalInfo))
{
//
// Add a UNICODE_STRING to the audit message
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, AdditionalInfo );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(MemberRid)) {
//
// Add a member SID string to the audit message
//
// Domain Sid + Member Rid = Final SID.
SubAuthorityCount = *RtlSubAuthorityCountSid( DomainSid );
if ( (LengthRequired = RtlLengthRequiredSid( SubAuthorityCount + 1 )) > 256 ) {
NewMemberSid = LsapAllocateLsaHeap( LengthRequired );
if ( NewMemberSid == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
SidPointer = NewMemberSid;
} else {
SidPointer = (PSID)MemberSidBuffer;
}
Status = RtlCopySid (
LengthRequired,
SidPointer,
DomainSid
);
ASSERT( NT_SUCCESS( Status ));
*(RtlSubAuthoritySid( SidPointer, SubAuthorityCount )) = *MemberRid;
*RtlSubAuthorityCountSid( SidPointer ) = SubAuthorityCount + 1;
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, SidPointer );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(MemberSid)) {
//
// Add a member SID string to the audit message
//
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, MemberSid );
AuditParameters.ParameterCount++;
} else {
if (SE_AUDITID_ADD_SID_HISTORY == AuditId) {
//
// Add dash ( - ) string to the audit message (SeAdtParmTypeNone)
// by calling LsapSetParmTypeSid with NULL as third parameter
//
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, NULL );
AuditParameters.ParameterCount++;
}
}
if (ARGUMENT_PRESENT(AccountName)) {
//
// Add a UNICODE_STRING to the audit message
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, AccountName );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(DomainName)) {
//
// Add a UNICODE_STRING to the audit message
//
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, DomainName );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(DomainSid) &&
!(ARGUMENT_PRESENT(MemberRid) || ARGUMENT_PRESENT(AccountRid))
) {
//
// Add the domain SID as a SID string to the audit message
//
// Just the domain SID.
//
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, DomainSid );
AuditParameters.ParameterCount++;
}
if (ARGUMENT_PRESENT(AccountRid)) {
//
// Add a member SID string to the audit message
// Domain Sid + account Rid = final sid
//
SubAuthorityCount = *RtlSubAuthorityCountSid( DomainSid );
if ( (LengthRequired = RtlLengthRequiredSid( SubAuthorityCount + 1 )) > 256 ) {
NewAccountSid = LsapAllocateLsaHeap( LengthRequired );
if ( NewAccountSid == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
SidPointer = NewAccountSid;
} else {
SidPointer = (PSID)AccountSidBuffer;
}
Status = RtlCopySid (
LengthRequired,
SidPointer,
DomainSid
);
ASSERT( NT_SUCCESS( Status ));
*(RtlSubAuthoritySid( SidPointer, SubAuthorityCount )) = *AccountRid;
*RtlSubAuthorityCountSid( SidPointer ) = SubAuthorityCount + 1;
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, SidPointer );
AuditParameters.ParameterCount++;
}
//
// Now add the caller information
//
// Caller name
// Caller domain
// Caller logon ID
//
LsapSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, LogonId );
AuditParameters.ParameterCount++;
//
// Add any privileges
//
if (ARGUMENT_PRESENT(Privileges)) {
LsapSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, Privileges );
}
AuditParameters.ParameterCount++;
//
// Take care of the extended info.
//
switch (AuditId)
{
case SE_AUDITID_ADD_SID_HISTORY:
if (ExtendedInfo)
{
LsapSetParmTypeStringList(
AuditParameters,
AuditParameters.ParameterCount,
(PLSA_ADT_STRING_LIST)ExtendedInfo);
}
AuditParameters.ParameterCount++;
break;
case SE_AUDITID_DOMAIN_POLICY_CHANGE:
LsapAdtAppendDomainAttrValues(
&AuditParameters,
(PLSAP_AUDIT_DOMAIN_ATTR_VALUES)ExtendedInfo);
break;
case SE_AUDITID_COMPUTER_CREATED:
case SE_AUDITID_COMPUTER_CHANGE:
LsapAdtAppendUserAttrValues(
&AuditParameters,
(PLSAP_AUDIT_USER_ATTR_VALUES)ExtendedInfo,
TRUE);
break;
case SE_AUDITID_USER_CREATED:
case SE_AUDITID_USER_CHANGE:
LsapAdtAppendUserAttrValues(
&AuditParameters,
(PLSAP_AUDIT_USER_ATTR_VALUES)ExtendedInfo,
FALSE);
break;
case SE_AUDITID_LOCAL_GROUP_CREATED:
case SE_AUDITID_LOCAL_GROUP_CHANGE:
case SE_AUDITID_GLOBAL_GROUP_CREATED:
case SE_AUDITID_GLOBAL_GROUP_CHANGE:
case SE_AUDITID_SECURITY_ENABLED_UNIVERSAL_GROUP_CREATED:
case SE_AUDITID_SECURITY_ENABLED_UNIVERSAL_GROUP_CHANGE:
case SE_AUDITID_SECURITY_DISABLED_LOCAL_GROUP_CREATED:
case SE_AUDITID_SECURITY_DISABLED_LOCAL_GROUP_CHANGE:
case SE_AUDITID_SECURITY_DISABLED_GLOBAL_GROUP_CREATED:
case SE_AUDITID_SECURITY_DISABLED_GLOBAL_GROUP_CHANGE:
case SE_AUDITID_SECURITY_DISABLED_UNIVERSAL_GROUP_CREATED:
case SE_AUDITID_SECURITY_DISABLED_UNIVERSAL_GROUP_CHANGE:
case SE_AUDITID_APP_BASIC_GROUP_CREATED:
case SE_AUDITID_APP_BASIC_GROUP_CHANGE:
case SE_AUDITID_APP_QUERY_GROUP_CREATED:
case SE_AUDITID_APP_QUERY_GROUP_CHANGE:
LsapAdtAppendGroupAttrValues(
&AuditParameters,
(PLSAP_AUDIT_GROUP_ATTR_VALUES)ExtendedInfo);
break;
case SE_AUDITID_PASSWORD_POLICY_API_CALLED:
{
PUNICODE_STRING *Information = ( PUNICODE_STRING *) ExtendedInfo;
ULONG i;
//
// Parameter count was moved in advance, move
// it to its original place.
//
AuditParameters.ParameterCount--;
//
// Add workstation ip and provided account name if present
//
for( i = 0; i < 2; ++i ) {
if( Information[i]->Length != 0 ) {
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, Information[i] );
} else {
AuditParameters.Parameters[AuditParameters.ParameterCount].Type = SeAdtParmTypeNone;
AuditParameters.Parameters[AuditParameters.ParameterCount].Length = 0;
AuditParameters.Parameters[AuditParameters.ParameterCount].Address = NULL;
}
AuditParameters.ParameterCount++;
}
//
// Add the status code
//
LsapSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, PassedStatus );
AuditParameters.ParameterCount++;
ASSERTMSG( "There must be 6 parameters! Not more, not less", AuditParameters.ParameterCount == 6 );
}
break;
case SE_AUDITID_DSRM_PASSWORD_SET:
{
PUNICODE_STRING String = ( PUNICODE_STRING ) ExtendedInfo;
//
// Parameter count was moved in advance, move
// it to its original place.
//
AuditParameters.ParameterCount--;
if( String->Length != 0 ) {
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, String );
} else {
AuditParameters.Parameters[AuditParameters.ParameterCount].Type = SeAdtParmTypeNone;
AuditParameters.Parameters[AuditParameters.ParameterCount].Length = 0;
AuditParameters.Parameters[AuditParameters.ParameterCount].Address = NULL;
}
AuditParameters.ParameterCount++;
//
// Add the status code
//
LsapSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, PassedStatus );
AuditParameters.ParameterCount++;
}
break;
}
//
// Now write out the audit record to the audit log
//
( VOID ) LsapAdtWriteLog( &AuditParameters );
//
// And clean up any allocated memory
//
Status = STATUS_SUCCESS;
Cleanup:
if ( !NT_SUCCESS(Status) ) {
LsapAuditFailed(Status);
}
if ( NewMemberSid != NULL ) {
LsapFreeLsaHeap( NewMemberSid );
}
if ( NewAccountSid != NULL ) {
LsapFreeLsaHeap( NewAccountSid );
}
if ( TokenUserInformation != NULL ) {
LsapFreeLsaHeap( TokenUserInformation );
}
return Status;
UNREFERENCED_PARAMETER(ExtendedInfo);
}
NTSTATUS
LsaIAuditPasswordAccessEvent(
IN USHORT EventType,
IN PCWSTR pszTargetUserName,
IN PCWSTR pszTargetUserDomain
)
/*++
Routine Description:
Generate SE_AUDITID_PASSWORD_HASH_ACCESS event. This is generated when
user password hash is retrieved by the ADMT password filter DLL.
This typically happens during ADMT password migration.
Arguments:
EventType - EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE
pszTargetUserName - name of user whose password is being retrieved
pszTargetUserDomain - domain of user whose password is being retrieved
Return Value:
NTSTATUS - Standard NT Result Code
Notes:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
LUID ClientAuthenticationId;
PTOKEN_USER TokenUserInformation=NULL;
SE_ADT_PARAMETER_ARRAY AuditParameters = { 0 };
UNICODE_STRING TargetUser;
UNICODE_STRING TargetDomain;
BOOLEAN bAudit;
if ( !((EventType == EVENTLOG_AUDIT_SUCCESS) ||
(EventType == EVENTLOG_AUDIT_FAILURE)) ||
!pszTargetUserName || !pszTargetUserDomain ||
!*pszTargetUserName || !*pszTargetUserDomain )
{
Status = STATUS_INVALID_PARAMETER;
goto Cleanup;
}
//
// get caller info from the thread token
//
Status = LsapQueryClientInfo( &TokenUserInformation, &ClientAuthenticationId );
if ( !NT_SUCCESS( Status ))
{
goto Cleanup;
}
//
// if auditing is not enabled, return asap
//
Status = LsapAdtAuditingEnabledByLogonId(
AuditCategoryAccountManagement,
&ClientAuthenticationId,
EventType,
&bAudit
);
if (!NT_SUCCESS(Status) || !bAudit)
{
goto Cleanup;
}
RtlInitUnicodeString( &TargetUser, pszTargetUserName );
RtlInitUnicodeString( &TargetDomain, pszTargetUserDomain );
Status =
LsapAdtInitParametersArray(
&AuditParameters,
SE_CATEGID_ACCOUNT_MANAGEMENT,
SE_AUDITID_PASSWORD_HASH_ACCESS,
EventType,
5, // there are 5 params to init
//
// User Sid
//
SeAdtParmTypeSid, TokenUserInformation->User.Sid,
//
// Subsystem name
//
SeAdtParmTypeString, &LsapSubsystemName,
//
// target user name
//
SeAdtParmTypeString, &TargetUser,
//
// target user domain name
//
SeAdtParmTypeString, &TargetDomain,
//
// client auth-id
//
SeAdtParmTypeLogonId, ClientAuthenticationId
);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
Status = LsapAdtWriteLog( &AuditParameters );
Cleanup:
if (TokenUserInformation != NULL)
{
LsapFreeLsaHeap( TokenUserInformation );
}
if (!NT_SUCCESS(Status))
{
LsapAuditFailed( Status );
}
return Status;
}
VOID
LsaIAuditFailed(
NTSTATUS AuditStatus
)
/*++
Routine Description:
Components must call this function if they encounter any problem
that prevent them from generating any audit.
Arguments:
AuditStatus : failure code
Return Value:
none.
--*/
{
//
// make sure that we are not called for success case
//
ASSERT(!NT_SUCCESS(AuditStatus));
LsapAuditFailed( AuditStatus );
}
VOID
LsapAdtAppendDomainAttrValues(
IN OUT PSE_ADT_PARAMETER_ARRAY pParameters,
IN PLSAP_AUDIT_DOMAIN_ATTR_VALUES pAttributes OPTIONAL
)
/*++
Routine Description:
Helper function to insert the domain attributes
into the audit parameter array.
Arguments:
pParameters : audit parameter array
pAttributes : pointer to structure containing the
attributes to insert
Return Value:
none.
--*/
{
ULONG Index;
PLSAP_SAM_AUDIT_ATTR_DELTA_TYPE pDelta;
DsysAssertMsg(
pParameters->ParameterCount + LSAP_DOMAIN_ATTR_COUNT <= SE_MAX_AUDIT_PARAMETERS,
"LsapAdtAppendDomainAttrValues: Insuffient audit param slots");
if (pAttributes == 0)
{
pParameters->ParameterCount += LSAP_DOMAIN_ATTR_COUNT;
return;
}
//
// Initialize our 'loop' vars.
//
Index = pParameters->ParameterCount;
pDelta = pAttributes->AttrDeltaType;
//
// Min Password Age
//
if (pAttributes->MinPasswordAge &&
*pDelta == LsapAuditSamAttrNewValue &&
!(pAttributes->MinPasswordAge->LowPart == 0 &&
pAttributes->MinPasswordAge->HighPart == MINLONG))
{
LsapSetParmTypeDuration(
*pParameters,
Index,
*pAttributes->MinPasswordAge);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Max Password Age
//
if (pAttributes->MaxPasswordAge &&
*pDelta == LsapAuditSamAttrNewValue &&
!(pAttributes->MaxPasswordAge->LowPart == 0 &&
pAttributes->MaxPasswordAge->HighPart == MINLONG))
{
LsapSetParmTypeDuration(
*pParameters,
Index,
*pAttributes->MaxPasswordAge);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Force Logoff
//
if (pAttributes->ForceLogoff &&
*pDelta == LsapAuditSamAttrNewValue &&
!(pAttributes->ForceLogoff->LowPart == 0 &&
pAttributes->ForceLogoff->HighPart == MINLONG))
{
LsapSetParmTypeDuration(
*pParameters,
Index,
*pAttributes->ForceLogoff);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Lockout Threshold
//
if (pAttributes->LockoutThreshold &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeUlong(
*pParameters,
Index,
(ULONG)(*pAttributes->LockoutThreshold));
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Lockout Observation Window
//
if (pAttributes->LockoutObservationWindow &&
*pDelta == LsapAuditSamAttrNewValue &&
!(pAttributes->LockoutObservationWindow->LowPart == 0 &&
pAttributes->LockoutObservationWindow->HighPart == MINLONG))
{
LsapSetParmTypeDuration(
*pParameters,
Index,
*pAttributes->LockoutObservationWindow);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Lockout Duration
//
if (pAttributes->LockoutDuration &&
*pDelta == LsapAuditSamAttrNewValue &&
!(pAttributes->LockoutDuration->LowPart == 0 &&
pAttributes->LockoutDuration->HighPart == MINLONG))
{
LsapSetParmTypeDuration(
*pParameters,
Index,
*pAttributes->LockoutDuration);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Password Properties
//
if (pAttributes->PasswordProperties &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeUlong(
*pParameters,
Index,
*pAttributes->PasswordProperties);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Min Password Length
//
if (pAttributes->MinPasswordLength &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeUlong(
*pParameters,
Index,
(ULONG)(*pAttributes->MinPasswordLength));
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Password History Length
//
if (pAttributes->PasswordHistoryLength &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeUlong(
*pParameters,
Index,
(ULONG)(*pAttributes->PasswordHistoryLength));
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Machine Account Quota
//
if (pAttributes->MachineAccountQuota &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeUlong(
*pParameters,
Index,
*pAttributes->MachineAccountQuota);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Mixed Domain Mode
//
if (pAttributes->MixedDomainMode &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeUlong(
*pParameters,
Index,
*pAttributes->MixedDomainMode);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Domain Behavior Version
//
if (pAttributes->DomainBehaviorVersion &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeUlong(
*pParameters,
Index,
*pAttributes->DomainBehaviorVersion);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Oem Information
//
if (pAttributes->OemInformation &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeString(
*pParameters,
Index,
pAttributes->OemInformation);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Verify we added the right number of params and fixup the param count.
//
DsysAssertMsg(
Index - pParameters->ParameterCount == LSAP_DOMAIN_ATTR_COUNT,
"LsapAdtAppendDomainAttrValues: Wrong param count");
pParameters->ParameterCount = Index;
}
VOID
LsapAdtAppendUserAttrValues(
IN OUT PSE_ADT_PARAMETER_ARRAY pParameters,
IN PLSAP_AUDIT_USER_ATTR_VALUES pAttributes OPTIONAL,
IN BOOL MachineAudit
)
/*++
Routine Description:
Helper function to insert the user attributes
into the audit parameter array. We are only going
to insert values that have changed.
Arguments:
pParameters : audit parameter array
pAttributes : pointer to structure containing the
attributes to insert
Return Value:
none.
--*/
{
ULONG Index;
ULONG AttrCount = LSAP_USER_ATTR_COUNT;
PLSAP_SAM_AUDIT_ATTR_DELTA_TYPE pDelta;
LARGE_INTEGER FileTime;
if (!MachineAudit)
{
//
// User audits don't have the last two attributes.
//
AttrCount -= 2;
}
DsysAssertMsg(
pParameters->ParameterCount + AttrCount <= SE_MAX_AUDIT_PARAMETERS,
"LsapAdtAppendUserAttrValues: Insuffient audit param slots");
if (pAttributes == 0)
{
//
// The user account control param actually produces 3 strings,
// so we have to increase the parameter count by 2 to make up for it.
// We also have to check/assert whether we hit the max param limit.
//
AttrCount += 2;
pParameters->ParameterCount += AttrCount;
if (pParameters->ParameterCount > SE_MAX_AUDIT_PARAMETERS)
{
DsysAssertMsg(
pParameters->ParameterCount <= SE_MAX_AUDIT_PARAMETERS,
"LsapAdtAppendUserAttrValues: Insuffient audit param slots");
//
// It is better to have one or two %xx entries in the log
// than av'ing or dropping the audit...
//
pParameters->ParameterCount = SE_MAX_AUDIT_PARAMETERS;
}
return;
}
//
// Initialize our 'loop' vars.
//
Index = pParameters->ParameterCount;
pDelta = pAttributes->AttrDeltaType;
//
// Sam Account Name
//
if (pAttributes->SamAccountName &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeString(
*pParameters,
Index,
pAttributes->SamAccountName);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Display Name
//
if (pAttributes->DisplayName &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeString(
*pParameters,
Index,
pAttributes->DisplayName);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// User Principal Name
//
if (pAttributes->UserPrincipalName &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeString(
*pParameters,
Index,
pAttributes->UserPrincipalName);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Home Directory
//
if (pAttributes->HomeDirectory &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeString(
*pParameters,
Index,
pAttributes->HomeDirectory);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Home Drive
//
if (pAttributes->HomeDrive &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeString(
*pParameters,
Index,
pAttributes->HomeDrive);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Script Path
//
if (pAttributes->ScriptPath &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeString(
*pParameters,
Index,
pAttributes->ScriptPath);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Profile Path
//
if (pAttributes->ProfilePath &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeString(
*pParameters,
Index,
pAttributes->ProfilePath);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// User WorkStations
//
if (pAttributes->UserWorkStations &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeString(
*pParameters,
Index,
pAttributes->UserWorkStations);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Password Last Set
//
if (pAttributes->PasswordLastSet &&
*pDelta == LsapAuditSamAttrNewValue)
{
FileTime.LowPart = pAttributes->PasswordLastSet->dwLowDateTime;
FileTime.HighPart = pAttributes->PasswordLastSet->dwHighDateTime;
if ((FileTime.LowPart == MAXULONG && FileTime.HighPart == MAXLONG) || // SampWillNeverTime
(FileTime.LowPart == 0 && FileTime.HighPart == 0)) // SampHasNeverTime
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_TIME_NEVER);
}
else
{
LsapSetParmTypeDateTime(
*pParameters,
Index,
FileTime);
}
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
else
{
FileTime.LowPart = 0;
FileTime.HighPart = 0;
LsapSetParmTypeDateTime(
*pParameters,
Index,
FileTime);
}
pDelta++;
Index++;
//
// Account Expires
//
if (pAttributes->AccountExpires &&
*pDelta == LsapAuditSamAttrNewValue)
{
FileTime.LowPart = pAttributes->AccountExpires->dwLowDateTime;
FileTime.HighPart = pAttributes->AccountExpires->dwHighDateTime;
if ((FileTime.LowPart == MAXULONG && FileTime.HighPart == MAXLONG) || // SampWillNeverTime
(FileTime.LowPart == 0 && FileTime.HighPart == 0)) // SampHasNeverTime
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_TIME_NEVER);
}
else
{
LsapSetParmTypeDateTime(
*pParameters,
Index,
FileTime);
}
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
else
{
FileTime.LowPart = 0;
FileTime.HighPart = 0;
LsapSetParmTypeDateTime(
*pParameters,
Index,
FileTime);
}
pDelta++;
Index++;
//
// Primary Group Id
//
if (pAttributes->PrimaryGroupId &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeUlong(
*pParameters,
Index,
*pAttributes->PrimaryGroupId);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Allowed To Delegate To
//
if (pAttributes->AllowedToDelegateTo &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeStringList(
*pParameters,
Index,
pAttributes->AllowedToDelegateTo);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// User Account Control
//
if (pAttributes->UserAccountControl &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeUac(
*pParameters,
Index,
*pAttributes->PrevUserAccountControl,
*pAttributes->UserAccountControl);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
else
{
LsapSetParmTypeNoUac(
*pParameters,
Index);
}
pDelta++;
Index++;
//
// User Parameters
// This value is special since it never gets displayed. Instead, we
// display only a string indicating that the value has changed.
//
if (*pDelta == LsapAuditSamAttrNewValue ||
*pDelta == LsapAuditSamAttrSecret)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_DISPLAYED);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Sid History
//
if (pAttributes->SidHistory &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeSidList(
*pParameters,
Index,
pAttributes->SidHistory);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Logon Hours (display not yet supported)
//
if (pAttributes->LogonHours &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_DISPLAYED);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// DnsHostName and SCPs are available for computer audits only.
//
if (MachineAudit)
{
//
// Dns Host Name
//
if (pAttributes->DnsHostName &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeString(
*pParameters,
Index,
pAttributes->DnsHostName);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Service Principal Names
//
if (pAttributes->ServicePrincipalNames &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeStringList(
*pParameters,
Index,
pAttributes->ServicePrincipalNames);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
}
//
// Verify we added the right number of params and fixup the param count.
//
DsysAssertMsg(
Index - pParameters->ParameterCount == AttrCount,
"LsapAdtAppendGroupAttrValues: Wrong param count");
pParameters->ParameterCount = Index;
}
VOID
LsapAdtAppendGroupAttrValues(
IN OUT PSE_ADT_PARAMETER_ARRAY pParameters,
IN PLSAP_AUDIT_GROUP_ATTR_VALUES pAttributes OPTIONAL
)
/*++
Routine Description:
Helper function to insert the group attributes
into the audit parameter array.
Arguments:
pParameters : audit parameter array
pAttributes : pointer to structure containing the
attributes to insert
Return Value:
none.
--*/
{
ULONG Index;
PLSAP_SAM_AUDIT_ATTR_DELTA_TYPE pDelta;
DsysAssertMsg(
pParameters->ParameterCount + LSAP_GROUP_ATTR_COUNT <= SE_MAX_AUDIT_PARAMETERS,
"LsapAdtAppendGroupAttrValues: Insuffient audit param slots");
if (pAttributes == 0)
{
pParameters->ParameterCount += LSAP_GROUP_ATTR_COUNT;
return;
}
//
// Initialize our 'loop' vars.
//
Index = pParameters->ParameterCount;
pDelta = pAttributes->AttrDeltaType;
//
// Sam Account Name
//
if (pAttributes->SamAccountName &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeString(
*pParameters,
Index,
pAttributes->SamAccountName);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Sid History
//
if (pAttributes->SidHistory &&
*pDelta == LsapAuditSamAttrNewValue)
{
LsapSetParmTypeSidList(
*pParameters,
Index,
pAttributes->SidHistory);
}
else if (*pDelta == LsapAuditSamAttrNoValue)
{
LsapSetParmTypeMessage(
*pParameters,
Index,
SE_ADT_VALUE_NOT_SET);
}
pDelta++;
Index++;
//
// Verify we added the right number of params and fixup the param count.
//
DsysAssertMsg(
Index - pParameters->ParameterCount == LSAP_GROUP_ATTR_COUNT,
"LsapAdtAppendGroupAttrValues: Wrong param count");
pParameters->ParameterCount = Index;
}