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

📄 msvpaswd.c

📁 安全支持提供器接口(SSPI)源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    if ( MsvPaswdLogFile != NULL ) {

        CloseHandle( MsvPaswdLogFile );
        MsvPaswdLogFile = NULL;
    }

    return( dwErr );
}



//
// Stolen and hacked up from netlogon code
//

VOID
MsvPaswdDebugDumpRoutine(
    IN LPSTR Format,
    va_list arglist
    )

{
    char OutputBuffer[2049];
    ULONG length;
    ULONG BytesWritten;
    SYSTEMTIME SystemTime;
    static BeginningOfLine = TRUE;

    //
    // If we don't have an open log file, just bail
    //
    if ( MsvPaswdLogFile == NULL ) {

        return;
    }

    length = 0;

    //
    // Handle the beginning of a new line.
    //
    //

    if ( BeginningOfLine ) {

        //
        // If we're writing to the debug terminal,
        //  indicate this is a Netlogon message.
        //

        //
        // Put the timestamp at the begining of the line.
        //

        GetLocalTime( &SystemTime );
        length += (ULONG) sprintf( &OutputBuffer[length],
                                   "%02u/%02u %02u:%02u:%02u ",
                                   SystemTime.wMonth,
                                   SystemTime.wDay,
                                   SystemTime.wHour,
                                   SystemTime.wMinute,
                                   SystemTime.wSecond );
    }

    //
    // Put a the information requested by the caller onto the line
    //
    length += (ULONG) vsprintf(&OutputBuffer[length], Format, arglist);
    BeginningOfLine = (length > 0 && OutputBuffer[length-1] == '\n' );
    if ( BeginningOfLine ) {

        OutputBuffer[length-1] = '\r';
        OutputBuffer[length] = '\n';
        OutputBuffer[length+1] = '\0';
        length++;
    }

    ASSERT( length <= sizeof( OutputBuffer ) / sizeof( CHAR ) );


    //
    // Write the debug info to the log file.
    //
    if ( !WriteFile( MsvPaswdLogFile,
                     OutputBuffer,
                     length,
                     &BytesWritten,
                     NULL ) ) {

    }


}

VOID
MsvPaswdLogPrintRoutine(
    IN LPSTR Format,
    ...
    )

{
    va_list arglist;

    va_start(arglist, Format);

    MsvPaswdDebugDumpRoutine( Format, arglist );

    va_end(arglist);

}




ULONG
MsvPaswdSetAndClearLog(
    VOID
    )
/*++

Routine Description:

    Flushes the log and seeks to the end of the file

Arguments:

    None

Returns:

    ERROR_SUCCESS - Success

--*/
{
    ULONG dwErr = ERROR_SUCCESS;
    if ( MsvPaswdLogFile != NULL ) {

        if( FlushFileBuffers( MsvPaswdLogFile ) == FALSE ) {

            dwErr = GetLastError();
        }
    }

    return( dwErr );

}

#endif // DONT_LOG_PASSWORD_CHANGES


NTSTATUS
MspChangePasswordSam(
    IN PUNICODE_STRING UncComputerName,
    IN PUNICODE_STRING UserName,
    IN PUNICODE_STRING OldPassword,
    IN PUNICODE_STRING NewPassword,
    IN PLSA_CLIENT_REQUEST ClientRequest,
    IN BOOLEAN Impersonating,
    OUT PDOMAIN_PASSWORD_INFORMATION *DomainPasswordInfo,
    OUT PPOLICY_PRIMARY_DOMAIN_INFO *PrimaryDomainInfo OPTIONAL,
    OUT PBOOLEAN Authoritative
    )

/*++

Routine Description:

    This routine is called by MspChangePassword to change the password
    on a Windows NT machine.

Arguments:

    UncComputerName - Name of the target machine.  This name must begin with
        two backslashes.

    UserName - Name of the user to change password for.

    OldPassword - Plaintext current password.

    NewPassword - Plaintext replacement password.

    ClientRequest - Is a pointer to an opaque data structure
        representing the client's request.

    DomainPasswordInfo - Password restriction information (returned only if
        status is STATUS_PASSWORD_RESTRICTION).

    PrimaryDomainInfo - DomainNameInformation (returned only if status is
        STATUS_BACKUP_CONTROLLER).

    Authoritative - The failure was authoritative and no retries should be
        made.

Return Value:

    STATUS_SUCCESS - Indicates the service completed successfully.

    ...

--*/

{
    NTSTATUS                    Status;
    OBJECT_ATTRIBUTES           ObjectAttributes;
    SECURITY_QUALITY_OF_SERVICE SecurityQos;
    SAM_HANDLE                  SamHandle = NULL;
    SAM_HANDLE                  DomainHandle = NULL;
    LSA_HANDLE                  LSAPolicyHandle = NULL;
    OBJECT_ATTRIBUTES           LSAObjectAttributes;
    PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo = NULL;

    //
    // Assume all failures are authoritative
    //

    *Authoritative = TRUE;

    //
    // If we're impersonating (ie, winlogon impersonated its caller before calling us),
    // impersonate again.  This allows us to get the name of the caller for auditing.
    //

    if ( Impersonating ) {

        Status = (*Lsap.ImpersonateClient)(ClientRequest);

    } else {

        //
        // Since the System context is a member of the Administrators alias,
        // when we connect with the local SAM we come in as an Administrator.
        // (When it's remote, we go over the null session and so have very
        // low access).  We don't want to be an Administrator because that
        // would allow the user to change the password on an account whose
        // ACL prohibits the user from changing the password.  So we'll
        // temporarily impersonate ourself and disable the Administrators
        // alias in the impersonation token.
        //

        Status = MspDisableAdminsAlias();
    }





    if (!NT_SUCCESS( Status )) {
        goto Cleanup;
    }

    try
    {

        Status = SamChangePasswordUser2(
                    UncComputerName,
                    UserName,
                    OldPassword,
                    NewPassword
                    );
    }
    except (EXCEPTION_EXECUTE_HANDLER)
    {
        Status = GetExceptionCode();
    }

    MsvPaswdLogPrint(("SamChangePasswordUser2 on machine %wZ for user %wZ returned 0x%x\n",
        UncComputerName,
        UserName,
        Status
        ));

    if ( !NT_SUCCESS(Status) ) {

#ifdef COMPILED_BY_DEVELOPER
        KdPrint(("MspChangePasswordSam: SamChangePasswordUser2(%wZ) failed, status %x\n",
                 UncComputerName, Status));
#endif // COMPILED_BY_DEVELOPER

        //
        // If we failed to connect and we were impersonating a client
        // then we may want to try again using the NULL session.
        // Only try this if we found a server last try.  Otherwise,
        // we'll subject our user to another long timeout.
        //

        if (( Impersonating ) &&
            ( Status != STATUS_WRONG_PASSWORD ) &&
            ( Status != STATUS_PASSWORD_RESTRICTION ) &&
            ( Status != STATUS_ACCOUNT_RESTRICTION ) &&
            ( Status != RPC_NT_SERVER_UNAVAILABLE) &&
            ( Status != STATUS_INVALID_DOMAIN_ROLE) ) {

            Status = MspDisableAdminsAlias();

            if (!NT_SUCCESS(Status)) {
                goto Cleanup;
            }

            Status = SamChangePasswordUser2(
                        UncComputerName,
                        UserName,
                        OldPassword,
                        NewPassword
                        );

            MsvPaswdLogPrint(("SamChangePasswordUser2 retry on machine %wZ for user %wZ returned 0x%x\n",
                UncComputerName,
                UserName,
                Status
                ));

#ifdef COMPILED_BY_DEVELOPER
            if ( !NT_SUCCESS(Status) ) {
                KdPrint(("MspChangePasswordSam: SamChangePasswordUser2(%wZ) (2nd attempt) failed, status %x\n",
                 UncComputerName, Status));
                }
#endif // COMPILED_BY_DEVELOPER
        }

    }



    if ( !NT_SUCCESS(Status) ) {

#ifdef COMPILED_BY_DEVELOPER
        KdPrint(("MspChangePasswordSam: Cannot change password for %wZ, status %x\n",
                 UserName, Status));
#endif // COMPILED_BY_DEVELOPER
        if (Status == RPC_NT_SERVER_UNAVAILABLE ||
            Status == RPC_S_SERVER_UNAVAILABLE ) {

            Status = STATUS_CANT_ACCESS_DOMAIN_INFO;
        } else if (Status == STATUS_PASSWORD_RESTRICTION) {

            //
            // Get the password restrictions for this domain and return them
            //



            //
            // Get the SID of the account domain from LSA
            //

            InitializeObjectAttributes( &LSAObjectAttributes,
                                          NULL,             // Name
                                          0,                // Attributes
                                          NULL,             // Root
                                          NULL );           // Security Descriptor

            Status = LsaOpenPolicy( UncComputerName,
                                    &LSAObjectAttributes,
                                    POLICY_VIEW_LOCAL_INFORMATION,
                                    &LSAPolicyHandle );

            if( !NT_SUCCESS(Status) ) {
                KdPrint(("MspChangePasswordSam: LsaOpenPolicy(%wZ) failed, status %x\n",
                         UncComputerName, Status));
                LSAPolicyHandle = NULL;
                goto Cleanup;
            }

            Status = LsaQueryInformationPolicy(
                            LSAPolicyHandle,
                            PolicyAccountDomainInformation,
                            (PVOID *) &AccountDomainInfo );

            if( !NT_SUCCESS(Status) ) {
                KdPrint(("MspChangePasswordSam: LsaQueryInformationPolicy(%wZ) failed, status %x\n",
                         UncComputerName, Status));
                AccountDomainInfo = NULL;
                goto Cleanup;
            }


            //
            // Setup ObjectAttributes for SamConnect call.
            //

            InitializeObjectAttributes(&ObjectAttributes, NULL, 0, 0, NULL);
            ObjectAttributes.SecurityQualityOfService = &SecurityQos;

            SecurityQos.Length = sizeof(SecurityQos);
            SecurityQos.ImpersonationLevel = SecurityIdentification;
            SecurityQos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
            SecurityQos.EffectiveOnly = FALSE;

            Status = SamConnect(
                         UncComputerName,
                         &SamHandle,
                         SAM_SERVER_LOOKUP_DOMAIN,
                         &ObjectAttributes
                         );


            if ( !NT_SUCCESS(Status) ) {
                KdPrint(("MspChangePasswordSam: Cannot open sam on %wZ, status %x\n",
                         UncComputerName, Status));
                DomainHandle = NULL;
                goto Cleanup;
            }


            //
            // Open the Account domain in SAM.
            //

            Status = SamOpenDomain(
                         SamHandle,
                         GENERIC_EXECUTE,
                         AccountDomainInfo->DomainSid,
                         &DomainHandle
                         );

            if ( !NT_SUCCESS(Status) ) {
                KdPrint(("MspChangePasswordSam: Cannot open domain on %wZ, status %x\n",
                         UncComputerName, Status));
                DomainHandle = NULL;
                goto Cleanup;
            }


            Status = SamQueryInformationDomain(
                            DomainHandle,
                            DomainPasswordInformation,
                            (PVOID *)DomainPasswordInfo );

            if (!NT_SUCCESS(Status)) {
                *DomainPasswordInfo = NULL;
            } else {
                Status = STATUS_PASSWORD_RESTRICTION;
            }
        }

        goto Cleanup;
    }


Cleanup:

    //
    // If the only problem is that this is a BDC,
    //  Return the domain name back to the caller.
    //

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

        NTSTATUS TempStatus;

        //

⌨️ 快捷键说明

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