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

📄 msvpaswd.c

📁 安全支持提供器接口(SSPI)源码
💻 C
📖 第 1 页 / 共 5 页
字号:
        }

        if (DCNameString.Buffer == NULL) {

            // BUGBUG: Should really pass both names to internal version of DsGetDcName
            if ( ClientDnsDomain.Length != 0 ) {
                ClientDsGetDcDomain = &ClientDnsDomain;
            } else {
                ClientDsGetDcDomain = &ClientNetbiosDomain;
            }

            //
            // Build a zero terminated domain name.
            //

            DomainName = RtlAllocateHeap(
                            MspHeap,
                            0,
                            ClientDsGetDcDomain->Length + sizeof(WCHAR));

            if ( DomainName == NULL ) {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                goto Cleanup;
            }

            RtlCopyMemory( DomainName,
                           ClientDsGetDcDomain->Buffer,
                           ClientDsGetDcDomain->Length );
            DomainName[ClientDsGetDcDomain->Length / sizeof(WCHAR)] = 0;

            NetStatus = DsGetDcNameW(
                                NULL,
                                DomainName,
                                NULL,           // no domain guid
                                NULL,           // no site name
                                DS_WRITABLE_REQUIRED,
                                &DCInfo );

            if ( NetStatus != NERR_Success ) {
                SspPrint(( SSP_CRITICAL, "MspLm20ChangePassword: DsGetDcNameW returned 0x%lx.\n",
                    NetStatus));

                Status = NetpApiStatusToNtStatus( NetStatus );
                if( Status == STATUS_INTERNAL_ERROR )
                    Status = STATUS_NO_SUCH_DOMAIN;
            } else {
                RtlInitUnicodeString( &DCNameString, DCInfo->DomainControllerName );
            }

            AttemptRediscovery = TRUE;
        }

        if (NT_SUCCESS(Status)) {

            Status = MspChangePassword(
                         &DCNameString,
                         &ClientName,
                         &ChangePasswordRequest->OldPassword,
                         &ChangePasswordRequest->NewPassword,
                         ClientRequest,
                         ChangePasswordRequest->Impersonating,
                         &DomainPasswordInfo,
                         NULL,
                         &Authoritative );

            //
            // If we succeeded or got back an authoritative answer
            if ( NT_SUCCESS(Status) || Authoritative) {
                goto PasswordChangeSuccessfull;
            }

        }

    }

    //
    // Free the DC info so we can call DsGetDcName again.
    //

    if ( DCInfo != NULL ) {
        NetApiBufferFree(DCInfo);
        DCInfo = NULL;
    }


    //
    // attempt re-discovery.
    //

    if( AttemptRediscovery ) {

        NetStatus = DsGetDcNameW(
                            NULL,
                            DomainName,
                            NULL,           // no domain guid
                            NULL,           // no site name
                            DS_FORCE_REDISCOVERY | DS_WRITABLE_REQUIRED,
                            &DCInfo );

        if ( NetStatus != NERR_Success ) {

            SspPrint(( SSP_CRITICAL, "MspLm20ChangePassword: DsGetDcNameW (re-discover) returned 0x%lx.\n",
                NetStatus));

            DCInfo = NULL;
            Status = NetpApiStatusToNtStatus( NetStatus );
            if( Status == STATUS_INTERNAL_ERROR )
                Status = STATUS_NO_SUCH_DOMAIN;
        } else {
            RtlInitUnicodeString( &DCNameString, DCInfo->DomainControllerName );

            Status = MspChangePassword(
                         &DCNameString,
                         &ClientName,
                         &ChangePasswordRequest->OldPassword,
                         &ChangePasswordRequest->NewPassword,
                         ClientRequest,
                         ChangePasswordRequest->Impersonating,
                         &DomainPasswordInfo,
                         NULL,
                         &Authoritative );

            //
            // If we succeeded or got back an authoritative answer
            if ( NT_SUCCESS(Status) || Authoritative) {
                goto PasswordChangeSuccessfull;
            }

            //
            // Free the DC info so we can call DsGetDcName again.
            //

            if ( DCInfo != NULL ) {
                NetApiBufferFree(DCInfo);
                DCInfo = NULL;
            }
        }
    }


    if (Status != STATUS_BACKUP_CONTROLLER) {
        //
        // Change the password assuming the DomainName is really a server name
        //
        // The domain name is overloaded to be either a domain name or a server
        // name.  The server name is useful when changing the password on a LM2.x
        // standalone server, which is a "member" of a domain but uses a private
        // account database.
        //

        Status = MspChangePassword(
                     &ClientNetbiosDomain,
                     &ClientName,
                     &ChangePasswordRequest->OldPassword,
                     &ChangePasswordRequest->NewPassword,
                     ClientRequest,
                     ChangePasswordRequest->Impersonating,
                     &DomainPasswordInfo,
                     &PrimaryDomainInfo,
                     &Authoritative );



        //
        // If DomainName is actually a server name,
        //  just return the status to the caller.
        //

        if ( Authoritative &&
             ( Status != STATUS_BAD_NETWORK_PATH ||
               ( ClientNetbiosDomain.Length >= 3 * sizeof(WCHAR) &&
                 ClientNetbiosDomain.Buffer[0] == L'\\' &&
                 ClientNetbiosDomain.Buffer[1] == L'\\' ) ) ) {

            //
            // If \\xxx was specified, but xxx doesn't exist,
            //  return the status code that the DomainName field is bad.
            //

            if ( Status == STATUS_BAD_NETWORK_PATH ) {
                Status = STATUS_NO_SUCH_DOMAIN;
            }
        }


        //
        // If we didn't get an error that this was a backup controller,
        // we are out of here.
        //

        if (Status != STATUS_BACKUP_CONTROLLER) {
            goto PasswordChangeSuccessfull;
        }


    }

    //
    // If the specified machine was a BDC in a domain,
    //    Pretend the caller passed us the domain name in the first place.
    //

    if ( Status == STATUS_BACKUP_CONTROLLER && PrimaryDomainInfo != NULL ) {

        ClientNetbiosDomain = PrimaryDomainInfo->Name;
        Status = STATUS_BAD_NETWORK_PATH;
    } else {
        goto PasswordChangeSuccessfull;
    }




    //
    // Build a zero terminated domain name.
    //

    // BUGBUG: Should really pass both names to internal version of DsGetDcName
    if ( ClientDnsDomain.Length != 0 ) {
        ClientDsGetDcDomain = &ClientDnsDomain;
    } else {
        ClientDsGetDcDomain = &ClientNetbiosDomain;
    }

    if( DomainName )
        RtlFreeHeap( MspHeap, 0, DomainName );

    DomainName = RtlAllocateHeap(
                    MspHeap,
                    0,
                    ClientDsGetDcDomain->Length + sizeof(WCHAR));

    if ( DomainName == NULL ) {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto Cleanup;
    }

    RtlCopyMemory( DomainName,
                   ClientDsGetDcDomain->Buffer,
                   ClientDsGetDcDomain->Length );
    DomainName[ClientDsGetDcDomain->Length / sizeof(WCHAR)] = 0;

    AttemptRediscovery = FALSE;

retry:
    {
        DWORD dwGetDcFlags = 0;

        if( AttemptRediscovery )
            dwGetDcFlags |= DS_FORCE_REDISCOVERY;

        //
        // Determine the PDC of the named domain so we can change the password there.
        //

        NetStatus = DsGetDcNameW(
                            NULL,
                            DomainName,
                            NULL,           // no domain guid
                            NULL,           // no site name
                            dwGetDcFlags | DS_WRITABLE_REQUIRED,
                            &DCInfo );

        if ( NetStatus != NERR_Success ) {

            SspPrint(( SSP_CRITICAL, "MspLm20ChangePassword: DsGetDcNameW returned 0x%lx.\n",
                NetStatus));

            Status = NetpApiStatusToNtStatus( NetStatus );
            if( Status == STATUS_INTERNAL_ERROR )
                Status = STATUS_NO_SUCH_DOMAIN;
            goto Cleanup;
        }

        RtlInitUnicodeString( &DCNameString, DCInfo->DomainControllerName );

        Status = MspChangePassword(
                     &DCNameString,
                     &ClientName,
                     &ChangePasswordRequest->OldPassword,
                     &ChangePasswordRequest->NewPassword,
                     ClientRequest,
                     ChangePasswordRequest->Impersonating,
                     &DomainPasswordInfo,
                     NULL,
                     &Authoritative );

        if( !NT_SUCCESS(Status) && !Authoritative && !AttemptRediscovery ) {
            AttemptRediscovery = TRUE;
            goto retry;
        }
    }


PasswordChangeSuccessfull:

    //
    // Allocate and initialize the response buffer.
    //

    SavedStatus = Status;

    *ReturnBufferSize = sizeof(MSV1_0_CHANGEPASSWORD_RESPONSE);

    Status = NlpAllocateClientBuffer( &ClientBufferDesc,
                                      sizeof(MSV1_0_CHANGEPASSWORD_RESPONSE),
                                      *ReturnBufferSize );


    if ( !NT_SUCCESS( Status ) ) {
        KdPrint(("MSV1_0: MspLm20ChangePassword: cannot alloc client buffer\n"));
        *ReturnBufferSize = 0;
        goto Cleanup;
    }

    ChangePasswordResponse = (PMSV1_0_CHANGEPASSWORD_RESPONSE) ClientBufferDesc.MsvBuffer;

    ChangePasswordResponse->MessageType = MsV1_0ChangePassword;


    //
    // Copy the DomainPassword restrictions out to the caller depending on
    //  whether it was passed to us.
    //
    // Mark the buffer as valid or invalid to let the caller know.
    //
    // if STATUS_PASSWORD_RESTRICTION is returned.  This status can be
    // returned by either SAM or a down-level change.  Only SAM will return
    // valid data so we have a flag in the buffer that says whether the data
    // is valid or not.
    //

    if ( DomainPasswordInfo == NULL ) {
        ChangePasswordResponse->PasswordInfoValid = FALSE;
    } else {
        ChangePasswordResponse->DomainPasswordInfo = *DomainPasswordInfo;
        ChangePasswordResponse->PasswordInfoValid = TRUE;
    }


    //
    // Flush the buffer to the client's address space.
    //

    Status = NlpFlushClientBuffer( &ClientBufferDesc,
                                   ProtocolReturnBuffer );



    //
    // Update cached credentials with the new password.
    //
    // This is done by calling NlpChangePassword,
    // which takes encrypted passwords, so encrypt 'em.
    //

    if ( NT_SUCCESS(SavedStatus) ) {

        //
        // Failure of NlpChangePassword is OK, that means that the
        // account we've been working with isn't the one we're
        // caching credentials for.
        //

        (VOID) NlpChangePassword(
                     &ClientNetbiosDomain,
                     &ClientName,
                     &ChangePasswordRequest->NewPassword
                     );

    }


    Status = SavedStatus;


Cleanup:


    //
    // Free Locally allocated resources
    //

    if (DomainName != NULL) {
        RtlFreeHeap(MspHeap, 0, DomainName);
    }

    if ( DCInfo != NULL ) {
        NetApiBufferFree(DCInfo);
    }

    if ( WkstaInfo100 != NULL ) {
        NetApiBufferFree(WkstaInfo100);
    }

    if ( DomainPasswordInfo != NULL ) {
        SamFreeMemory(DomainPasswordInfo);
    }

    if ( PrimaryDomainInfo != NULL ) {
        (VOID) LsaFreeMemory( PrimaryDomainInfo );
    }


    if ( DsHandle != NULL) {
        DsUnBindW(
            &DsHandle
            );
    }

    //
    // Free Policy Server Role Information if used.
    //

    if (PolicyLsaServerRoleInfo != NULL) {

        I_LsaIFree_LSAPR_POLICY_INFORMATION(
            PolicyLsaServerRoleInformation,
            (PLSAPR_POLICY_INFORMATION) PolicyLsaServerRoleInfo
            );
    }

    //
    // Free the return buffer.
    //

    NlpFreeClientBuffer( &ClientBufferDesc );

    //
    // Don't let the password stay in the page file.
    //

    if ( PasswordBufferValidated ) {
        RtlEraseUnicodeString( &ChangePasswordRequest->OldPassword );
        RtlEraseUnicodeString( &ChangePasswordRequest->NewPassword );
    }

    //
    // Flush the log to disk
    //

    MsvPaswdSetAndClearLog();

    //
    // Return status to the caller.
    //


    *ProtocolStatus = Status;
    return STATUS_SUCCESS;
}

⌨️ 快捷键说明

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