📄 nlpcache.c
字号:
length = pEntry->DomainNameLength = NetbiosDomainName.Length;
if (length) {
RtlCopyMemory(dataptr, NetbiosDomainName.Buffer, length);
dataptr = ROUND_UP_POINTER(dataptr+length, sizeof(ULONG));
}
length = pEntry->DnsDomainNameLength = DnsDomainName.Length;
if (length) {
RtlCopyMemory(dataptr, DnsDomainName.Buffer, length);
dataptr = ROUND_UP_POINTER(dataptr+length, sizeof(ULONG));
}
length = pEntry->UpnLength = Upn.Length;
if (length) {
RtlCopyMemory(dataptr, Upn.Buffer, length);
dataptr = ROUND_UP_POINTER(dataptr+length, sizeof(ULONG));
}
length = pEntry->EffectiveNameLength = AccountInfo->EffectiveName.Length;
if (length) {
RtlCopyMemory(dataptr, AccountInfo->EffectiveName.Buffer, length);
dataptr = ROUND_UP_POINTER(dataptr+length, sizeof(ULONG));
}
length = pEntry->FullNameLength = AccountInfo->FullName.Length;
if (length) {
RtlCopyMemory(dataptr, AccountInfo->FullName.Buffer, length);
dataptr = ROUND_UP_POINTER(dataptr+length, sizeof(ULONG));
}
length = pEntry->LogonScriptLength = AccountInfo->LogonScript.Length;
if (length) {
RtlCopyMemory(dataptr, AccountInfo->LogonScript.Buffer, length);
dataptr = ROUND_UP_POINTER(dataptr+length, sizeof(ULONG));
}
length = pEntry->ProfilePathLength = AccountInfo->ProfilePath.Length;
if (length) {
RtlCopyMemory(dataptr, AccountInfo->ProfilePath.Buffer, length);
dataptr = ROUND_UP_POINTER(dataptr+length, sizeof(ULONG));
}
length = pEntry->HomeDirectoryLength = AccountInfo->HomeDirectory.Length;
if (length) {
RtlCopyMemory(dataptr, AccountInfo->HomeDirectory.Buffer, length);
dataptr = ROUND_UP_POINTER(dataptr+length, sizeof(ULONG));
}
length = pEntry->HomeDirectoryDriveLength = AccountInfo->HomeDirectoryDrive.Length;
if (length) {
RtlCopyMemory(dataptr, AccountInfo->HomeDirectoryDrive.Buffer, length);
dataptr = ROUND_UP_POINTER(dataptr+length, sizeof(ULONG));
}
pEntry->UserId = AccountInfo->UserId;
pEntry->PrimaryGroupId = AccountInfo->PrimaryGroupId;
length = pEntry->GroupCount = AccountInfo->GroupCount;
length *= sizeof(GROUP_MEMBERSHIP);
if (length) {
RtlCopyMemory(dataptr, AccountInfo->GroupIds, length);
dataptr = ROUND_UP_POINTER(dataptr+length, sizeof(ULONG));
}
length = pEntry->LogonDomainNameLength = AccountInfo->LogonDomainName.Length;
if (length) {
RtlCopyMemory(dataptr, AccountInfo->LogonDomainName.Buffer, length);
dataptr = ROUND_UP_POINTER(dataptr+length, sizeof(ULONG));
}
if (AccountInfo->UserFlags & LOGON_EXTRA_SIDS) {
length = pEntry->SidCount = AccountInfo->SidCount;
length *= sizeof(ULONG);
if (length) {
ULONG i, sidLength;
PULONG sidAttributes = (PULONG) dataptr;
dataptr = ROUND_UP_POINTER(dataptr+length, sizeof(ULONG));
//
// Now copy over all the SIDs
//
for (i = 0; i < AccountInfo->SidCount ; i++ ) {
sidAttributes[i] = AccountInfo->ExtraSids[i].Attributes;
sidLength = RtlLengthSid(AccountInfo->ExtraSids[i].Sid);
RtlCopySid(sidLength,(PSID) dataptr,AccountInfo->ExtraSids[i].Sid);
dataptr = ROUND_UP_POINTER(dataptr + sidLength, sizeof(ULONG));
}
pEntry->SidLength = (ULONG) (dataptr - (PCHAR) sidAttributes);
} else {
pEntry->SidLength = 0;
}
} else {
pEntry->SidCount = 0;
pEntry->SidLength = 0;
}
pEntry->LogonDomainIdLength = (USHORT) RtlLengthSid(AccountInfo->LogonDomainId);
NtStatus = RtlCopySid(pEntry->LogonDomainIdLength,
(PSID)dataptr,
AccountInfo->LogonDomainId
);
ASSERT(NT_SUCCESS(NtStatus));
dataptr = ROUND_UP_POINTER(dataptr+length, sizeof(ULONG));
//
// fill in randomkey for this cache entry.
//
SspGenerateRandomBits( pEntry->RandomKey, sizeof(pEntry->RandomKey) );
*ppCacheEntry = pEntry;
#if DBG
if (DumpCacheInfo) {
DbgPrint("BuildCacheEntry:\n");
DumpCacheEntry(999,pEntry);
}
#endif
return STATUS_SUCCESS;
}
NTSTATUS
NlpOpenCache( VOID )
/*++
Routine Description:
Opens the registry node for read or write (depending on Switch) and opens
the secret storage in the same mode. If successful, the NlpCacheHandle
is valid.
Arguments:
Return Value:
NTSTATUS
Success = STATUS_SUCCESS
NlpCacheHandle contains handle to use for reading/writing
registry
Failure =
--*/
{
NTSTATUS NtStatus;
ULONG Disposition;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ObjectName;
ObjectName.Length = ObjectName.MaximumLength = CACHE_NAME_SIZE;
ObjectName.Buffer = CACHE_NAME;
InitializeObjectAttributes(&ObjectAttributes,
&ObjectName,
OBJ_CASE_INSENSITIVE,
0, // RootDirectory
NULL // BUGBUG - put security descriptor here
);
NtStatus = NtCreateKey(&NlpCacheHandle,
(KEY_WRITE | KEY_READ),
&ObjectAttributes,
CACHE_TITLE_INDEX,
NULL, // class name
0, // create options
&Disposition
);
return NtStatus;
}
VOID
NlpCloseCache( VOID )
/*++
Routine Description:
Closes handles opened by NlpOpenCache
Arguments:
None.
Return Value:
None.
--*/
{
#if DBG
NTSTATUS NtStatus;
if (DumpCacheInfo) {
DbgPrint("CloseCache: Closing NlpCacheHandle (%#08x)\n", NlpCacheHandle);
}
if (IS_VALID_HANDLE(NlpCacheHandle)) {
NtStatus = NtClose(NlpCacheHandle);
if (DumpCacheInfo) {
DbgPrint("CloseCache: NtClose returns %#08x\n", NtStatus);
}
ASSERT(NT_SUCCESS(NtStatus));
INVALIDATE_HANDLE(NlpCacheHandle);
}
#else
if (IS_VALID_HANDLE(NlpCacheHandle)) {
NtClose(NlpCacheHandle);
INVALIDATE_HANDLE(NlpCacheHandle);
}
#endif
}
NTSTATUS
NlpOpenSecret(
IN ULONG Index
)
/*++
Routine Description:
Opens a cache entry's secret storage object for read (in order to LsaQuerySecret) and
write (in order to LsaSetSecret). If successful, the handle value
is placed in the global variable NlpSecretHandle.
If the secret does not exist, it will be created.
Arguments:
Index - The index of the entry being opened. This is used to build
a name of the object.
Return Value:
NTSTATUS
Success = STATUS_SUCCESS
NlpSecretHandle can be used to read/write secret storage
Failure =
--*/
{
NTSTATUS
NtStatus;
UNICODE_STRING
ValueName;
WCHAR
NameBuffer[32];
//
// Close previous handle if necessary
//
if (IS_VALID_HANDLE(NlpSecretHandle)) {
I_LsarClose( &NlpSecretHandle );
}
ValueName.Buffer = &NameBuffer[0];
ValueName.MaximumLength = 32;
ValueName.Length = 0;
NlpMakeCacheEntryName( Index, &ValueName );
NtStatus = I_LsarOpenSecret(NlpLsaHandle,
(PLSAPR_UNICODE_STRING) &ValueName,
SECRET_QUERY_VALUE | SECRET_SET_VALUE,
&NlpSecretHandle
);
if (!NT_SUCCESS(NtStatus)) {
if (NtStatus == STATUS_OBJECT_NAME_NOT_FOUND) {
NtStatus = I_LsarCreateSecret(NlpLsaHandle,
(PLSAPR_UNICODE_STRING) &ValueName,
SECRET_SET_VALUE | SECRET_QUERY_VALUE,
&NlpSecretHandle
);
if (!NT_SUCCESS(NtStatus)) {
INVALIDATE_HANDLE(NlpSecretHandle);
}
} else {
INVALIDATE_HANDLE(NlpSecretHandle);
}
}
return(NtStatus);
}
VOID
NlpCloseSecret( VOID )
/*++
Routine Description:
Closes the handles opened via NlpOpenSecret
Arguments:
None.
Return Value:
None.
--*/
{
NTSTATUS
NtStatus;
if (IS_VALID_HANDLE(NlpSecretHandle)) {
NtStatus = I_LsarClose(&NlpSecretHandle);
#if DBG
if (DumpCacheInfo) {
DbgPrint("CloseSecret: LsaClose returns %#08x\n", NtStatus);
}
#endif
ASSERT(NT_SUCCESS(NtStatus));
INVALIDATE_HANDLE(NlpSecretHandle);
}
}
NTSTATUS
NlpWriteSecret(
IN PLSAPR_CR_CIPHER_VALUE NewSecret,
IN PLSAPR_CR_CIPHER_VALUE OldSecret
)
/*++
Routine Description:
Writes the password (and optionally the previous password) to the LSA
secret storage
Arguments:
NewSecret - pointer to UNICODE_STRING containing current password
OldSecret - pointer to UNICODE_STRING containing previous password
Return Value:
NTSTATUS
Success =
Failure =
--*/
{
return I_LsarSetSecret(NlpSecretHandle, NewSecret, OldSecret);
}
NTSTATUS
NlpReadSecret(
OUT PLSAPR_CR_CIPHER_VALUE * NewSecret,
OUT PLSAPR_CR_CIPHER_VALUE * OldSecret
)
/*++
Routine Description:
Reads the new and old secrets (UNICODE_STRINGs) for the
currently open LSA secret
The Lsa routine returns us pointers to UNICODE strings
Arguments:
NewSecret - pointer to returned pointer to UNICODE_STRING containing
most recent password (if any)
OldSecret - pointer to returned pointer to UNICODE_STRING containing
previous password (if any)
Return Value:
NTSTATUS
Success
Failure
--*/
{
NTSTATUS
NtStatus;
LARGE_INTEGER
NewTime,
OldTime;
NtStatus = I_LsarQuerySecret(NlpSecretHandle,
NewSecret,
&NewTime,
OldSecret,
&OldTime
);
#if DBG
{
char newNt[80];
char newLm[80];
char oldNt[80];
char oldLm[80];
if (DumpCacheInfo) {
DbgPrint("NlpReadSecret: NewSecret.Nt = \"%s\"\n"
" NewSecret.Lm = \"%s\"\n"
" OldSecret.Nt = \"%s\"\n"
" OldSecret.Lm = \"%s\"\n",
*NewSecret
? DumpOwfPasswordToString(newNt, (PLM_OWF_PASSWORD)((*NewSecret)->Buffer))
: "",
*NewSecret
? DumpOwfPasswordToString(newLm, (PLM_OWF_PASSWORD)((*NewSecret)->Buffer)+1)
: "",
*OldSecret
? DumpOwfPasswordToString(oldNt, (PLM_OWF_PASSWORD)((*OldSecret)->Buffer))
: "",
*OldSecret
? DumpOwfPasswordToString(oldLm, (PLM_OWF_PASSWORD)((*OldSecret)->Buffer)+1)
: ""
);
}
}
#endif
return NtStatus;
}
NTSTATUS
NlpComputeSaltedHashedPassword(
OUT PNT_OWF_PASSWORD SaltedOwfPassword,
IN PNT_OWF_PASSWORD OwfPassword,
IN PUNICODE_STRING UserName
)
/*++
Routine Description:
Computes the salted hash of a password by concatenating the user name
with the OWF and computing the OWF of the combination.
Arguments:
SaltedOwfPassword - receives the LM or NT salted password/
OwfPassword - Contains the NT or LM owf password.
UserName - Contains the name of the user, used for salt.
Return Value:
NTSTATUS
Success = STATUS_SUCCESS
Passwords created OK
Failure = STATUS_NO_MEMORY
Not enough storage to create Passwords
--*/
{
NTSTATUS Status;
UNICODE_STRING TempString;
UNICODE_STRING LowerUserName;
//
// Compute the lower case user name.
//
Status = RtlDowncaseUnicodeString( &LowerUserName,
UserName,
TRUE );
if ( !NT_SUCCESS(Status)) {
return Status;
}
//
// Build a string that is a concatenation of the OWF and LowerCase username.
//
TempString.Length = TempString.MaximumLength = LowerUserName.Length + sizeof(NT_OWF_PASSWORD);
TempString.Buffer = AllocateFromHeap( TempString.Length );
if (TempString.Buffer == NULL) {
RtlFreeUnicodeString( &LowerUserName );
return(STATUS_INSUFFICIENT_RESOURCES);
}
Rt
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -