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

📄 nlmain.c

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


    //
    // Open a handle to the Netlogon Service.
    //

    ScManagerHandle = OpenSCManager(
                          NULL,
                          NULL,
                          SC_MANAGER_CONNECT );

    if (ScManagerHandle == NULL) {
        KdPrint(( "[MSV1_0] NlWaitForNetlogon: OpenSCManager failed: "
                      "%lu\n", GetLastError()));
        Status = STATUS_NETLOGON_NOT_STARTED;
        goto Cleanup;
    }

    ServiceHandle = OpenService(
                        ScManagerHandle,
                        SERVICE_NETLOGON,
                        SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG );

    if ( ServiceHandle == NULL ) {
        KdPrint(( "[MSV1_0] NlWaitForNetlogon: OpenService failed: "
                      "%lu\n", GetLastError()));
        Status = STATUS_NETLOGON_NOT_STARTED;
        goto Cleanup;
    }


    //
    // If the Netlogon service isn't configured to be automatically started
    //  by the service controller, don't bother waiting for it to start.
    //
    // ?? Pass "DummyServiceConfig" and "sizeof(..)" since QueryService config
    //  won't allow a null pointer, yet.

    if ( QueryServiceConfig(
            ServiceHandle,
            &DummyServiceConfig,
            sizeof(DummyServiceConfig),
            &ServiceConfigSize )) {

        ServiceConfig = &DummyServiceConfig;

    } else {

        NetStatus = GetLastError();
        if ( NetStatus != ERROR_INSUFFICIENT_BUFFER ) {
            KdPrint(( "[MSV1_0] NlWaitForNetlogon: QueryServiceConfig failed: "
                      "%lu\n", NetStatus));
            Status = STATUS_NETLOGON_NOT_STARTED;
            goto Cleanup;
        }

        AllocServiceConfig = RtlAllocateHeap( MspHeap, 0, ServiceConfigSize );
        ServiceConfig = AllocServiceConfig;

        if ( AllocServiceConfig == NULL ) {
            Status = STATUS_NO_MEMORY;
            goto Cleanup;
        }

        if ( !QueryServiceConfig(
                ServiceHandle,
                ServiceConfig,
                ServiceConfigSize,
                &ServiceConfigSize )) {

            KdPrint(( "[MSV1_0] NlWaitForNetlogon: QueryServiceConfig "
                      "failed again: %lu\n", GetLastError()));
            Status = STATUS_NETLOGON_NOT_STARTED;
            goto Cleanup;
        }
    }

    if ( ServiceConfig->dwStartType != SERVICE_AUTO_START ) {
        KdPrint(( "[MSV1_0] NlWaitForNetlogon: Netlogon start type invalid:"
                          "%lu\n", ServiceConfig->dwStartType ));
        Status = STATUS_NETLOGON_NOT_STARTED;
        goto Cleanup;
    }



    //
    // Loop waiting for the netlogon service to start.
    //  (Convert Timeout to a number of 10 second iterations)
    //

    Timeout = (Timeout+9)/10;
    for (;;) {


        //
        // Query the status of the Netlogon service.
        //

        if (! QueryServiceStatus( ServiceHandle, &ServiceStatus )) {

            KdPrint(( "[MSV1_0] NlWaitForNetlogon: QueryServiceStatus failed: "
                          "%lu\n", GetLastError() ));
            Status = STATUS_NETLOGON_NOT_STARTED;
            goto Cleanup;
        }

        //
        // Return or continue waiting depending on the state of
        //  the netlogon service.
        //

        switch( ServiceStatus.dwCurrentState) {
        case SERVICE_RUNNING:
            Status = STATUS_SUCCESS;
            goto Cleanup;

        case SERVICE_STOPPED:

            //
            // If Netlogon failed to start,
            //  error out now.  The caller has waited long enough to start.
            //
            if ( ServiceStatus.dwWin32ExitCode != ERROR_SERVICE_NEVER_STARTED ){
#if DBG
                KdPrint(( "[MSV1_0] NlWaitForNetlogon: "
                          "Netlogon service couldn't start: %lu %lx\n",
                          ServiceStatus.dwWin32ExitCode,
                          ServiceStatus.dwWin32ExitCode ));
                if ( ServiceStatus.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR ) {
                    KdPrint(( "         Service specific error code: %lu %lx\n",
                              ServiceStatus.dwServiceSpecificExitCode,
                              ServiceStatus.dwServiceSpecificExitCode ));
                }
#endif // DBG
                Status = STATUS_NETLOGON_NOT_STARTED;
                goto Cleanup;
            }

            //
            // If Netlogon has never been started on this boot,
            //  continue waiting for it to start.
            //

            break;

        //
        // If Netlogon is trying to start up now,
        //  continue waiting for it to start.
        //
        case SERVICE_START_PENDING:
            break;

        //
        // Any other state is bogus.
        //
        default:
            KdPrint(( "[MSV1_0] NlWaitForNetlogon: "
                      "Invalid service state: %lu\n",
                      ServiceStatus.dwCurrentState ));
            Status = STATUS_NETLOGON_NOT_STARTED;
            goto Cleanup;

        }


        //
        // Wait ten seconds for the netlogon service to start.
        //  If it has successfully started, just return now.
        //

        Status = NlWaitForEvent( L"\\NETLOGON_SERVICE_STARTED", 10 );

        if ( Status != STATUS_NETLOGON_NOT_STARTED ) {
            goto Cleanup;
        }

        //
        // If we've waited long enough for netlogon to start,
        //  time out now.
        //

        if ( (--Timeout) == 0 ) {
            Status = STATUS_NETLOGON_NOT_STARTED;
            goto Cleanup;
        }


    }

    /* NOT REACHED */

Cleanup:
    if ( ScManagerHandle != NULL ) {
        (VOID) CloseServiceHandle(ScManagerHandle);
    }
    if ( ServiceHandle != NULL ) {
        (VOID) CloseServiceHandle(ServiceHandle);
    }
    if ( AllocServiceConfig != NULL ) {
        RtlFreeHeap( MspHeap, 0, AllocServiceConfig );
    }
    return Status;
}


NTSTATUS
NlSamInitialize(
    ULONG Timeout
    )

/*++

Routine Description:

    Initialize the MSV1_0 Authentication Package's communication to the SAM
    database.  This initialization will take place once immediately prior
    to the first actual use of the SAM database.

Arguments:

    Timeout - Timeout for event (in seconds).

Return Status:

    STATUS_SUCCESS - Indicates NETLOGON successfully initialized.

--*/

{
    NTSTATUS Status;

    //
    // locals that are staging area for globals.
    //

    LSA_HANDLE PolicyHandle = NULL;
    UNICODE_STRING PrimaryDomainName;
    PSID SamDomainId = NULL;
    UNICODE_STRING SamDomainName;
    SAMPR_HANDLE SamDomainHandle = NULL;
    BOOLEAN UasCompatibilityRequired;


    OBJECT_ATTRIBUTES PolicyObjectAttributes;
    PLSAPR_POLICY_INFORMATION PolicyPrimaryDomainInfo = NULL;
    PLSAPR_POLICY_INFORMATION PolicyAccountDomainInfo = NULL;

    SAMPR_HANDLE SamHandle = NULL;
#ifdef SAM
    PSAMPR_DOMAIN_INFO_BUFFER DomainInfo = NULL;
#endif // SAM

    PrimaryDomainName.Buffer = NULL;
    SamDomainName.Buffer = NULL;


    //
    // Wait for SAM to finish initialization.
    //

    Status = NlWaitForEvent( L"\\SAM_SERVICE_STARTED", Timeout );

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



    //
    // Determine the DomainName and DomainId of the Account Database
    //

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

    Status = I_LsaIOpenPolicyTrusted(&PolicyHandle);

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

    ASSERT(PolicyHandle);

    Status = I_LsarQueryInformationPolicy( PolicyHandle,
                                           PolicyAccountDomainInformation,
                                           &PolicyAccountDomainInfo );


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

    if ( PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainSid == NULL ||
         PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainName.Length == 0 ) {
        KdPrint(( "MsV1_0: Account domain info from LSA invalid.\n"));
        Status = STATUS_NO_SUCH_DOMAIN;
        goto Cleanup;
    }

    Status = I_LsarQueryInformationPolicy(
                                PolicyHandle,
                                PolicyPrimaryDomainInformation,
                                &PolicyPrimaryDomainInfo );

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

    if ( PolicyPrimaryDomainInfo->PolicyPrimaryDomainInfo.Name.Length == 0 )
    {
        KdPrint(( "MsV1_0: Primary domain info from LSA invalid.\n"));
        Status = STATUS_NO_SUCH_DOMAIN;
        goto Cleanup;
    }


    //
    // save PrimaryDomainName
    //

    PrimaryDomainName.Length = PolicyPrimaryDomainInfo->PolicyPrimaryDomainInfo.Name.Length;
    PrimaryDomainName.MaximumLength = PrimaryDomainName.Length;

    PrimaryDomainName.Buffer =
            (PWSTR)RtlAllocateHeap( MspHeap, 0, PrimaryDomainName.MaximumLength );

    if ( PrimaryDomainName.Buffer == NULL ) {
        Status = STATUS_NO_MEMORY;
        goto Cleanup;
    }

    RtlCopyMemory( PrimaryDomainName.Buffer,
                    PolicyPrimaryDomainInfo->PolicyPrimaryDomainInfo.Name.Buffer,
                    PrimaryDomainName.Length );


    //
    // Save the domain id of this domain
    //

    SamDomainId = RtlAllocateHeap(
                        MspHeap, 0,
                        RtlLengthSid( PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainSid ));

    if ( SamDomainId == NULL ) {
        Status = STATUS_NO_MEMORY;
        goto Cleanup;
    }

    RtlCopyMemory( SamDomainId,
                   PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainSid,
                   RtlLengthSid( PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainSid ));


    //
    // Save the name of the account database on this machine.
    //
    // On a workstation, the account database is refered to by the machine
    // name and not the database name.

    // The above being true, the machine name is set to MACHINENAME during
    // setup and for the duration when the machine has a real machine name
    // until the end of setup, NlpSamDomainName will still have MACHINENAME.
    // This is not what the caller expects to authenticate against, so we
    // force a look from the Lsa all the time.

    // We assume that NlpSamDomainName will get the right info from the Lsa

    SamDomainName.Length = PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainName.Length;
    SamDomainName.MaximumLength = (USHORT)
        (SamDomainName.Length + sizeof(WCHAR));

    SamDomainName.Buffer =
        RtlAllocateHeap( MspHeap, 0, SamDomainName.MaximumLength );

    if ( SamDomainName.Buffer == NULL ) {
        Status = STATUS_NO_MEMORY;
        goto Cleanup;
    }

    RtlCopyMemory( SamDomainName.Buffer,
                   PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainName.Buffer,
                   SamDomainName.MaximumLength );


    //
    // Open our connection with SAM
    //

    Status = I_SamIConnect( NULL,     // No server name
                            &SamHandle,
                            SAM_SERVER_CONNECT,
                            (BOOLEAN) TRUE );   // Indicate we are privileged

    if ( !NT_SUCCESS(Status) ) {
        SamHandle = NULL;
        KdPrint(( "MsV1_0: Cannot SamIConnect %lX\n", Status));
        goto Cleanup;
    }

    //
    // Open the domain.
    //

    Status = I_SamrOpenDomain( SamHandle,
                               DOMAIN_ALL_ACCESS,
                               SamDomainId,
                               &SamDomainHandle );

    if ( !NT_SUCCESS(Status) ) {
        SamDomainHandle = NULL;
        KdPrint(( "MsV1_0: Cannot SamrOpenDomain %lX\n", Status));
        goto Cleanup;
    }

#ifdef SAM
    #error
    //
    // Ensure the role in SAM is compatible with Netlogon's role
    //  ?? Use DomainUasInformation once it is defined
    //

    Status = I_SamrQueryInformationDomain( SamDomainHandle,
                                           DomainGeneralInformation,
                                           &DomainInfo );
    if ( !NT_SUCCESS(Status) ) {
        DomainInfo = NULL;
        KdPrint(( "MsV1_0: Cannot SamrQueryInformationDomain %lX\n", Status));
        goto Cleanup;
    }

    // ?? Doesn't define this properly
    UasCompatibilityRequired = DomainInfo->General.UasCompatibilityRequired;

    I_SamIFree_SAMPR_DOMAIN_INFO_BUFFER( DomainInfo, DomainGeneralInformation );
#endif // SAM



    Status = STATUS_SUCCESS;

    EnterCriticalSection(&NtLmGlobalCritSect);

    if( !NlpSamInitialized ) {

        NlpPolicyHandle = PolicyHandle;
        NlpPrimaryDomainName = PrimaryDomainName;
        NlpSamDomainId = SamDomainId;
        NlpSamDomainName = SamDomainName;
        NlpSamDomainHandle = SamDomainHandle;

        //
        // mark locals invalid so they don't get freed.
        //

        PolicyHandle = NULL;
        PrimaryDomainName.Buffer = NULL;
        SamDomainId = NULL;
        SamDomainName.Buffer = NULL;
        SamDomainHandle = NULL;


⌨️ 快捷键说明

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