Example #1
0
static
NTSTATUS
GetAccountDomainSid(PRPC_SID *Sid)
{
    LSAPR_HANDLE PolicyHandle = NULL;
    PLSAPR_POLICY_INFORMATION PolicyInfo = NULL;
    ULONG Length = 0;
    NTSTATUS Status;

    Status = LsaIOpenPolicyTrusted(&PolicyHandle);
    if (!NT_SUCCESS(Status))
    {
        TRACE("LsaIOpenPolicyTrusted() failed (Status 0x%08lx)\n", Status);
        return Status;
    }

    Status = LsarQueryInformationPolicy(PolicyHandle,
                                        PolicyAccountDomainInformation,
                                        &PolicyInfo);
    if (!NT_SUCCESS(Status))
    {
        TRACE("LsarQueryInformationPolicy() failed (Status 0x%08lx)\n", Status);
        goto done;
    }

    Length = RtlLengthSid(PolicyInfo->PolicyAccountDomainInfo.Sid);

    *Sid = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
    if (*Sid == NULL)
    {
        ERR("Failed to allocate SID\n");
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto done;
    }

    memcpy(*Sid, PolicyInfo->PolicyAccountDomainInfo.Sid, Length);

done:
    if (PolicyInfo != NULL)
        LsaIFree_LSAPR_POLICY_INFORMATION(PolicyAccountDomainInformation,
                                          PolicyInfo);

    if (PolicyHandle != NULL)
        LsarClose(&PolicyHandle);

    return Status;
}
Example #2
0
VOID
NlChangeLogWorker(
    IN LPVOID ChangeLogWorkerParam
    )
/*++

Routine Description:

    This thread performs the special operations that are required to
    replicate the special local groups such as Administrator, Server
    Operartors, etc., in the NT BUILTIN database to the
    down level systems.

    This thread comes up first time during system bootup and initializes
    required global data.  If this NT (PDC) System is replicating to any
    down level system then it stays back, otherwise it terminates.  Also
    when a down level system is added to the domain, this thread is
    created if it is not running on the system before.

Arguments:

    None.

Return Value:

    Return when there is no down level system on the domain.

--*/
{
    NTSTATUS Status;

#if DBG
    DWORD Count;
#endif


    NlPrint((NL_CHANGELOG, "ChangeLogWorker Thread is starting \n"));

    //
    // check if have initialize the global data before
    //

    if ( !NlGlobalChangeLogWorkInit ) {

        PLSAPR_POLICY_INFORMATION PolicyAccountDomainInfo = NULL;
        DWORD DomainSidLength;

        //
        // wait for SAM service to start.
        //

        if( !NlWaitForSamService(FALSE) ) {

            NlPrint((NL_CRITICAL, "Sam server failed start."));
            goto Cleanup;
        }

        //
        // Open Sam Server
        //

        Status = SamIConnect( NULL,     // No server name
                              &NlGlobalChWorkerSamServerHandle,
                              0,        // Ignore desired access
                              (BOOLEAN) TRUE );
                                        // Indicate we are privileged

        if ( !NT_SUCCESS(Status) ) {

            NlPrint((NL_CRITICAL,
                "Failed to connect to SAM server %lx\n", Status ));

            NlGlobalChWorkerSamServerHandle = NULL;
            goto Cleanup;
        }

        //
        // Open Policy Domain
        //

        Status = LsaIOpenPolicyTrusted( &NlGlobalChWorkerPolicyHandle );

        if ( !NT_SUCCESS(Status) ) {

            NlPrint((NL_CRITICAL,
                "Failed to Open LSA database %lx\n", Status ));

            NlGlobalChWorkerPolicyHandle = NULL;
            goto Cleanup;
        }

        //
        // Open BuiltIn Domain database
        //
        // Note, build in domain SID is made during dll init time.
        //


        Status = SamrOpenDomain( NlGlobalChWorkerSamServerHandle,
                                 DOMAIN_ALL_ACCESS,
                                 NlGlobalChWorkerBuiltinDomainSid,
                                 &NlGlobalChWorkerBuiltinDBHandle );

        if ( !NT_SUCCESS(Status) ) {

            NlPrint((NL_CRITICAL,
                "Failed to Open BUILTIN database %lx\n", Status ));
            NlGlobalChWorkerBuiltinDBHandle = NULL;
            goto Cleanup;
        }

        //
        // Query account domain SID.
        //

        Status = LsarQueryInformationPolicy(
                    NlGlobalChWorkerPolicyHandle,
                    PolicyAccountDomainInformation,
                    &PolicyAccountDomainInfo );

        if ( !NT_SUCCESS(Status) ) {

            NlPrint((NL_CRITICAL,
                "Failed to Query Account domain Sid from LSA %lx\n",
                Status ));

            goto Cleanup;
        }

        if ( PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainSid == NULL ) {

            LsaIFree_LSAPR_POLICY_INFORMATION(
                PolicyAccountDomainInformation,
                PolicyAccountDomainInfo );

            NlPrint((NL_CRITICAL, "Account domain info from LSA invalid.\n"));
            goto Cleanup;
        }

        //
        // copy domain SID to global data.
        //

        DomainSidLength = RtlLengthSid( PolicyAccountDomainInfo->
                            PolicyAccountDomainInfo.DomainSid );

        NlGlobalChWorkerSamDomainSid = (PSID)NetpMemoryAllocate( DomainSidLength );

        if( NlGlobalChWorkerSamDomainSid == NULL ) {

            Status = STATUS_NO_MEMORY;

            NlPrint((NL_CRITICAL,
                "NlChangeLogWorker is out of memory.\n"));

            goto Cleanup;
        }

        Status = RtlCopySid(
                    DomainSidLength,
                    NlGlobalChWorkerSamDomainSid,
                    PolicyAccountDomainInfo->
                        PolicyAccountDomainInfo.DomainSid );

        if ( !NT_SUCCESS(Status) ) {

            NlPrint((NL_CRITICAL,
                "Failed to copy SAM Domain sid %lx\n", Status ));
            goto Cleanup;
        }

        //
        // Free up Account domain info, we don't need any more.
        //

        LsaIFree_LSAPR_POLICY_INFORMATION(
            PolicyAccountDomainInformation,
            PolicyAccountDomainInfo );

        //
        // Open Account domain
        //

        Status = SamrOpenDomain( NlGlobalChWorkerSamServerHandle,
                                 DOMAIN_ALL_ACCESS,
                                 NlGlobalChWorkerSamDomainSid,
                                 &NlGlobalChWorkerSamDBHandle );

        if ( !NT_SUCCESS(Status) ) {

            NlPrint((NL_CRITICAL,
                "Failed to Open SAM database %lx\n", Status ));
            NlGlobalChWorkerSamDBHandle = NULL;
            goto Cleanup;
        }

        //
        // Initialization done. Never do it again.
        //

        NlGlobalChangeLogWorkInit = TRUE;

    }

    //
    // If SERVERS global group is empty then it implies that we don't
    // have any down level system on this domain. so we can stop this
    // thread.
    //

    if ( NlIsServersGroupEmpty( 0 ) ) {

        NlPrint((NL_CHANGELOG, "Servers Group is empty \n "));

        goto Cleanup;
    }

    //
    // Initialize NlGlobalSpecialServerGroupList.
    //

    Status = NlInitSpecialGroupList();

    if ( !NT_SUCCESS(Status) ) {

        NlPrint((NL_CRITICAL,
            "Failed to initialize Special group list %lx\n", Status ));
        goto Cleanup;
    }

    //
    // process worker queue forever, terminate when we are asked to do
    // so or when the SERVERS group goes empty.
    //

    for( ;; ) {

        DWORD WaitStatus;

        //
        // wait on the queue to become non-empty
        //

        WaitStatus = WaitForSingleObject(
                        NlGlobalChangeLogWorkerQueueEvent,
                        (DWORD)(-1) );

        if ( WaitStatus != 0 ) {

            NlPrint((NL_CRITICAL,
                    "Change log worker failed, "
                    "WaitForSingleObject error: %ld\n",
                    WaitStatus));
            break;
        }

        //
        // empty worker queue.
        //

#if DBG
        Count = 0;
#endif
        for (;;) {

            PLIST_ENTRY ListEntry;
            PWORKER_QUEUE_ENTRY WorkerQueueEntry;

            //
            // if we are asked to leave, do so.
            //

            if( NlGlobalChangeLogWorkerTerminate ) {

                NlPrint((NL_CHANGELOG,
                    "ChangeLogWorker is asked to leave \n"));

                goto Cleanup;
            }

            LOCK_CHANGELOG();

            if( IsListEmpty( &NlGlobalChangeLogWorkerQueue ) ) {

                UNLOCK_CHANGELOG();
                break;
            }

            ListEntry = RemoveHeadList( &NlGlobalChangeLogWorkerQueue );

            UNLOCK_CHANGELOG();

            WorkerQueueEntry = CONTAINING_RECORD( ListEntry,
                                                  WORKER_QUEUE_ENTRY,
                                                  Next );

            //
            // process an queue entry.
            //

            if( !NlProcessQueueEntry( WorkerQueueEntry ) ) {

                NlPrint((NL_CHANGELOG, "Servers group becomes empty \n"));

                NetpMemoryFree( WorkerQueueEntry );
                goto Cleanup;
            }

            //
            // Free this entry.
            //

            NetpMemoryFree( WorkerQueueEntry );
#if DBG
            Count++;
#endif
        }

        NlPrint((NL_CHANGELOG,
            "Changelog worker processed %lu entries.\n", Count) );
    }

Cleanup:

    //
    // empty worker queue and group list
    //

    LOCK_CHANGELOG();

#if DBG
    Count = 0;
#endif
    while ( !IsListEmpty( &NlGlobalChangeLogWorkerQueue ) ) {
        PLIST_ENTRY ListEntry;
        PWORKER_QUEUE_ENTRY WorkerQueueEntry;

        ListEntry = RemoveHeadList( &NlGlobalChangeLogWorkerQueue );

        WorkerQueueEntry = CONTAINING_RECORD( ListEntry,
                                              WORKER_QUEUE_ENTRY,
                                              Next );
        NetpMemoryFree( WorkerQueueEntry );
#if DBG
        Count++;
#endif
    }

#if DBG
    if ( Count != 0 ) {
        NlPrint((NL_CHANGELOG,
            "Changelog worker did not process %lu entries.\n", Count) );
    }
#endif

    while ( !IsListEmpty( &NlGlobalSpecialServerGroupList ) ) {
        PLIST_ENTRY ListEntry;
        PGLOBAL_GROUP_ENTRY ServerEntry;

        ListEntry = RemoveHeadList( &NlGlobalSpecialServerGroupList );

        ServerEntry = CONTAINING_RECORD( ListEntry,
                                         GLOBAL_GROUP_ENTRY,
                                         Next );
        NetpMemoryFree( ServerEntry );
    }

    UNLOCK_CHANGELOG();

    NlPrint((NL_CHANGELOG, "ChangeLogWorker Thread is exiting \n"));

    return;
    UNREFERENCED_PARAMETER( ChangeLogWorkerParam );
}
Example #3
0
static
NTSTATUS
BuildTokenPrivileges(PTOKEN_PRIVILEGES *TokenPrivileges)
{
    /* FIXME shouldn't use hard-coded list of privileges */
    static struct
    {
      LPCWSTR PrivName;
      DWORD Attributes;
    }
    DefaultPrivs[] =
    {
      { L"SeMachineAccountPrivilege", 0 },
      { L"SeSecurityPrivilege", 0 },
      { L"SeTakeOwnershipPrivilege", 0 },
      { L"SeLoadDriverPrivilege", 0 },
      { L"SeSystemProfilePrivilege", 0 },
      { L"SeSystemtimePrivilege", 0 },
      { L"SeProfileSingleProcessPrivilege", 0 },
      { L"SeIncreaseBasePriorityPrivilege", 0 },
      { L"SeCreatePagefilePrivilege", 0 },
      { L"SeBackupPrivilege", 0 },
      { L"SeRestorePrivilege", 0 },
      { L"SeShutdownPrivilege", 0 },
      { L"SeDebugPrivilege", 0 },
      { L"SeSystemEnvironmentPrivilege", 0 },
      { L"SeChangeNotifyPrivilege", SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
      { L"SeRemoteShutdownPrivilege", 0 },
      { L"SeUndockPrivilege", 0 },
      { L"SeEnableDelegationPrivilege", 0 },
      { L"SeImpersonatePrivilege", SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
      { L"SeCreateGlobalPrivilege", SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }
    };
    PTOKEN_PRIVILEGES Privileges = NULL;
    ULONG i;
    RPC_UNICODE_STRING PrivilegeName;
    LSAPR_HANDLE PolicyHandle = NULL;
    NTSTATUS Status = STATUS_SUCCESS;

    Status = LsaIOpenPolicyTrusted(&PolicyHandle);
    if (!NT_SUCCESS(Status))
    {
        goto done;
    }

    /* Allocate and initialize token privileges */
    Privileges = DispatchTable.AllocateLsaHeap(sizeof(TOKEN_PRIVILEGES) +
                                               sizeof(DefaultPrivs) / sizeof(DefaultPrivs[0]) *
                                               sizeof(LUID_AND_ATTRIBUTES));
    if (Privileges == NULL)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto done;
    }

    Privileges->PrivilegeCount = 0;
    for (i = 0; i < sizeof(DefaultPrivs) / sizeof(DefaultPrivs[0]); i++)
    {
        PrivilegeName.Length = wcslen(DefaultPrivs[i].PrivName) * sizeof(WCHAR);
        PrivilegeName.MaximumLength = PrivilegeName.Length + sizeof(WCHAR);
        PrivilegeName.Buffer = (LPWSTR)DefaultPrivs[i].PrivName;

        Status = LsarLookupPrivilegeValue(PolicyHandle,
                                          &PrivilegeName,
                                          &Privileges->Privileges[Privileges->PrivilegeCount].Luid);
        if (!NT_SUCCESS(Status))
        {
            WARN("Can't set privilege %S\n", DefaultPrivs[i].PrivName);
        }
        else
        {
            Privileges->Privileges[Privileges->PrivilegeCount].Attributes = DefaultPrivs[i].Attributes;
            Privileges->PrivilegeCount++;
        }
    }

    *TokenPrivileges = Privileges;

done:
    if (PolicyHandle != NULL)
        LsarClose(PolicyHandle);

    return Status;
}