⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msvsam.c

📁 安全支持提供器接口(SSPI)源码
💻 C
📖 第 1 页 / 共 5 页
字号:
                if ( RtlCompareMemory(
                      LogonNetworkInfo->
                        NtChallengeResponse.Buffer,
                      &NtResponse,
                      LogonNetworkInfo->NtChallengeResponse.Length ) ==
                      NT_RESPONSE_LENGTH ) {

                    AlreadyValidated = TRUE;

                } else if ( RtlCompareMemory(
                      LogonNetworkInfo->
                        LmChallengeResponse.Buffer,
                      &NtResponse,
                      LogonNetworkInfo->LmChallengeResponse.Length ) ==
                      NT_RESPONSE_LENGTH ) {

                    AlreadyValidated = TRUE;
                }
            }
        }

        // if we're requiring all Win9x clients to have been upgraded, fail out now
        if (!AlreadyValidated && NtLmProtocolSupported >= RefuseLm)
            return FALSE;

        //
        //  if the LM response is the right size
        //  validate against the LM version of the response
        //  this applies also when both NTOWF and LMOWF are not present in SAM.
        //

        if (!AlreadyValidated &&
            ( LogonNetworkInfo->LmChallengeResponse.Length == LM_RESPONSE_LENGTH ) &&
            ( (Passwords->LmPasswordPresent) || (!Passwords->LmPasswordPresent && !Passwords->NtPasswordPresent) ) &&
            ( LogonNetworkInfo->NtChallengeResponse.Length < NT_RESPONSE_LENGTH )
            ) {

            LM_RESPONSE LmResponse;

            //
            // Compute what the response should be.
            //

            Status = RtlCalculateLmResponse(
                        &LogonNetworkInfo->LmChallenge,
                        &Passwords->LmOwfPassword,
                        &LmResponse );

            if ( NT_SUCCESS(Status) ) {

                //
                // If the responses match, the passwords are valid.
                //

                if ( RtlCompareMemory(
                      LogonNetworkInfo->
                        LmChallengeResponse.Buffer,
                      &LmResponse,
                      LM_RESPONSE_LENGTH ) ==
                      LM_RESPONSE_LENGTH ) {

                    AlreadyValidated = TRUE;
                    *UserFlags |= LOGON_USED_LM_PASSWORD;
                }
            }
        }

        //
        // If we haven't already validated this user,
        //  Validate a Cleartext password on a Network logon request.
        //

        if ( !AlreadyValidated ) {

            // If Cleartext passwords are not allowed,
            //  indicate the password doesn't match.
            //

            if((LogonInfo->ParameterControl & CLEARTEXT_PASSWORD_ALLOWED) == 0){
                return FALSE;
            }


            //
            // Compute the OWF password for the specified Cleartext password and
            // compare that to the OWF password retrieved from SAM.
            //

            //
            // If we're in UasCompatibilityMode,
            //  and we don't have the NT password in SAM or
            //      we don't have the NT password supplied by the caller.
            //  validate against the LM version of the password.
            //
            // if neither password are present, we validate against
            // the empty computed LMOWF.
            //

            if ( UasCompatibilityRequired &&
                 ((Passwords->LmPasswordPresent) || (!Passwords->LmPasswordPresent && !Passwords->NtPasswordPresent)) &&
                 (!Passwords->NtPasswordPresent ||
                 LogonNetworkInfo->NtChallengeResponse.Length == 0 ) ) {

                LM_OWF_PASSWORD LmOwfPassword;
                CHAR LmPassword[LM20_PWLEN+1];
                USHORT i;


                //
                // Compute the LmOwfPassword for the cleartext password passed in.
                //  (Enforce length restrictions on LanMan compatible passwords.)
                //

                if ( LogonNetworkInfo->LmChallengeResponse.Length >
                    sizeof(LmPassword) ) {
                    return FALSE;
                }

                RtlZeroMemory( &LmPassword, sizeof(LmPassword) );

                for (i = 0; i < LogonNetworkInfo->LmChallengeResponse.Length; i++) {
                    LmPassword[i] =
                      RtlUpperChar(LogonNetworkInfo->LmChallengeResponse.Buffer[i]);
                }

                (VOID) RtlCalculateLmOwfPassword( LmPassword, &LmOwfPassword );

                if ( RtlCompareMemory( &Passwords->LmOwfPassword,
                                       &LmOwfPassword,
                                       LM_OWF_PASSWORD_LENGTH ) !=
                                       LM_OWF_PASSWORD_LENGTH ) {

                    //
                    // Try the case preserved clear text password, too.
                    //  (I know of no client that does this,
                    //  but it is compatible with the LM 2.x server.)
                    //

                    RtlZeroMemory( &LmPassword, sizeof(LmPassword) );
                    RtlCopyMemory(
                        &LmPassword,
                        LogonNetworkInfo->LmChallengeResponse.Buffer,
                        LogonNetworkInfo->LmChallengeResponse.Length);

                    (VOID) RtlCalculateLmOwfPassword( LmPassword,
                                                      &LmOwfPassword );

                    if ( RtlCompareMemory( &Passwords->LmOwfPassword,
                                           &LmOwfPassword,
                                           LM_OWF_PASSWORD_LENGTH ) !=
                                           LM_OWF_PASSWORD_LENGTH ) {

                        return FALSE;
                    }

                }

                *UserFlags |= LOGON_USED_LM_PASSWORD;


            //
            // In all other circumstances, use the NT version of the password.
            //  This enforces case sensitivity.
            //

            } else {
                NT_OWF_PASSWORD NtOwfPassword;


                //
                // Compute the NtOwfPassword for the cleartext password passed in.
                //

                Status = RtlCalculateNtOwfPassword(
                             (PUNICODE_STRING)
                                &LogonNetworkInfo->NtChallengeResponse,
                             &NtOwfPassword );

                if ( RtlCompareMemory( &Passwords->NtOwfPassword,
                                       &NtOwfPassword,
                                       NT_OWF_PASSWORD_LENGTH ) !=
                                       NT_OWF_PASSWORD_LENGTH ) {

                    return FALSE;
                }
            }

            *UserFlags |= LOGON_NOENCRYPTION;
        }

        //
        // ASSERT: the network logon has been authenticated
        //
        //  Compute the session keys.

        //
        // If the client negotiated a non-NT protocol,
        //  use the lanman session key as the UserSessionKey.
        //

        if ( LogonNetworkInfo->NtChallengeResponse.Length == 0 ) {

            ASSERT( sizeof(*UserSessionKey) >= sizeof(*LmSessionKey) );

            RtlCopyMemory( UserSessionKey,
                           &Passwords->LmOwfPassword,
                           sizeof(*LmSessionKey) );

        } else {

            //
            // Return the NT UserSessionKey unless this is an account
            //  that doesn't have the NT version of the password.
            //  (A null password counts as a password).
            //

            if ( Passwords->NtPasswordPresent || !Passwords->LmPasswordPresent){

                Status = RtlCalculateUserSessionKeyNt(
                            (PNT_RESPONSE) NULL,    // Argument not used
                            &Passwords->NtOwfPassword,
                            UserSessionKey );

                ASSERT( NT_SUCCESS(Status) );
            }
        }

        //
        // Return the LM SessionKey unless this is an account
        //  that doesn't have the LM version of the password.
        //  (A null password counts as a password).
        //

        if ( Passwords->LmPasswordPresent || !Passwords->NtPasswordPresent ) {
            RtlCopyMemory( LmSessionKey,
                           &Passwords->LmOwfPassword,
                           sizeof(*LmSessionKey) );
        }

        break;

    //
    // Any other LogonLevel is an internal error.
    //
    default:
        return FALSE;

    }

    return TRUE;
}


BOOLEAN
MsvpEqualSidPrefix(
    IN PSID DomainSid,
    IN PSID GroupSid
    )
/*++

Routine Description:

    This routine checks to see if the specified group sid came from the
    specified domain by verifying that the domain portion of the group sid
    is equal to the domain sid.

Arguments:

    DomainSid - Sid of the domain for comparison.

    GroupSid - Sid of the group for comparison

Returns:

    TRUE - The group sid came from the specified domain.
    FALSE - The group sid did not come from the specified domain.

--*/
{
    PISID LocalGroupSid = (PISID) GroupSid;
    PISID LocalDomainSid = (PISID) DomainSid;
    if ((LocalGroupSid->SubAuthorityCount == LocalDomainSid->SubAuthorityCount + 1) &&
        RtlEqualMemory(
            RtlIdentifierAuthoritySid(LocalDomainSid),
            RtlIdentifierAuthoritySid(LocalGroupSid),
            RtlLengthRequiredSid(
                LocalDomainSid->SubAuthorityCount
                ) - FIELD_OFFSET(SID,IdentifierAuthority)
            )) {
        return(TRUE);
    }
    return(FALSE);
}

NTSTATUS
MsvpFilterGroupMembership(
    IN PSID_AND_ATTRIBUTES_LIST CompleteMembership,
    IN PSID LogonDomainId,
    OUT PSAMPR_GET_GROUPS_BUFFER LocalMembership,
    OUT PSID_AND_ATTRIBUTES_LIST GlobalMembership,
    OUT PULONG GlobalMembershipSize
    )
/*++

Routine Description:

    This routine separates the complete transitive group membership into
    portions from this domain and portions from others.

Arguments:

    CompleteMembership - The complete transitive membership.

    LogonDomainId - SID of the logon domain, used for compressing group
        membership.

    LocalMembership - Receives a list of rids corresponding to groups in this
        domain. The list should be freed with MIDL_user_free.

    GlobalMembership - Recevies a list of sids corresponding to groups in
        other domain. The list, but not the sids, should be free with
        MIDL_user_free.

    GlobalMembershipSize - Size, in bytes, of the sids in the global membership
        and the size of the SID_AND_ATTRIBUTES structures.

Returns:

    STATUS_SUCCESS on success
    STATUS_INSUFFICIENT_RESOURCES on for memory allocation failures.

--*/
{
    NTSTATUS Status = STATUS_SUCCESS;
    ULONG LocalCount = 0;
    ULONG GlobalCount = 0;
    ULONG GlobalSize = 0;
    ULONG Index;

    LocalMembership->MembershipCount = 0;
    LocalMembership->Groups = NULL;
    GlobalMembership->Count = 0;
    GlobalMembership->SidAndAttributes = NULL;


    //
    // Define a flag so we don't have to do the comparison twice.
    //

#define MSVP_LOCAL_GROUP_ATTR 0x20000000

    for (Index = 0; Index < CompleteMembership->Count ; Index++ ) {
        ASSERT((CompleteMembership->SidAndAttributes[Index].Attributes & MSVP_LOCAL_GROUP_ATTR) == 0);

        if (MsvpEqualSidPrefix(
            LogonDomainId,
            CompleteMembership->SidAndAttributes[Index].Sid
            )) {

            CompleteMembership->SidAndAttributes[Index].Attributes |= MSVP_LOCAL_GROUP_ATTR;
            LocalCount++;
        } else {

            GlobalCount++;
            GlobalSize += sizeof(SID_AND_ATTRIBUTES) + RtlLengthSid(CompleteMembership->SidAndAttributes[Index].Sid);
        }
    }

    //
    // Allocate the arrays for the output
    //

    if (LocalCount != 0)
    {
        LocalMembership->Groups = (PGROUP_MEMBERSHIP) MIDL_user_allocate(LocalCount * sizeof(GROUP_MEMBERSHIP));
        if (LocalMembership->Groups == NULL) {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            goto Cleanup;
        }
        LocalMembership->MembershipCount = LocalCount;
    }
    if (GlobalCount != 0)
    {
        GlobalMembership->SidAndAttributes = (PSID_AND_ATTRIBUTES) MIDL_user_allocate(GlobalCount * sizeof(SID_AND_ATTRIBUTES));
        if (GlobalMembership->SidAndAttributes == NULL) {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            goto Cleanup;
        }
        GlobalMembership->Count = GlobalCount;
    }

    //
    // Loop through again copy the rid or sid into the respective array
    //

    LocalCount = 0;
    GlobalCount = 0;
    for (Index = 0; Index < CompleteMembership->Count ; Index++ ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -