|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1992.
//
// File: debug.cxx
//
// Contents: Debug definitions that shouldn't be necessary
// in the retail build.
//
// History: 19-Nov-92 WadeR Created
//
// Notes: If you change or add a debug level, also fix debug.hxx
// This is only compiled if DBG > 0
//
//--------------------------------------------------------------------------
#include "kdcsvr.hxx"
#include <kdcdbg.h>
#include "debug.hxx"
#include <tostring.hxx>
//
// The "#pragma hdrstop" causes the preprocessor to forget any "#if"s
// is is processing. Therefore you can't have it inside an "#if" block.
// So the includes will always compile, and the rest of this code becomes
// conditional.
//
#include <stddef.h>
#ifdef RETAIL_LOG_SUPPORT
//
// Variables for heap checking and used by sectrace.hxx:
//
// Set following to HEAP_CHECK_ON_ENTER | HEAP_CHECK_ON_EXIT for heap checking.
DWORD dwHeapChecking = 0;
// This keeps a registry key handle to the HKLM\System\CCSet\Control\LSA\ // Kerberoskey
HKEY hKeyParams = NULL; HANDLE hWait = NULL;
// Set following to address of a function which takes 0 arguments and returns
// a void for arbitrary run time checking.
VOID (*debugFuncAddr)() = NULL;
//
// Tons and tons of global data to get debugging params from the ini file.
//
// Note: For every trace bit, there must be a label in this array matching
// that trace bit and only that trace bit. There can be other labels
// matching combinations of trace bits.
//
DEBUG_KEY KdcDebugKeys[] = { {DEB_ERROR, "Error"}, {DEB_WARN, "Warning"}, {DEB_TRACE, "Trace"}, {DEB_T_KDC, "Kdc"}, {DEB_T_TICKETS, "Tickets"}, {DEB_T_DOMAIN, "Domain"}, {DEB_T_SOCK, "Sock"}, {DEB_T_TRANSIT, "Transit"}, {DEB_T_PERF_STATS, "Perf"}, {DEB_T_PKI, "PKI"}, {0, NULL}, };
DEFINE_DEBUG2(KDC); extern DWORD KSuppInfoLevel; // needed to adjust values for common2 dir
////////////////////////////////////////////////////////////////////
//
// Name: KerbGetKDCRegParams
//
// Synopsis: Gets the debug paramaters from the registry
//
// Arguments: HKEY to HKLM/System/CCS/LSA/Kerberos
//
// Notes: Sets KDCInfolevel for debug spew
//
void KerbGetKDCRegParams(HKEY ParamKey) {
DWORD cbType, tmpInfoLevel = KDCInfoLevel, cbSize = sizeof(DWORD); DWORD dwErr; dwErr = RegQueryValueExW( ParamKey, WSZ_DEBUGLEVEL, NULL, &cbType, (LPBYTE)&tmpInfoLevel, &cbSize ); if (dwErr != ERROR_SUCCESS) { if (dwErr == ERROR_FILE_NOT_FOUND) { // no registry value is present, don't want info
// so reset to defaults
// NOTE: Since SCLogon sux so badly, we're going to log all PKI events for now.
// FESTER: Pull for server B3.
#if DBG
KSuppInfoLevel = KDCInfoLevel = DEB_ERROR | DEB_T_PKI; #else // fre
KSuppInfoLevel = KDCInfoLevel = DEB_T_PKI; #endif
}else{ DebugLog((DEB_WARN, "Failed to query DebugLevel: 0x%x\n", dwErr)); }
}
// TBD: Validate flags?
KSuppInfoLevel = KDCInfoLevel = tmpInfoLevel; return; }
//
// Tempo?
//
/*void FillExtError(PKERB_EXT_ERROR p,NTSTATUS s,ULONG f,ULONG l)
{ if (EXT_ERROR_ON(KDCInfoLevel)) \ { p->status = s; p->klininfo = KLIN(f,l); } sprintf(xx, "XX File-%i, Line-%i", f,l); OutputDebugStringA(xx); } */
////////////////////////////////////////////////////////////////////
//
// Name: KerbWatchParamKey
//
// Synopsis: Sets RegNotifyChangeKeyValue() on param key, initializes
// debug level, then utilizes thread pool to wait on
// changes to this registry key. Enables dynamic debug
// level changes, as this function will also be callback
// if registry key modified.
//
// Arguments: pCtxt is actually a HANDLE to an event. This event
// will be triggered when key is modified.
//
// Notes: .
//
VOID KerbWatchParamKey(PVOID pCtxt, BOOLEAN fWaitStatus) { NTSTATUS Status; LONG lRes = ERROR_SUCCESS; if (NULL == hKeyParams) // first time we've been called.
{ lRes = RegOpenKeyExW( HKEY_LOCAL_MACHINE, KERB_PARAMETER_PATH, 0, KEY_READ, &hKeyParams); if (ERROR_SUCCESS != lRes) { DebugLog((DEB_WARN,"Failed to open kerberos key: 0x%x\n", lRes)); goto Reregister; } }
if (NULL != hWait) { Status = RtlDeregisterWait(hWait); if (!NT_SUCCESS(Status)) { DebugLog((DEB_WARN, "Failed to Deregister wait on registry key: 0x%x\n", Status)); goto Reregister; }
}
lRes = RegNotifyChangeKeyValue( hKeyParams, FALSE, REG_NOTIFY_CHANGE_LAST_SET, (HANDLE) pCtxt, TRUE);
if (ERROR_SUCCESS != lRes) { DebugLog((DEB_ERROR,"Debug RegNotify setup failed: 0x%x\n", lRes)); // we're tanked now. No further notifications, so get this one
} KerbGetKDCRegParams(hKeyParams); Reregister: Status = RtlRegisterWait(&hWait, (HANDLE) pCtxt, KerbWatchParamKey, (HANDLE) pCtxt, INFINITE, WT_EXECUTEONLYONCE);
} ////////////////////////////////////////////////////////////////////
//
// Name: WaitCleanup
//
// Synopsis: Cleans up for KerbWatchParamKey
//
// Arguments: <none>
//
// Notes: .
//
VOID WaitCleanup(HANDLE hEvent) { NTSTATUS Status = STATUS_SUCCESS;
if (NULL != hWait) { Status = RtlDeregisterWait(hWait); hWait = NULL; }
if (NT_SUCCESS(Status) && NULL != hEvent) { CloseHandle(hEvent); hEvent = NULL; } }
////////////////////////////////////////////////////////////////////
//
// Name: GetDebugParams
//
// Synopsis: Gets the debug paramaters from the ini file.
//
// Arguments: <none>
//
// Notes: .
//
void GetDebugParams() {
CHAR chBuf[128]; DWORD cbBuf;
KDCInitDebug(KdcDebugKeys); }
#if DBG // moved here to utilize debug logging in free builds.
NTSTATUS KDC_GetState( handle_t hBinding, DWORD * KDCFlags, DWORD * MaxLifespan, DWORD * MaxRenewSpan, PTimeStamp FudgeFactor) { *FudgeFactor = SkewTime;
TimeStamp tsLife, tsRenew;
NTSTATUS hr = SecData.DebugGetState(KDCFlags, &tsLife, &tsRenew ); tsLife.QuadPart = (tsLife.QuadPart / ulTsPerSecond); *MaxLifespan =tsLife.LowPart; tsRenew.QuadPart = (tsRenew.QuadPart / ulTsPerSecond); *MaxRenewSpan = tsRenew.LowPart; return(hr); }
NTSTATUS KDC_SetState( handle_t hBinding, DWORD KdcFlags, DWORD MaxLifespan, DWORD MaxRenewSpan, TimeStamp FudgeFactor) { NTSTATUS hr; TimeStamp tsLife = {0,0}; TimeStamp tsRenew = {0,0}; UNICODE_STRING ss;
if (FudgeFactor.QuadPart != 0) { SkewTime = FudgeFactor; Authenticators->SetMaxAge( SkewTime ); }
tsLife.QuadPart = (LONGLONG) MaxLifespan * 10000000; tsRenew.QuadPart = (LONGLONG) MaxRenewSpan * 10000000;
if (KdcFlags == 0) { KdcFlags = SecData.KdcFlags(); } if (MaxLifespan == 0) { tsLife = SecData.KdcTgtTicketLifespan(); }
if (MaxRenewSpan == 0) { tsLife = SecData.KdcTicketRenewSpan(); }
hr = SecData.DebugSetState(KdcFlags, tsLife, tsRenew);
SecData.DebugShowState();
return(hr); }
void PrintIntervalTime ( ULONG DebugFlag, LPSTR Message, PLARGE_INTEGER Interval ) { LONGLONG llTime = Interval->QuadPart; LONG lSeconds = (LONG) ( llTime / 10000000 ); LONG lMinutes = ( lSeconds / 60 ) % 60; LONG lHours = ( lSeconds / 3600 ); DebugLog(( DebugFlag, "%s %d:%2.2d:%2.2d \n", Message, lHours, lMinutes, lSeconds % 60 )); }
void PrintTime ( ULONG DebugFlag, LPSTR Message, PLARGE_INTEGER Time ) { SYSTEMTIME st;
FileTimeToSystemTime ( (PFILETIME) Time, & st ); DebugLog((DebugFlag, "%s %d-%d-%d %d:%2.2d:%2.2d\n", Message, st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond )); }
#else // DBG
NTSTATUS KDC_GetState( handle_t hBinding, DWORD * KDCFlags, DWORD * MaxLifespan, DWORD * MaxRenewSpan, PTimeStamp FudgeFactor) { return(STATUS_NOT_SUPPORTED); }
NTSTATUS KDC_SetState( handle_t hBinding, DWORD KDCFlags, DWORD MaxLifespan, DWORD MaxRenewSpan, TimeStamp FudgeFactor) { return(STATUS_NOT_SUPPORTED); }
#endif
#endif
BOOLEAN KdcSetPassSupported( VOID ) { NET_API_STATUS NetStatus; ULONG SetPassUnsupported = 0; LPNET_CONFIG_HANDLE ConfigHandle = NULL;
NetStatus = NetpOpenConfigData( &ConfigHandle, NULL, // noserer name
L"kdc", TRUE // read only
); if (NetStatus != NO_ERROR) { return(TRUE); } NetStatus = NetpGetConfigDword( ConfigHandle, L"SetPassUnsupported", 0, &SetPassUnsupported );
NetpCloseConfigData( ConfigHandle ); if ((NetStatus == NO_ERROR) && (SetPassUnsupported == 1)) { return(FALSE); } else { return(TRUE); } }
//+-------------------------------------------------------------------------
//
// Function: KDC_SetPassword
//
// Synopsis: Sets password for an account
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
NTSTATUS KDC_SetPassword( IN handle_t hBinding, IN PUNICODE_STRING UserName, IN PUNICODE_STRING PrincipalName, IN PUNICODE_STRING Password, IN ULONG Flags ) { NTSTATUS Status = STATUS_SUCCESS; KERBERR KerbErr; SECPKG_SUPPLEMENTAL_CRED Credentials; KDC_TICKET_INFO TicketInfo; SAMPR_HANDLE UserHandle = NULL; UNICODE_STRING NewUserName; KERB_EXT_ERROR ExtendedError; // dummy var.
Credentials.Credentials = NULL;
if (!KdcSetPassSupported()) { Status = STATUS_NOT_SUPPORTED; goto Cleanup; }
//
// Make sure we can impersonate the caller.
//
if (RpcImpersonateClient(NULL) != ERROR_SUCCESS) { Status = STATUS_ACCESS_DENIED; goto Cleanup; } else { RpcRevertToSelf(); }
// According to bug 228139, rpc definition of unicode strings allow
// for odd lengths. We will set them to even (1 less) so that we
// don't av in the lsa.
if (ARGUMENT_PRESENT(UserName) && UserName->Buffer) { UserName->Length = (UserName->Length/sizeof(WCHAR)) * sizeof(WCHAR); } else { Status = STATUS_INVALID_PARAMETER; goto Cleanup; }
KerbErr = KdcGetTicketInfo( UserName, 0, // no flags
NULL, NULL, &TicketInfo, &ExtendedError, &UserHandle, 0L, // no fields to fetch
0L, // no extended fields
NULL, // no user all
NULL ); if (!KERB_SUCCESS(KerbErr)) { DebugLog((DEB_ERROR, "Failed to get ticket info for %wZ: 0x%x\n", UserName, KerbErr )); Status = STATUS_NO_SUCH_USER; goto Cleanup; } FreeTicketInfo(&TicketInfo);
if (ARGUMENT_PRESENT(Password) && Password->Buffer) { Password->Length = (Password->Length/sizeof(WCHAR)) * sizeof(WCHAR); } else { Status = STATUS_INVALID_PARAMETER; goto Cleanup; }
if (ARGUMENT_PRESENT(PrincipalName) && PrincipalName->Buffer) { PrincipalName->Length = (PrincipalName->Length/sizeof(WCHAR)) * sizeof(WCHAR); } else { Status = STATUS_INVALID_PARAMETER; goto Cleanup; }
Status = KdcBuildPasswordList( Password, PrincipalName, SecData.KdcDnsRealmName(), UnknownAccount, NULL, // no stored creds
0, // no stored creds
TRUE, // marshall
FALSE, // don't include builtins
Flags, Unknown, (PKERB_STORED_CREDENTIAL *) &Credentials.Credentials, &Credentials.CredentialSize ); if (!NT_SUCCESS(Status)) { goto Cleanup; }
RtlInitUnicodeString( &Credentials.PackageName, MICROSOFT_KERBEROS_NAME_W );
Status = SamIStorePrimaryCredentials( UserHandle, &Credentials ); if (!NT_SUCCESS(Status)) { DebugLog((DEB_ERROR, "Failed to store primary credentials: 0x%x\n",Status)); goto Cleanup; }
Cleanup: if (UserHandle != NULL) { SamrCloseHandle(&UserHandle); } if (Credentials.Credentials != NULL) { MIDL_user_free(Credentials.Credentials); } return(Status); }
NTSTATUS KDC_GetDomainList( IN handle_t hBinding, OUT PKDC_DBG_DOMAIN_LIST * DomainList ) { NTSTATUS Status = STATUS_SUCCESS; PKDC_DBG_DOMAIN_LIST TempList; PKDC_DBG_DOMAIN_INFO DomainInfo = NULL; PKDC_DOMAIN_INFO Domain; ULONG DomainCount = 0; PLIST_ENTRY ListEntry; ULONG Index = 0;
*DomainList = NULL;
KdcLockDomainListFn();
TempList = (PKDC_DBG_DOMAIN_LIST) MIDL_user_allocate(sizeof(KDC_DBG_DOMAIN_LIST)); if (TempList == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; }
for (ListEntry = KdcDomainList.Flink; ListEntry != &KdcDomainList ; ListEntry = ListEntry->Flink ) { DomainCount++; }
DomainInfo = (PKDC_DBG_DOMAIN_INFO) MIDL_user_allocate(DomainCount * sizeof(KDC_DBG_DOMAIN_INFO)); if (DomainInfo == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } RtlZeroMemory( DomainInfo, DomainCount * sizeof(KDC_DBG_DOMAIN_INFO) );
Index = 0; for (ListEntry = KdcDomainList.Flink; ListEntry != &KdcDomainList ; ListEntry = ListEntry->Flink ) { Domain = (PKDC_DOMAIN_INFO) CONTAINING_RECORD(ListEntry, KDC_DOMAIN_INFO, Next); KerbDuplicateString( &DomainInfo[Index].DnsName, &Domain->DnsName ); KerbDuplicateString( &DomainInfo[Index].NetbiosName, &Domain->NetbiosName ); if (Domain->ClosestRoute != NULL) { KerbDuplicateString( &DomainInfo[Index].ClosestRoute, &Domain->ClosestRoute->DnsName ); } DomainInfo->Type = Domain->Type; DomainInfo->Attributes = Domain->Attributes; Index++; }
TempList->Count = DomainCount; TempList->Domains = DomainInfo; *DomainList = TempList; TempList = NULL; DomainInfo = NULL;
Cleanup: KdcUnlockDomainListFn();
if (TempList != NULL) { MIDL_user_free(TempList); } if (DomainInfo != NULL) { MIDL_user_free(DomainInfo); }
return(Status); }
VOID KdcCopyKeyData( OUT PKERB_KEY_DATA NewKey, IN PKERB_KEY_DATA OldKey, IN OUT PBYTE * Where, IN LONG_PTR Offset ) { //
// Copy the key
//
NewKey->Key.keytype = OldKey->Key.keytype; NewKey->Key.keyvalue.length = OldKey->Key.keyvalue.length; NewKey->Key.keyvalue.value = (*Where) - Offset; RtlCopyMemory( (*Where), OldKey->Key.keyvalue.value, OldKey->Key.keyvalue.length ); (*Where) += OldKey->Key.keyvalue.length;
//
// Copy the salt
//
if (OldKey->Salt.Buffer != NULL) { NewKey->Salt.Length = NewKey->Salt.MaximumLength = OldKey->Salt.Length; NewKey->Salt.Buffer = (LPWSTR) ((*Where) - Offset); RtlCopyMemory( (*Where), OldKey->Salt.Buffer, OldKey->Salt.Length ); (*Where) += OldKey->Salt.Length;
}
}
//+-------------------------------------------------------------------------
//
// Function: KDC_SetAccountKeys
//
// Synopsis: Set the keys for an account
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
NTSTATUS KDC_SetAccountKeys( IN handle_t hBinding, IN PUNICODE_STRING UserName, IN ULONG Flags, IN PKERB_STORED_CREDENTIAL Keys ) { NTSTATUS Status = STATUS_SUCCESS; KERBERR KerbErr; KERB_EXT_ERROR ExtendedError; // dummy var
SECPKG_SUPPLEMENTAL_CRED Credentials = {0}; KDC_TICKET_INFO TicketInfo= {0}; SAMPR_HANDLE UserHandle = NULL; PKERB_STORED_CREDENTIAL StoredCreds = NULL; PKERB_STORED_CREDENTIAL Passwords = NULL; ULONG StoredCredSize = 0; ULONG CredentialCount = 0; ULONG CredentialIndex = 0; ULONG Index; PBYTE Where; UNICODE_STRING DefaultSalt; LONG_PTR Offset;
if (!KdcSetPassSupported()) { Status = STATUS_NOT_SUPPORTED; goto Cleanup; }
//
// Make sure we can impersonate the caller.
//
if (RpcImpersonateClient(NULL) != ERROR_SUCCESS) { Status = STATUS_ACCESS_DENIED; goto Cleanup; } else { RpcRevertToSelf(); }
// According to bug 228139, rpc definition of unicode strings allow
// for odd lengths. We will set them to even (1 less) so that we
// don't av in the lsa.
if (ARGUMENT_PRESENT(UserName) && UserName->Buffer) { UserName->Length = (UserName->Length/sizeof(WCHAR)) * sizeof(WCHAR); } else { Status = STATUS_INVALID_PARAMETER; goto Cleanup; }
KerbErr = KdcGetTicketInfo( UserName, 0, // no flags
NULL, NULL, &TicketInfo, &ExtendedError, &UserHandle, 0L, // no fields to fetch
0L, // no extended fields
NULL, // no user all
NULL ); if (!KERB_SUCCESS(KerbErr)) { DebugLog((DEB_ERROR, "Failed to get ticket info for %wZ: 0x%x\n", UserName, KerbErr )); Status = STATUS_NO_SUCH_USER; goto Cleanup; }
//
// If the caller asks us to replace keys, then clobber all supplemental
// creds with the new ones. Otherwise, just replace the current ones
// with the old ones
//
Passwords = TicketInfo.Passwords;
if ((Flags & KERB_SET_KEYS_REPLACE) || (Passwords == NULL)) { KerbErr = KdcDuplicateCredentials( &StoredCreds, &StoredCredSize, Keys, TRUE // marshall
); if (!KERB_SUCCESS(KerbErr)) { Status = KerbMapKerbError(KerbErr); goto Cleanup; } } else {
if (Keys->OldCredentialCount != 0) { DebugLog((DEB_ERROR,"OldCredentialCount supplied with merge-in keys - illegal\n")); Status = STATUS_INVALID_PARAMETER; goto Cleanup; } //
// Calculate the size of the stored creds.
//
StoredCredSize = FIELD_OFFSET(KERB_STORED_CREDENTIAL,Credentials) + Keys->CredentialCount * sizeof(KERB_KEY_DATA) + Keys->DefaultSalt.Length;
for (Index = 0; Index < Keys->CredentialCount; Index++ ) { StoredCredSize += Keys->Credentials[Index].Salt.Length + Keys->Credentials[Index].Key.keyvalue.length; CredentialCount++; }
//
// Add in the keys that aren't in the supplied ones
//
if (Keys->DefaultSalt.Buffer == NULL) { StoredCredSize += Passwords->DefaultSalt.Length; }
//
// Add the size for all the keys in the passwords that weren't
// in the passed in keys
//
for (Index = 0; Index < Passwords->CredentialCount ; Index++ ) { if (KerbGetKeyFromList(Keys, Passwords->Credentials[Index].Key.keytype) == NULL) { //
// Make sure it is not a builtin
//
if ((Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_LM) || (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_MD4) || (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_OLD) || (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_OLD_EXP) || (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_NT) || (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_NT_EXP) || (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_NULL)) { continue; } StoredCredSize += Passwords->Credentials[Index].Salt.Length + Passwords->Credentials[Index].Key.keyvalue.length + sizeof(KERB_KEY_DATA); CredentialCount++; } }
//
// Add in the old keys
//
for (Index = 0; Index < Passwords->OldCredentialCount; Index++ ) { StoredCredSize += sizeof(KERB_KEY_DATA) + Passwords->Credentials[Index + Passwords->OldCredentialCount].Salt.Length + Passwords->Credentials[Index + Passwords->OldCredentialCount].Key.keyvalue.length; }
//
// Allocate a new buffer to contain the marshalled keys
//
StoredCreds = (PKERB_STORED_CREDENTIAL) MIDL_user_allocate(StoredCredSize); if (StoredCreds == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; }
RtlZeroMemory( StoredCreds, StoredCredSize ); //
// Set the standard bits
//
StoredCreds->Revision = KERB_PRIMARY_CRED_REVISION; StoredCreds->Flags = 0;
Offset = (LONG_PTR) StoredCreds; Where = (PBYTE) &(StoredCreds->Credentials[CredentialCount + Passwords->OldCredentialCount]);
//
// Copy in the default salt.
//
if (Keys->DefaultSalt.Buffer != NULL) { DefaultSalt = Keys->DefaultSalt; } else { DefaultSalt = Passwords->DefaultSalt; } if (DefaultSalt.Buffer != NULL) { StoredCreds->DefaultSalt.Length = StoredCreds->DefaultSalt.MaximumLength = DefaultSalt.Length; StoredCreds->DefaultSalt.Buffer = (LPWSTR) (Where - Offset); RtlCopyMemory( Where, DefaultSalt.Buffer, DefaultSalt.Length ); Where += DefaultSalt.Length; }
//
// Copy in all the new keys
//
for (Index = 0; Index < Keys->CredentialCount ; Index++ ) { KdcCopyKeyData( &StoredCreds->Credentials[CredentialIndex], &Keys->Credentials[Index], &Where, Offset ); CredentialIndex++;
}
//
// Copy in the existing keys
//
for (Index = 0; Index < Passwords->CredentialCount ; Index++ ) { if (KerbGetKeyFromList(Keys, Passwords->Credentials[Index].Key.keytype) == NULL) { if ((Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_LM) || (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_MD4) || (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_OLD) || (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_OLD_EXP) || (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_NT) || (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_NT_EXP) || (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_NULL)) { continue; }
KdcCopyKeyData( &StoredCreds->Credentials[CredentialIndex], &Passwords->Credentials[Index], &Where, Offset ); CredentialIndex++; } } StoredCreds->CredentialCount = (USHORT) CredentialIndex;
//
// Copy in the old keys from the existing keys
//
for (Index = 0; Index < Passwords->OldCredentialCount; Index++ ) { KdcCopyKeyData( &StoredCreds->Credentials[CredentialIndex], &Passwords->Credentials[Index + Passwords->OldCredentialCount], &Where, Offset ); CredentialIndex++; }
StoredCreds->OldCredentialCount = Passwords->OldCredentialCount;
}
RtlInitUnicodeString( &Credentials.PackageName, MICROSOFT_KERBEROS_NAME_W );
Credentials.Credentials = (PBYTE) StoredCreds; Credentials.CredentialSize = StoredCredSize; Status = SamIStorePrimaryCredentials( UserHandle, &Credentials ); if (!NT_SUCCESS(Status)) { DebugLog((DEB_ERROR, "Failed to store primary credentials: 0x%x\n",Status)); goto Cleanup; }
Cleanup: FreeTicketInfo(&TicketInfo);
if (UserHandle != NULL) { SamrCloseHandle(&UserHandle); } if (StoredCreds != NULL) { MIDL_user_free(StoredCreds); } return(Status); }
|