📄 nlp.c
字号:
//
// Kludge: Pass back UserParameters in HomeDirectoryDrive since we
// can't change the NETLOGON_VALIDATION_SAM_INFO structure between
// releases NT 1.0 and NT 1.0A. HomeDirectoryDrive was NULL for release 1.0A
// so we'll use that field.
//
NlpPutClientString( &ClientBufferDesc,
&LocalProfile->UserParameters,
&NlpUser->HomeDirectoryDrive );
}
//
// Flush the buffer to the client's address space.
//
Status = NlpFlushClientBuffer( &ClientBufferDesc,
ProfileBuffer );
Cleanup:
//
// If the copy wasn't successful,
// cleanup resources we would have returned to the caller.
//
if ( !NT_SUCCESS(Status) ) {
NlpFreeClientBuffer( &ClientBufferDesc );
}
// Save the status for subauth logons
if (NT_SUCCESS(Status) && !NT_SUCCESS(SubAuthStatus))
{
Status = SubAuthStatus;
}
return Status;
}
PSID
NlpMakeDomainRelativeSid(
IN PSID DomainId,
IN ULONG RelativeId
)
/*++
Routine Description:
Given a domain Id and a relative ID create the corresponding SID allocated
from the LSA heap.
Arguments:
DomainId - The template SID to use.
RelativeId - The relative Id to append to the DomainId.
Return Value:
Sid - Returns a pointer to a buffer allocated from the LsaHeap
containing the resultant Sid.
--*/
{
UCHAR DomainIdSubAuthorityCount;
ULONG Size;
PSID Sid;
//
// Allocate a Sid which has one more sub-authority than the domain ID.
//
DomainIdSubAuthorityCount = *(RtlSubAuthorityCountSid( DomainId ));
Size = RtlLengthRequiredSid(DomainIdSubAuthorityCount+1);
if ((Sid = (*Lsa.AllocateLsaHeap)( Size )) == NULL ) {
return NULL;
}
//
// Initialize the new SID to have the same inital value as the
// domain ID.
//
if ( !NT_SUCCESS( RtlCopySid( Size, Sid, DomainId ) ) ) {
(*Lsa.FreeLsaHeap)( Sid );
return NULL;
}
//
// Adjust the sub-authority count and
// add the relative Id unique to the newly allocated SID
//
(*(RtlSubAuthorityCountSid( Sid ))) ++;
*RtlSubAuthoritySid( Sid, DomainIdSubAuthorityCount ) = RelativeId;
return Sid;
}
PSID
NlpCopySid(
IN PSID * Sid
)
/*++
Routine Description:
Given a SID allocatees space for a new SID from the LSA heap and copies
the original SID.
Arguments:
Sid - The original SID.
Return Value:
Sid - Returns a pointer to a buffer allocated from the LsaHeap
containing the resultant Sid.
--*/
{
PSID NewSid;
ULONG Size;
Size = RtlLengthSid( Sid );
if ((NewSid = (*Lsa.AllocateLsaHeap)( Size )) == NULL ) {
return NULL;
}
if ( !NT_SUCCESS( RtlCopySid( Size, NewSid, Sid ) ) ) {
(*Lsa.FreeLsaHeap)( NewSid );
return NULL;
}
return NewSid;
}
//+-------------------------------------------------------------------------
//
// Function: NlpMakeTokenInformationV2
//
// Synopsis: This routine makes copies of all the pertinent
// information from the UserInfo and generates a
// LSA_TOKEN_INFORMATION_V2 data structure.
//
// Effects:
//
// Arguments:
//
// UserInfo - Contains the validation information which is
// to be copied into the TokenInformation.
//
// TokenInformation - Returns a pointer to a properly Version 1 token
// information structures. The structure and individual fields are
// allocated properly as described in ntlsa.h.
//
// Requires:
//
// Returns: STATUS_SUCCESS - Indicates the service completed successfully.
//
// STATUS_INSUFFICIENT_RESOURCES - This error indicates that
// the logon could not be completed because the client
// does not have sufficient quota to allocate the return
// buffer.
//
// Notes: stolen back from from kerberos\client2\krbtoken.cxx.c:KerbMakeTokenInformationV1
//
//
//--------------------------------------------------------------------------
NTSTATUS
NlpMakeTokenInformationV2(
IN PNETLOGON_VALIDATION_SAM_INFO2 ValidationInfo,
OUT PLSA_TOKEN_INFORMATION_V2 *TokenInformation
)
{
PNETLOGON_VALIDATION_SAM_INFO3 UserInfo = (PNETLOGON_VALIDATION_SAM_INFO3) ValidationInfo;
NTSTATUS Status;
PLSA_TOKEN_INFORMATION_V2 V2 = NULL;
ULONG Size, i;
SID LocalSystemSid = {SID_REVISION,1,SECURITY_NT_AUTHORITY,SECURITY_LOCAL_SYSTEM_RID};
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
DWORD NumGroups = 0;
PBYTE CurrentSid = NULL;
ULONG SidLength = 0;
//
// Allocate the structure itself
//
Size = (ULONG)sizeof(LSA_TOKEN_INFORMATION_V2);
//
// Allocate an array to hold the groups
//
Size += sizeof(TOKEN_GROUPS);
// Add room for groups passed as RIDS
NumGroups = UserInfo->GroupCount;
if(UserInfo->GroupCount)
{
Size += UserInfo->GroupCount * (RtlLengthSid(UserInfo->LogonDomainId) + sizeof(ULONG));
}
//
// If there are extra SIDs, add space for them
//
if (UserInfo->UserFlags & LOGON_EXTRA_SIDS) {
ULONG i = 0;
NumGroups += UserInfo->SidCount;
// Add room for the sid's themselves
for(i=0; i < UserInfo->SidCount; i++)
{
Size += RtlLengthSid(UserInfo->ExtraSids[i].Sid);
}
}
//
// If there are resource groups, add space for them
//
if (UserInfo->UserFlags & LOGON_RESOURCE_GROUPS) {
NumGroups += UserInfo->ResourceGroupCount;
if ((UserInfo->ResourceGroupCount != 0) &&
((UserInfo->ResourceGroupIds == NULL) ||
(UserInfo->ResourceGroupDomainSid == NULL)))
{
Status = STATUS_INVALID_PARAMETER;
goto Cleanup;
}
// Allocate space for the sids
if(UserInfo->ResourceGroupCount)
{
Size += UserInfo->ResourceGroupCount * (RtlLengthSid(UserInfo->ResourceGroupDomainSid) + sizeof(ULONG));
}
}
if( UserInfo->UserId )
{
// Size of the user sid and the primary group sid.
Size += 2*(RtlLengthSid(UserInfo->LogonDomainId) + sizeof(ULONG));
}
else
{
if ( UserInfo->SidCount <= 0 ) {
Status = STATUS_INSUFFICIENT_LOGON_INFO;
goto Cleanup;
}
// Size of the primary group sid.
Size += (RtlLengthSid(UserInfo->LogonDomainId) + sizeof(ULONG));
}
Size += (NumGroups - ANYSIZE_ARRAY)*sizeof(SID_AND_ATTRIBUTES);
V2 = (PLSA_TOKEN_INFORMATION_V2) (*Lsa.AllocateLsaHeap)( Size );
if ( V2 == NULL ) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(
V2,
Size
);
V2->Groups = (PTOKEN_GROUPS)(V2+1);
V2->Groups->GroupCount = 0;
CurrentSid = (PBYTE)&V2->Groups->Groups[NumGroups];
OLD_TO_NEW_LARGE_INTEGER( UserInfo->KickOffTime, V2->ExpirationTime );
//
// If the UserId is non-zero, then it contians the users RID.
//
if ( UserInfo->UserId ) {
V2->User.User.Sid = (PSID)CurrentSid;
CurrentSid += NlpCopyDomainRelativeSid((PSID)CurrentSid, UserInfo->LogonDomainId, UserInfo->UserId);
}
//
// Make a copy of the primary group (a required field).
//
V2->PrimaryGroup.PrimaryGroup = (PSID)CurrentSid;
CurrentSid += NlpCopyDomainRelativeSid((PSID)CurrentSid, UserInfo->LogonDomainId, UserInfo->PrimaryGroupId );
//
// Copy over all the groups passed as RIDs
//
for ( i=0; i < UserInfo->GroupCount; i++ ) {
V2->Groups->Groups[V2->Groups->GroupCount].Attributes = UserInfo->GroupIds[i].Attributes;
V2->Groups->Groups[V2->Groups->GroupCount].Sid = (PSID)CurrentSid;
CurrentSid += NlpCopyDomainRelativeSid((PSID)CurrentSid, UserInfo->LogonDomainId, UserInfo->GroupIds[i].RelativeId);
V2->Groups->GroupCount++;
}
//
// Add in the extra SIDs
//
if (UserInfo->UserFlags & LOGON_EXTRA_SIDS) {
ULONG index = 0;
//
// If the user SID wasn't passed as a RID, it is the first
// SID.
//
if ( !V2->User.User.Sid ) {
V2->User.User.Sid = (PSID)CurrentSid;
SidLength = RtlLengthSid(UserInfo->ExtraSids[index].Sid);
RtlCopySid(SidLength, (PSID)CurrentSid, UserInfo->ExtraSids[index].Sid);
CurrentSid += SidLength;
index++;
}
//
// Copy over all additional SIDs as groups.
//
for ( ; index < UserInfo->SidCount; index++ ) {
V2->Groups->Groups[V2->Groups->GroupCount].Attributes =
UserInfo->ExtraSids[index].Attributes;
V2->Groups->Groups[V2->Groups->GroupCount].Sid= (PSID)CurrentSid;
SidLength = RtlLengthSid(UserInfo->ExtraSids[index].Sid);
RtlCopySid(SidLength, (PSID)CurrentSid, UserInfo->ExtraSids[index].Sid);
CurrentSid += SidLength;
V2->Groups->GroupCount++;
}
}
//
// Check to see if any resouce groups exist
//
if (UserInfo->UserFlags & LOGON_RESOURCE_GROUPS) {
for ( i=0; i < UserInfo->ResourceGroupCount; i++ ) {
V2->Groups->Groups[V2->Groups->GroupCount].Attributes = UserInfo->ResourceGroupIds[i].Attributes;
V2->Groups->Groups[V2->Groups->GroupCount].Sid= (PSID)CurrentSid;
CurrentSid += NlpCopyDomainRelativeSid((PSID)CurrentSid, UserInfo->ResourceGroupDomainSid, UserInfo->ResourceGroupIds[i].RelativeId);
V2->Groups->GroupCount++;
}
}
ASSERT( ((PBYTE)V2 + Size) == CurrentSid );
if (!V2->User.User.Sid) {
Status = STATUS_INSUFFICIENT_LOGON_INFO;
goto Cleanup;
}
//
// There are no default privileges supplied.
// We don't have an explicit owner SID.
// There is no default DACL.
//
V2->Privileges = NULL;
V2->Owner.Owner = NULL;
V2->DefaultDacl.DefaultDacl = NULL;
//
// Return the Validation Information to the caller.
//
*TokenInformation = V2;
return STATUS_SUCCESS;
//
// Deallocate any memory we've allocated
//
Cleanup:
(*Lsa.FreeLsaHeap)( V2 );
return Status;
}
VOID
NlpPutOwfsInPrimaryCredential(
IN PUNICODE_STRING CleartextPassword,
OUT PMSV1_0_PRIMARY_CREDENTIAL Credential
)
/*++
Routine Description:
This routine puts the OWFs for the specified clear password into
the passed in Credential structure.
Arguments:
CleartextPassword - Is a string containing the user's cleartext password.
The password may be up to 255 characters long and contain any
UNICODE value.
Credential - A pointer to the credential to update.
Return Value:
STATUS_SUCCESS - Indicates the service completed successfully.
STATUS_QUOTA_EXCEEDED - This error indicates that the logon
could not be completed because the client does not have
sufficient quota to allocate the return buffer.
--*/
{
NTSTATUS Status;
CHAR LmPassword[LM20_PWLEN+1];
BOOLEAN LmPasswordPresent;
STRING AnsiCleartextPassword;
//
// Compute the Ansi version to the Cleartext password.
//
// The Ansi version of the Cleartext password is at most 14 bytes long,
// exists in a trailing zero filled 15 byte buffer,
// is uppercased.
//
AnsiCleartextPassword.Buffer = LmPassword;
AnsiCleartextPassword.MaximumLength = sizeof(LmPassword);
RtlZeroMemory( &LmPassword, sizeof(LmPassword) );
Status = RtlUpcaseUnicodeStringToOemString(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -