|
|
//+-----------------------------------------------------------------------
//
// File: secdata.cxx
//
// Contents: Global data and methods on it.
//
//
// History:
//
//------------------------------------------------------------------------
#include "kdcsvr.hxx"
#include <tostring.hxx>
#include <kpasswd.h>
///////////////////////////////////////////////////////////////
//
//
// Global data
//
// This is all the security information that gets cached.
CSecurityData SecData;
CAuthenticatorList * Authenticators; CAuthenticatorList * FailedRequests;
///////////////////////////////////////////////////////////////
//
//
// Prototypes
//
fLsaPolicyChangeNotificationCallback KdcPolicyChangeCallback;
//+-------------------------------------------------------------------------
//
// Function: KdcPolicyChangeCallBack
//
// Synopsis: Function that gets called when policy changes
//
// Effects: Changes policy variables
//
// Arguments: MonitorInfoClass - class of data that changed
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
VOID KdcPolicyChangeCallBack( IN POLICY_NOTIFICATION_INFORMATION_CLASS MonitorInfoClass ) { NTSTATUS Status; WCHAR Class[10];
TRACE(KDC, KdcPolicyChangeCallBack, DEB_FUNCTION);
Status = SecData.ReloadPolicy(MonitorInfoClass);
if (!NT_SUCCESS(Status)) { _itow(MonitorInfoClass, Class, 10 );
ReportServiceEvent( EVENTLOG_ERROR_TYPE, KDCEVENT_POLICY_UPDATE_FAILED, sizeof(NTSTATUS), &Status, 1, // number of strings
Class ); } }
//+-------------------------------------------------------------------------
//
// Function: CSecurityData::ReloadPolicy
//
// Synopsis: Reloads a particular piece of policy
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
NTSTATUS CSecurityData::ReloadPolicy( IN POLICY_NOTIFICATION_INFORMATION_CLASS MonitorInfoClass ) { NTSTATUS Status = STATUS_SUCCESS; PLSAPR_POLICY_DOMAIN_INFORMATION DomainPolicy = NULL; PLSAPR_POLICY_INFORMATION LocalPolicy = NULL; WCHAR Class[10];
TRACE(KDC, CSecurityData::ReloadPolicy, DEB_FUNCTION);
//
// Ignore changes to non-kerberos ticket information
//
switch(MonitorInfoClass) { case PolicyNotifyDomainKerberosTicketInformation:
Status = LsarQueryDomainInformationPolicy( GlobalPolicyHandle, PolicyDomainKerberosTicketInformation, &DomainPolicy ); if (!NT_SUCCESS(Status)) { goto Cleanup; } break; case PolicyNotifyAuditEventsInformation: Status = LsarQueryInformationPolicy( GlobalPolicyHandle, PolicyAuditEventsInformation, &LocalPolicy ); if (!NT_SUCCESS(Status)) { goto Cleanup; } break; default: return(STATUS_SUCCESS); }
//
// Update the changed information in the KDCs global data structures.
//
//
// Current policy defaults, see KirkSol/JBrezak
// [Kerberos Policy]
// MaxTicketAge=10 ;Maximum User Ticket Lifetime (hours)
// MaxRenewAge=7 ;Maximum lifetime that a user tickeet can be renewed (days)
// MaxServiceAge=60 ;Maximum Service Ticket Lifetime (minutes)
// MaxClockSkew=5 ;Maximum tolerance for synchronization of computer clocks (minutes)
// TicketValidateClient=1 ;Enforce user logon restrictions
WriteLock(); switch(MonitorInfoClass) { case PolicyNotifyDomainKerberosTicketInformation:
// Validate parameters
if ((DomainPolicy->PolicyDomainKerbTicketInfo.MaxServiceTicketAge.QuadPart <= (LONGLONG) -1) || (DomainPolicy->PolicyDomainKerbTicketInfo.MaxTicketAge.QuadPart <= (LONGLONG) -1) || (DomainPolicy->PolicyDomainKerbTicketInfo.MaxRenewAge.QuadPart <= (LONGLONG) -1) || (DomainPolicy->PolicyDomainKerbTicketInfo.MaxClockSkew.QuadPart <= (LONGLONG) -1) || (DomainPolicy->PolicyDomainKerbTicketInfo.MaxServiceTicketAge.QuadPart == (LONGLONG) 0) || (DomainPolicy->PolicyDomainKerbTicketInfo.MaxTicketAge.QuadPart == (LONGLONG) 0) || (DomainPolicy->PolicyDomainKerbTicketInfo.MaxRenewAge.QuadPart == (LONGLONG) 0) )
{ _itow(MonitorInfoClass, Class, 10 );
ReportServiceEvent( EVENTLOG_ERROR_TYPE, KDCEVENT_POLICY_UPDATE_FAILED, sizeof(NTSTATUS), &Status, 1, // number of strings
Class ); } else {
_KDC_TgsTicketLifespan = DomainPolicy->PolicyDomainKerbTicketInfo.MaxServiceTicketAge; _KDC_TgtTicketLifespan = DomainPolicy->PolicyDomainKerbTicketInfo.MaxTicketAge; _KDC_TicketRenewSpan = DomainPolicy->PolicyDomainKerbTicketInfo.MaxRenewAge; SkewTime = DomainPolicy->PolicyDomainKerbTicketInfo.MaxClockSkew;
} // Update domain policy flags. Don't depend on the flags keeping in sync
// with the kerberos internal flags
if ( DomainPolicy->PolicyDomainKerbTicketInfo.AuthenticationOptions & POLICY_KERBEROS_VALIDATE_CLIENT) { _KDC_Flags |= AUTH_REQ_VALIDATE_CLIENT; } else { _KDC_Flags &= ~AUTH_REQ_VALIDATE_CLIENT; }
break; case PolicyNotifyAuditEventsInformation:
if ((LocalPolicy->PolicyAuditEventsInfo.AuditingMode) && (LocalPolicy->PolicyAuditEventsInfo.MaximumAuditEventCount > AuditCategoryAccountLogon)) {
if (LocalPolicy->PolicyAuditEventsInfo.EventAuditingOptions[AuditCategoryAccountLogon] & POLICY_AUDIT_EVENT_SUCCESS ) { _KDC_AuditEvents |= KDC_AUDIT_AS_SUCCESS | KDC_AUDIT_TGS_SUCCESS | KDC_AUDIT_MAP_SUCCESS; } else { _KDC_AuditEvents &= ~(KDC_AUDIT_AS_SUCCESS | KDC_AUDIT_TGS_SUCCESS | KDC_AUDIT_MAP_SUCCESS); }
if (LocalPolicy->PolicyAuditEventsInfo.EventAuditingOptions[AuditCategoryAccountLogon] & POLICY_AUDIT_EVENT_FAILURE ) { _KDC_AuditEvents |= KDC_AUDIT_AS_FAILURE | KDC_AUDIT_TGS_FAILURE | KDC_AUDIT_MAP_FAILURE; } else { _KDC_AuditEvents &= ~(KDC_AUDIT_AS_FAILURE | KDC_AUDIT_TGS_FAILURE | KDC_AUDIT_MAP_FAILURE); } }
break; } Release();
Cleanup: if (DomainPolicy != NULL) { LsaIFree_LSAPR_POLICY_DOMAIN_INFORMATION ( PolicyDomainKerberosTicketInformation, DomainPolicy); } if (LocalPolicy != NULL) { LsaIFree_LSAPR_POLICY_INFORMATION( PolicyAuditEventsInformation, LocalPolicy); } return(Status); }
//+-------------------------------------------------------------------------
//
// Function: CSecurityData::SetForestRoot
//
// Synopsis: Sets the forest root
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
NTSTATUS CSecurityData::SetForestRoot( IN PUNICODE_STRING NewForestRoot ) {
NTSTATUS Status; UNICODE_STRING Temp;
WriteLock();
RtlCopyMemory( &Temp, &_ForestRoot, sizeof(UNICODE_STRING) );
Status = KerbDuplicateString( &_ForestRoot, NewForestRoot );
// on alloc failure, just keep old version as it will never change
if (!NT_SUCCESS(Status)) { RtlCopyMemory( &_ForestRoot, &Temp, sizeof(UNICODE_STRING) ); } else { KerbFreeString(&Temp); }
_KDC_IsForestRoot = IsOurRealm(&_ForestRoot);
Release();
return Status;
}
////////////////////////////////////////////////////////////////////
//
// Name: CSecurityData::CSecurityData
//
// Synopsis: Constructor.
//
// Arguments: <none>
//
// Notes: .
//
CSecurityData::CSecurityData() { TRACE(KDC, CSecurityData::CSecurityData, DEB_FUNCTION);
RtlInitUnicodeString( &_MachineName, NULL ); RtlInitUnicodeString( &_MachineUpn, NULL ); RtlInitUnicodeString( &_RealmName, NULL ); RtlInitUnicodeString( &_KDC_Name, NULL );
RtlInitUnicodeString( &_KDC_FullName, NULL );
RtlInitUnicodeString( &_KDC_FullDnsName, NULL );
RtlInitUnicodeString( &_KDC_FullKdcName, NULL );
RtlInitUnicodeString( &_ForestRoot, NULL );
_KerbRealmName = NULL; _KerbDnsRealmName = NULL;
_KrbtgtServiceName = NULL; _KpasswdServiceName = NULL;
RtlZeroMemory( &_KrbtgtTicketInfo, sizeof(KDC_TICKET_INFO) ); _KrbtgtTicketInfoValid = FALSE; _KDC_CrossForestEnabled = FALSE; _KDC_IsForestRoot = FALSE;
RtlInitializeCriticalSection(&_Monitor); }
//+---------------------------------------------------------------------------
//
// Member: CSecurityData::Init
//
// Synopsis: Initializes the global data.
//
// Effects: Allocates memory
//
// Arguments: (none)
//
// Returns: STATUS_SUCCESS or error code
//
// Signals: May raise exception on out of memory.
//
// History: 4-02-93 WadeR Created
//
// Notes: This must be called before any other method of
// CSecurityData. It gets data from the registry, the domain
// object, and the kdc.ini file.
//
//----------------------------------------------------------------------------
NTSTATUS CSecurityData::Init() { TRACE(KDC, CSecurityData::Init, DEB_FUNCTION);
NTSTATUS Status; UNICODE_STRING TempString; WCHAR TempMachineName[CNLEN+1]; ULONG MachineNameLength = CNLEN+1; NET_API_STATUS NetStatus; LARGE_INTEGER MaxAuthenticatorAge; PLSAPR_POLICY_INFORMATION PolicyInfo = NULL; UNICODE_STRING KadminName; UNICODE_STRING ChangePwName;
D_DebugLog(( DEB_TRACE, "Entered CSecurityData::Init()\n" ));
//
// Get the domain name and ID from the registry
//
Status = KerbDuplicateString( &_RealmName, &GlobalDomainName ); if (!NT_SUCCESS(Status)) { goto Cleanup; }
if (!KERB_SUCCESS(KerbConvertUnicodeStringToRealm( &_KerbRealmName, &GlobalDomainName))) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; }
//
// Construct the KDC Name from the realm and the suffix.
//
RtlInitUnicodeString( &TempString, KDC_PRINCIPAL_NAME );
Status = KerbDuplicateString( &_KDC_Name, &TempString ); if (!NT_SUCCESS(Status)) { goto Cleanup; }
if (!GetComputerName( TempMachineName, &MachineNameLength )) { Status = STATUS_BUFFER_TOO_SMALL; goto Cleanup; }
RtlInitUnicodeString( &TempString, TempMachineName ); Status = KerbDuplicateString( &_MachineName, &TempString );
if (!NT_SUCCESS(Status)) { goto Cleanup; }
Status = LsaIQueryInformationPolicyTrusted( PolicyDnsDomainInformation, &PolicyInfo ); if (!NT_SUCCESS(Status)) { goto Cleanup; }
//
// WAS BUG: this DNS name may have a trailing '.' - if so, strip it off
//
if (PolicyInfo->PolicyDnsDomainInfo.DnsDomainName.Length >= sizeof(WCHAR)) { if (PolicyInfo->PolicyDnsDomainInfo.DnsDomainName.Buffer[ -1 + PolicyInfo->PolicyDnsDomainInfo.DnsDomainName.Length / sizeof(WCHAR) ] == L'.') { PolicyInfo->PolicyDnsDomainInfo.DnsDomainName.Length -= sizeof(WCHAR); } }
Status = KerbDuplicateString( &_DnsRealmName, (PUNICODE_STRING) &PolicyInfo->PolicyDnsDomainInfo.DnsDomainName );
if (!NT_SUCCESS(Status)) { goto Cleanup; }
Status = RtlUpcaseUnicodeString( &_DnsRealmName, &_DnsRealmName, FALSE ); if (!NT_SUCCESS(Status)) { goto Cleanup; }
if (!KERB_SUCCESS(KerbConvertUnicodeStringToRealm( &_KerbDnsRealmName, &_DnsRealmName))) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; }
//
// Build the machine UPN: [email protected]
//
_MachineUpn.Length = _MachineName.Length + 2 * sizeof(WCHAR) + _DnsRealmName.Length; _MachineUpn.MaximumLength = _MachineUpn.Length + sizeof(WCHAR); _MachineUpn.Buffer = (LPWSTR) MIDL_user_allocate(_MachineUpn.MaximumLength); if (_MachineUpn.Buffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; }
RtlCopyMemory( _MachineUpn.Buffer, _MachineName.Buffer, _MachineName.Length ); _MachineUpn.Buffer[_MachineName.Length / sizeof(WCHAR)] = L'$'; _MachineUpn.Buffer[1+_MachineName.Length / sizeof(WCHAR)] = L'@'; RtlCopyMemory( _MachineUpn.Buffer + _MachineName.Length / sizeof(WCHAR) + 2 , _DnsRealmName.Buffer, _DnsRealmName.Length ); _MachineUpn.Buffer[_MachineUpn.Length / sizeof(WCHAR)] = L'\0';
if (!KERB_SUCCESS(KerbBuildFullServiceName( &_RealmName, &_KDC_Name, &_KDC_FullName ))) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; }
if (!KERB_SUCCESS(KerbBuildFullServiceName( &_DnsRealmName, &_KDC_Name, &_KDC_FullDnsName ))) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; }
//
// Build the full kdc name - a kerberos style name
//
_KDC_FullKdcName.Length = _KDC_Name.Length + _DnsRealmName.Length + sizeof(WCHAR); _KDC_FullKdcName.MaximumLength = _KDC_FullKdcName.Length + sizeof(WCHAR); _KDC_FullKdcName.Buffer = (LPWSTR) MIDL_user_allocate(_KDC_FullDnsName.MaximumLength); if (_KDC_FullKdcName.Buffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; }
RtlCopyMemory( _KDC_FullKdcName.Buffer, _KDC_Name.Buffer, _KDC_Name.Length ); _KDC_FullKdcName.Buffer[_KDC_Name.Length / sizeof(WCHAR)] = L'/'; RtlCopyMemory( _KDC_FullKdcName.Buffer + 1 + _KDC_Name.Length / sizeof(WCHAR), _DnsRealmName.Buffer, _DnsRealmName.Length ); _KDC_FullKdcName.Buffer[_KDC_FullKdcName.Length / sizeof(WCHAR)] = L'\0';
D_DebugLog((DEB_TRACE, "_KDC_Name='%wZ', MachineName='%wZ'\n", &_KDC_Name, &_MachineName ));
if (!KERB_SUCCESS(KerbBuildFullServiceKdcName( &_DnsRealmName, &_KDC_Name, KRB_NT_SRV_INST, &_KrbtgtServiceName ))) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; }
//
// Build the kdc name for kadmin/changepw.
//
RtlInitUnicodeString( &KadminName, KERB_KPASSWD_NAME ); RtlInitUnicodeString( &ChangePwName, L"changepw" );
if (!KERB_SUCCESS(KerbBuildFullServiceKdcName( &ChangePwName, &KadminName, KRB_NT_SRV_INST, &_KpasswdServiceName ))) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; }
Status = LoadParameters(GlobalAccountDomainHandle);
if (!NT_SUCCESS(Status)) { DebugLog((DEB_ERROR,"Failed to load parameters: 0x%x\n",Status)); goto Cleanup; }
//
// Create the authenticators.
//
//
// In reality, set skew time to 5 minutes and same for authenticators.
//
SkewTime.QuadPart = (LONGLONG) 10000000 * 60 * 5; MaxAuthenticatorAge = SkewTime;
//
// Create the authenticator list
//
Authenticators = new CAuthenticatorList( MaxAuthenticatorAge ); if (Authenticators == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; }
//
// Setup a list to track failed requests - we don't fail the
// same request twice for the timeout time
//
FailedRequests = new CAuthenticatorList( MaxAuthenticatorAge ); if (FailedRequests == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; }
//
// Register for policy callbacks
//
Status = LsaIRegisterPolicyChangeNotificationCallback( KdcPolicyChangeCallBack, PolicyNotifyDomainKerberosTicketInformation );
if (NT_SUCCESS(Status)) { Status = LsaIRegisterPolicyChangeNotificationCallback( KdcPolicyChangeCallBack, PolicyNotifyAuditEventsInformation );
} if (!NT_SUCCESS(Status)) { DebugLog((DEB_ERROR,"Failed to register for policy changes: 0x%x\n",Status)); goto Cleanup; }
Status = UpdateKrbtgtTicketInfo(); if (!NT_SUCCESS(Status)) { goto Cleanup; }
Cleanup: if (PolicyInfo != NULL) { LsaIFree_LSAPR_POLICY_INFORMATION( PolicyDnsDomainInformation, PolicyInfo ); } return(Status);
}
//+---------------------------------------------------------------------------
//
// Member: CSecurityData::~CSecurityData
//
// Synopsis: Destructor
//
// Effects: Frees memory
//
// Arguments: (none)
//
// History: 4-02-93 WadeR Created
//
// Notes:
//
//----------------------------------------------------------------------------
VOID CSecurityData::Cleanup() { TRACE(KDC, CSecurityData::Cleanup, DEB_FUNCTION);
KerbFreeString(&_RealmName); KerbFreeString(&_KDC_Name); KerbFreeString(&_KDC_FullName); KerbFreeString(&_KDC_FullDnsName); KerbFreeString(&_KDC_FullKdcName); KerbFreeString(&_MachineName); KerbFreeString(&_MachineUpn); KerbFreeString(&_DnsRealmName); KerbFreeRealm(&_KerbRealmName); KerbFreeRealm(&_KerbDnsRealmName); KerbFreeKdcName(&_KrbtgtServiceName); KerbFreeKdcName(&_KpasswdServiceName);
if (Authenticators != NULL) { delete Authenticators; Authenticators = NULL; } if (FailedRequests != NULL) { delete FailedRequests; FailedRequests = NULL; }
LsaIUnregisterAllPolicyChangeNotificationCallback( KdcPolicyChangeCallBack );
}
//+---------------------------------------------------------------------------
//
// Member: CSecurityData::~CSecurityData
//
// Synopsis: Destructor
//
// Effects: Frees memory
//
// Arguments: (none)
//
// History: 4-02-93 WadeR Created
//
// Notes:
//
//----------------------------------------------------------------------------
CSecurityData::~CSecurityData() { TRACE(KDC, CSecurityData::~CSecurityData, DEB_FUNCTION);
Cleanup();
//
// This doesn't happen during Cleanup() because we want to
// make sure it only happens once.
//
RtlDeleteCriticalSection(&_Monitor); }
NTSTATUS CSecurityData::LoadParameters(SAMPR_HANDLE DomainHandle) { NTSTATUS Status = STATUS_SUCCESS; LARGE_INTEGER TempDeltaTime; LARGE_INTEGER OneHour, EightHours, TenHours; TRACE(KDC, CSecurityData::LoadParameters, DEB_FUNCTION);
OneHour.QuadPart = (LONGLONG) 10000000 * 60 * 60 * 1; EightHours.QuadPart = (LONGLONG) 10000000 * 60 * 60 * 8; TenHours.QuadPart = (LONGLONG) 10000000 * 60 * 60 * 10;
// New internal defaults according to JBrezak. 7/28/99
//
// Initialize Tgt lifetime to 10 hours.
//
_KDC_TgtTicketLifespan = TenHours;
//
// Initialize ticket max renew time to one hour.
//
_KDC_TicketRenewSpan = OneHour;
//
// Initialize Tgs lifetime to one hour.
//
_KDC_TgsTicketLifespan = OneHour;
//
// Initialize domain password replication skew tolerance to 60 minutes.
//
_KDC_DomainPasswordReplSkew.QuadPart = (LONGLONG) 60*60*10000000;
//
// Initialize restriciton lifetime to 20 minutes
//
_KDC_RestrictionLifetime.QuadPart = (LONGLONG) 20*60*10000000;
//
// Default authentication flags
//
_KDC_Flags = AUTH_REQ_ALLOW_FORWARDABLE | AUTH_REQ_ALLOW_PROXIABLE | AUTH_REQ_ALLOW_POSTDATE | AUTH_REQ_ALLOW_RENEWABLE | AUTH_REQ_ALLOW_NOADDRESS | AUTH_REQ_ALLOW_ENC_TKT_IN_SKEY | AUTH_REQ_ALLOW_VALIDATE | AUTH_REQ_VALIDATE_CLIENT | AUTH_REQ_OK_AS_DELEGATE;
_KDC_AuditEvents = 0;
//
// Get kerberos policy information
//
Status = ReloadPolicy( PolicyNotifyDomainKerberosTicketInformation ); if (!NT_SUCCESS(Status)) { if ((Status != STATUS_NOT_FOUND) && (Status != STATUS_OBJECT_NAME_NOT_FOUND)) { DebugLog((DEB_ERROR,"Failed to reload kerberos ticket policy: 0x%x\n",Status)); goto Cleanup; } Status = STATUS_SUCCESS; }
//
// Get audit information
//
Status = ReloadPolicy( PolicyNotifyAuditEventsInformation );
if (!NT_SUCCESS(Status)) { if (Status != STATUS_NOT_FOUND) { DebugLog((DEB_ERROR,"Failed to query audit event info: 0x%x\n",Status)); goto Cleanup; } Status = STATUS_SUCCESS; }
Cleanup:
#if DBG
DebugShowState(); #endif
return(Status); }
//+-------------------------------------------------------------------------
//
// Function: CSecurityData::GetKrbtgtTicketInfo
//
// Synopsis: Duplicates ticket info for krbtgt account
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
KERBERR CSecurityData::GetKrbtgtTicketInfo( OUT PKDC_TICKET_INFO TicketInfo ) { KERBERR KerbErr = KDC_ERR_NONE; ULONG CredentialSize;
RtlZeroMemory( TicketInfo, sizeof(KDC_TICKET_INFO) );
ReadLock(); if (!_KrbtgtTicketInfoValid) { KerbErr = KDC_ERR_S_PRINCIPAL_UNKNOWN; goto Cleanup; }
//
// Duplicate the cached copy of the KRBTGT information
//
*TicketInfo = _KrbtgtTicketInfo; TicketInfo->Passwords = NULL; TicketInfo->OldPasswords = NULL; TicketInfo->TrustSid = NULL; TicketInfo->AccountName.Buffer = NULL;
if (!NT_SUCCESS(KerbDuplicateString( &TicketInfo->AccountName, &_KrbtgtTicketInfo.AccountName ))) { KerbErr = KRB_ERR_GENERIC; goto Cleanup; }
KerbErr = KdcDuplicateCredentials( &TicketInfo->Passwords, &CredentialSize, _KrbtgtTicketInfo.Passwords, FALSE // don't marshall
);
if (!KERB_SUCCESS(KerbErr)) { goto Cleanup; } KerbErr = KdcDuplicateCredentials( &TicketInfo->OldPasswords, &CredentialSize, _KrbtgtTicketInfo.OldPasswords, FALSE // don't marshall
);
Cleanup: Release();
if (!KERB_SUCCESS(KerbErr)) { FreeTicketInfo(TicketInfo); } return(KerbErr); }
//+-------------------------------------------------------------------------
//
// Function: CSecurityData::UpdateKrbtgtTicketInfo
//
// Synopsis: Triggers an update of the krbtgt ticket info
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
NTSTATUS CSecurityData::UpdateKrbtgtTicketInfo( VOID ) { NTSTATUS Status = STATUS_SUCCESS; KERBERR KerbErr; KDC_TICKET_INFO NewTicketInfo = {0}; PUSER_INTERNAL6_INFORMATION UserInfo = NULL; KERB_EXT_ERROR ExtendedError; // dummy var
ReadLock(); _KrbtgtTicketInfoValid = FALSE;
KerbErr = KdcGetTicketInfo( SecData.KdcServiceName(), 0, // no lookup flags
NULL, // no principal name
NULL, // no realm
&NewTicketInfo, &ExtendedError, // dummy
NULL, // no user handle
USER_ALL_PASSWORDLASTSET, 0L, // no extended fields
&UserInfo, NULL // no group membership
);
if (KERB_SUCCESS(KerbErr)) { FreeTicketInfo( &_KrbtgtTicketInfo ); _KrbtgtTicketInfo = NewTicketInfo; _KrbtgtTicketInfoValid = TRUE; _KrbtgtPasswordLastSet = UserInfo->I1.PasswordLastSet;
SamIFree_UserInternal6Information( UserInfo ); } else { Status = KerbMapKerbError(KerbErr); } Release(); return(Status); }
//+-------------------------------------------------------------------------
//
// Function: KdcAccountChangeNotificationRoutine
//
// Synopsis: Receives notification of changes to interesting accounts
//
// Effects: updatees cached krbtgt information
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
NTSTATUS KdcAccountChangeNotification ( IN PSID DomainSid, IN SECURITY_DB_DELTA_TYPE DeltaType, IN SECURITY_DB_OBJECT_TYPE ObjectType, IN ULONG ObjectRid, IN OPTIONAL PUNICODE_STRING ObjectName, IN PLARGE_INTEGER ModifiedCount, IN PSAM_DELTA_DATA DeltaData OPTIONAL ) { NTSTATUS Status;
//
// We are only interested in the krbtgt account
//
if (ObjectRid != DOMAIN_USER_RID_KRBTGT) { return(STATUS_SUCCESS); }
Status = SecData.UpdateKrbtgtTicketInfo(); if (!NT_SUCCESS(Status)) { DebugLog((DEB_ERROR,"Failed to update krbtgt ticket info: 0x%x\n",Status)); } return(Status); }
#if DBG
////////////////////////////////////////////////////////////////////////////
//
// Some debugging functions.
//
void CSecurityData::DebugShowState(void) { TRACE(KDC, CSecurityData::DebugShowState, DEB_FUNCTION);
PrintTime(DEB_TRACE, " TGT Ticket lifespan\t", &_KDC_TgtTicketLifespan ); PrintTime(DEB_TRACE, " Ticket Renew Span\t",&_KDC_TicketRenewSpan ); D_DebugLog((DEB_TRACE, " Blank Addresses?\t%s\n",(_KDC_Flags & AUTH_REQ_ALLOW_NOADDRESS ? "Yes" : "No"))); D_DebugLog((DEB_TRACE, " Proxies? \t%s\n", (_KDC_Flags & AUTH_REQ_ALLOW_PROXIABLE ? "Yes" : "No"))); D_DebugLog((DEB_TRACE, " Renewable? \t%s\n", (_KDC_Flags & AUTH_REQ_ALLOW_RENEWABLE ? "Yes" : "No"))); D_DebugLog((DEB_TRACE, " Postdated? \t%s\n", (_KDC_Flags & AUTH_REQ_ALLOW_POSTDATE ? "Yes" : "No"))); D_DebugLog((DEB_TRACE, " Forwardable? \t%s\n", (_KDC_Flags & AUTH_REQ_ALLOW_FORWARDABLE ? "Yes" : "No")));
}
NTSTATUS CSecurityData::DebugGetState( DWORD * KDCFlags, TimeStamp * MaxLifespan, TimeStamp * MaxRenewSpan) { TRACE(KDC, CSecurityData::DebugGetState, DEB_FUNCTION);
*KDCFlags = _KDC_Flags; *MaxLifespan = _KDC_TgtTicketLifespan; *MaxRenewSpan = _KDC_TicketRenewSpan; return(STATUS_SUCCESS); }
NTSTATUS CSecurityData::DebugSetState( DWORD KDCFlags, TimeStamp MaxLifespan, TimeStamp MaxRenewSpan) { TRACE(KDC, CSecurityData::DebugSetState, DEB_FUNCTION);
_KDC_Flags = KDC_AUTH_STATE(KDCFlags); _KDC_AuditEvents = KDC_AUDIT_STATE(KDCFlags); _KDC_TgtTicketLifespan = MaxLifespan; _KDC_TicketRenewSpan = MaxRenewSpan; return(STATUS_SUCCESS); }
#endif // DBG
|