Exemplo n.º 1
0
static
DWORD
LocalDirQueryMemberOfDN(
    IN HANDLE hProvider,
    IN LSA_FIND_FLAGS FindFlags,
    IN PWSTR pwszDN,
    IN OUT PLW_HASH_TABLE pGroupHash
    )
{
    DWORD dwError = 0;
    PLOCAL_PROVIDER_CONTEXT pContext = (PLOCAL_PROVIDER_CONTEXT)hProvider;
    static WCHAR wszAttrNameObjectSID[] = LOCAL_DIR_ATTR_OBJECT_SID;
    static PWSTR wszMemberAttrs[] =
    {
        wszAttrNameObjectSID,
        NULL
    };
    PDIRECTORY_ENTRY pEntries = NULL;
    DWORD dwNumEntries = 0;
    PSTR pszFilter = NULL;
    PWSTR pwszFilter = NULL;
    DWORD dwIndex = 0;
    PSTR pszGroupSid = NULL;
    PSTR pszPreviousGroupSid = NULL;

    dwError = DirectoryGetMemberships(
        pContext->hDirectory,
        pwszDN,
        wszMemberAttrs,
        &pEntries,
        &dwNumEntries);
    BAIL_ON_LSA_ERROR(dwError);
            
    for (dwIndex = 0; dwIndex < dwNumEntries; dwIndex++)
    {
        dwError = LocalMarshalAttrToANSIFromUnicodeString(
            &pEntries[dwIndex],
            wszAttrNameObjectSID,
            &pszGroupSid);
        BAIL_ON_LSA_ERROR(dwError);
        
        dwError = LwHashGetValue(
            pGroupHash,
            pszGroupSid,
            OUT_PPVOID(&pszPreviousGroupSid));
        if (dwError == ERROR_NOT_FOUND)
        {
            dwError = LwHashSetValue(
                pGroupHash,
                pszGroupSid,
                pszGroupSid);
            BAIL_ON_LSA_ERROR(dwError);
            
            dwError = LocalDirQueryMemberOfInternal(
                hProvider,
                FindFlags,
                pszGroupSid,
                pGroupHash);
            pszGroupSid = NULL;
            BAIL_ON_LSA_ERROR(dwError);
        }
        else
        {
            BAIL_ON_LSA_ERROR(dwError);
        }
        
        LW_SAFE_FREE_MEMORY(pszGroupSid);
    }

cleanup:

    LW_SAFE_FREE_MEMORY(pwszFilter);
    LW_SAFE_FREE_MEMORY(pszFilter);
    
    if (pEntries)
    {
        DirectoryFreeEntries(pEntries, dwNumEntries);
    }

    return dwError;

error:

    goto cleanup;
}
Exemplo n.º 2
0
DWORD
AD_AddAllowedMember(
    IN PLSA_AD_PROVIDER_STATE pState,
    IN PCSTR               pszSID,
    IN PSTR                pszMember,
    IN OUT PLW_HASH_TABLE *ppAllowedMemberList
)
{
    DWORD dwError = 0;
    BOOLEAN bInLock = FALSE;
    PSTR  pszValue = NULL;
    PSTR  pszSIDCopy = NULL;
    PSTR  pszMemberCopy = NULL;
    PLW_HASH_TABLE pAllowedMemberList = *ppAllowedMemberList;

    ENTER_AD_CONFIG_RW_WRITER_LOCK(bInLock, pState);

    if (!pState->pAllowedSIDs)
    {
        dwError = LwHashCreate(
                      11,
                      LwHashCaselessStringCompare,
                      LwHashCaselessStringHash,
                      AD_FreeHashStringKeyValue,
                      AD_CopyHashStringKeyValue,
                      &pState->pAllowedSIDs);
        BAIL_ON_LSA_ERROR(dwError);
    }

    if (!pAllowedMemberList)
    {
        dwError = LwHashCreate(
                      11,
                      LwHashCaselessStringCompare,
                      LwHashCaselessStringHash,
                      AD_FreeHashStringKeyValue,
                      AD_CopyHashStringKeyValue,
                      &pAllowedMemberList);
        BAIL_ON_LSA_ERROR(dwError);
    }

    dwError = LwAllocateString(
                  pszSID,
                  &pszSIDCopy);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwAllocateString(
                  pszMember,
                  &pszMemberCopy);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwHashSetValue(
                  pAllowedMemberList,
                  pszSIDCopy,
                  pszMemberCopy);
    BAIL_ON_LSA_ERROR(dwError);

    pszSIDCopy = NULL;
    pszMemberCopy = NULL;

    if ( AD_IsInMembersList_InLock(pState, pszMember) )
    {
        dwError = LwHashGetValue(
                      pState->pAllowedSIDs,
                      pszSID,
                      (PVOID*)&pszValue);
        if (dwError == ERROR_NOT_FOUND)
        {
            dwError = LwAllocateString(
                          pszSID,
                          &pszSIDCopy);
            BAIL_ON_LSA_ERROR(dwError);

            dwError = LwAllocateString(
                          pszMember,
                          &pszMemberCopy);
            BAIL_ON_LSA_ERROR(dwError);

            dwError = LwHashSetValue(
                          pState->pAllowedSIDs,
                          pszSIDCopy,
                          pszMemberCopy);
            BAIL_ON_LSA_ERROR(dwError);

            pszSIDCopy = NULL;
            pszMemberCopy = NULL;
        }

        AD_DeleteFromMembersList_InLock(pState, pszMember);
    }

    *ppAllowedMemberList = pAllowedMemberList;

cleanup:

    LW_SAFE_FREE_STRING(pszSIDCopy);
    LW_SAFE_FREE_STRING(pszMemberCopy);

    LEAVE_AD_CONFIG_RW_WRITER_LOCK(bInLock, pState);

    return dwError;

error:

    if ( ! *ppAllowedMemberList )
    {
        LwHashSafeFree(&pAllowedMemberList);
    }

    goto cleanup;
}
Exemplo n.º 3
0
static
DWORD
UmnSrvAddUsersFromMembership(
    HANDLE hLsass,
    LW_HASH_TABLE *pUsers,
    PCSTR pLookup
    )
{
    DWORD dwError = 0;
    LSA_QUERY_LIST list;
    PLSA_SECURITY_OBJECT *ppObjects = NULL;
    PLSA_SECURITY_OBJECT *ppMembers = NULL;
    DWORD memberCount = 0;
    DWORD i = 0;

    list.ppszStrings = &pLookup;

    dwError = LsaFindObjects(
                    hLsass,
                    NULL,
                    0,
                    LSA_OBJECT_TYPE_UNDEFINED,
                    LSA_QUERY_TYPE_BY_NT4,
                    1,
                    list,
                    &ppObjects);
    switch(dwError)
    {
        // The string was not a valid NT4 name
        case LW_ERROR_INVALID_PARAMETER:
        // The user/group does not exist
        case LW_ERROR_NO_SUCH_OBJECT:
            goto cleanup;
        default:
            BAIL_ON_UMN_ERROR(dwError);
    }

    if (ppObjects[0] && ppObjects[0]->type == LSA_OBJECT_TYPE_USER)
    {
        if (ppObjects[0]->enabled &&
                !LwHashExists(pUsers, ppObjects[0]->pszObjectSid))
        {
            dwError = LwHashSetValue(
                            pUsers,
                            ppObjects[0]->pszObjectSid,
                            ppObjects[0]);
            BAIL_ON_UMN_ERROR(dwError);
            ppObjects[0] = NULL;
        }
    }
    else if (ppObjects[0] && ppObjects[0]->type == LSA_OBJECT_TYPE_GROUP)
    {
        dwError = LsaQueryExpandedGroupMembers(
                        hLsass,
                        NULL,
                        0,
                        LSA_OBJECT_TYPE_USER,
                        ppObjects[0]->pszObjectSid,
                        &memberCount,
                        &ppMembers);
        BAIL_ON_UMN_ERROR(dwError);

        for (i = 0; i < memberCount; i++)
        {
            if (ppMembers[i]->enabled &&
                    !LwHashExists(pUsers, ppMembers[i]->pszObjectSid))
            {
                UMN_LOG_VERBOSE("Found AD user %s that can login because of group %s",
                        ppMembers[i]->userInfo.pszUnixName, pLookup);

                dwError = LwHashSetValue(
                                pUsers,
                                ppMembers[i]->pszObjectSid,
                                ppMembers[i]);
                BAIL_ON_UMN_ERROR(dwError);
                ppMembers[i] = NULL;
            }
        }
    }

cleanup:
    if (ppObjects)
    {
        LsaFreeSecurityObjectList(
            1,
            ppObjects);
    }
    if (ppMembers)
    {
        LsaFreeSecurityObjectList(
            memberCount,
            ppMembers);
    }
    return dwError;

error:
    goto cleanup;
}
Exemplo n.º 4
0
static
DWORD
UmnSrvUpdateADAccountsByHash(
    HANDLE hLsass,
    PLW_EVENTLOG_CONNECTION pEventlog,
    HANDLE hReg,
    HKEY hParameters,
    PLW_HASH_TABLE pUsers,
    long long PreviousRun,
    long long Now
    )
{
    DWORD dwError = 0;
    HKEY hUsers = NULL;
    HKEY hGroups = NULL;
    LW_HASH_ITERATOR usersIterator = { 0 };
    LW_HASH_ENTRY* pEntry = NULL;
    DWORD groupSidCount = 0;
    PSTR* ppGroupSids = NULL;
    DWORD lookupGroupSidCount = 0;
    DWORD lookupGroupSidCapacity = 0;
    // Only free the first level of this array, do not free the strings it
    // points to.
    PSTR* ppLookupGroupSids = NULL;
    LSA_QUERY_LIST list = { 0 };
    PLSA_SECURITY_OBJECT *ppLookedupGroups = NULL;
    PLW_HASH_TABLE pGroups = NULL;
    PLW_HASH_TABLE pNameToUser = NULL;
    PLW_HASH_TABLE pNameToGroup = NULL;
    DWORD i = 0;
    // Do not free
    PLSA_SECURITY_OBJECT pGroup = NULL;
    // Do not free
    PLSA_SECURITY_OBJECT pExisting = NULL;
    PSTR pNewName = NULL;

    dwError = LwHashCreate(
                    100,
                    LwHashStringCompare,
                    LwHashStringHash,
                    UmnSrvHashFreeObjectValue,
                    NULL,
                    &pGroups);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LwHashCreate(
                    100,
                    LwHashStringCompare,
                    LwHashStringHash,
                    NULL,
                    NULL,
                    &pNameToGroup);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LwHashCreate(
                    pUsers->sCount * 2,
                    LwHashStringCompare,
                    LwHashStringHash,
                    NULL,
                    NULL,
                    &pNameToUser);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegOpenKeyExA(
                hReg,
                hParameters,
                "AD Users",
                0,
                KEY_ALL_ACCESS,
                &hUsers);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegOpenKeyExA(
                hReg,
                hParameters,
                "AD Groups",
                0,
                KEY_ALL_ACCESS,
                &hGroups);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LwHashGetIterator(
                    pUsers,
                    &usersIterator);
    BAIL_ON_UMN_ERROR(dwError);

    while((pEntry = LwHashNext(&usersIterator)) != NULL)
    {
        PLSA_SECURITY_OBJECT pUser = (PLSA_SECURITY_OBJECT)pEntry->pValue;

        if (gbPollerThreadShouldExit)
        {
            dwError = ERROR_CANCELLED;
            BAIL_ON_UMN_ERROR(dwError);
        }

        dwError = LwHashGetValue(
                        pNameToUser,
                        pUser->userInfo.pszUnixName,
                        (PVOID*)&pExisting);
        if (dwError != ERROR_NOT_FOUND)
        {
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateStringPrintf(
                            &pNewName,
                            "%s\\%s",
                            pUser->pszNetbiosDomainName,
                            pUser->pszSamAccountName);
            BAIL_ON_UMN_ERROR(dwError);

            UMN_LOG_ERROR("Found conflict on user name '%hhs'. Sid %hhs will now be reported as name '%s' instead because its alias conflicts with sid %hhs.",
                                    pUser->userInfo.pszUnixName,
                                    pUser->pszObjectSid,
                                    pNewName,
                                    pExisting->pszObjectSid);
            BAIL_ON_UMN_ERROR(dwError);

            LW_SAFE_FREE_STRING(pUser->userInfo.pszUnixName);
            pUser->userInfo.pszUnixName = pNewName;
            pNewName = NULL;
        }

        dwError = LwHashSetValue(
                        pNameToUser,
                        pUser->userInfo.pszUnixName,
                        pUser);
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvUpdateADUser(
                        pEventlog,
                        hReg,
                        hUsers,
                        PreviousRun,
                        Now,
                        pUser);
        if (dwError == ERROR_NO_UNICODE_TRANSLATION)
        {
            // Error message already logged
            dwError = 0;
            continue;
        }
        BAIL_ON_UMN_ERROR(dwError);

        if (ppGroupSids)
        {
            LsaFreeSidList(
                    groupSidCount,
                    ppGroupSids);
        }
        dwError = LsaQueryMemberOf(
                        hLsass,
                        NULL,
                        0,
                        1,
                        &pUser->pszObjectSid,
                        &groupSidCount,
                        &ppGroupSids);
        BAIL_ON_UMN_ERROR(dwError);

        if (groupSidCount > lookupGroupSidCapacity)
        {
            LW_SAFE_FREE_MEMORY(ppLookupGroupSids);

            dwError = LwAllocateMemory(
                            groupSidCount * sizeof(ppLookupGroupSids[0]),
                            (PVOID*)&ppLookupGroupSids);
            BAIL_ON_UMN_ERROR(dwError);

            lookupGroupSidCapacity = groupSidCount;
        }

        lookupGroupSidCount = 0;

        for (i = 0; i < groupSidCount; i++)
        {
            dwError = LwHashGetValue(
                            pGroups,
                            ppGroupSids[i],
                            (PVOID*)&pGroup);
            if (dwError == ERROR_NOT_FOUND)
            {
                ppLookupGroupSids[lookupGroupSidCount++] = ppGroupSids[i];
            }
            else
            {
                BAIL_ON_UMN_ERROR(dwError);

                UMN_LOG_VERBOSE("Found AD user %s is a member of processed group %s",
                        pUser->userInfo.pszUnixName,
                        pGroup->groupInfo.pszUnixName);

                if (!pGroup->enabled)
                {
                    UMN_LOG_VERBOSE("Skipping unenabled group %s",
                        pGroup->groupInfo.pszUnixName);
                }
                else
                {
                    dwError = UmnSrvUpdateADGroupMember(
                                    pEventlog,
                                    hReg,
                                    hGroups,
                                    PreviousRun,
                                    Now,
                                    pGroup,
                                    pUser->userInfo.pszUnixName);
                    BAIL_ON_UMN_ERROR(dwError);
                }
            }
        }
        
        if (lookupGroupSidCount)
        {
            list.ppszStrings = (PCSTR *)ppLookupGroupSids;

            dwError = LsaFindObjects(
                            hLsass,
                            NULL,
                            0,
                            LSA_OBJECT_TYPE_GROUP,
                            LSA_QUERY_TYPE_BY_SID,
                            lookupGroupSidCount,
                            list,
                            &ppLookedupGroups);
            BAIL_ON_UMN_ERROR(dwError);

            for (i = 0; i < lookupGroupSidCount; i++)
            {
                if (gbPollerThreadShouldExit)
                {
                    dwError = ERROR_CANCELLED;
                    BAIL_ON_UMN_ERROR(dwError);
                }
                pGroup = ppLookedupGroups[i];

                if (!pGroup)
                {
                    UMN_LOG_ERROR("Unable to find group sid %s that user %s is a member of",
                            ppLookupGroupSids[i],
                            pUser->userInfo.pszUnixName);
                    continue;
                }

                UMN_LOG_VERBOSE("Found AD user %s is a member of unprocessed group %s",
                        pUser->userInfo.pszUnixName,
                        pGroup->groupInfo.pszUnixName);

                dwError = LwHashGetValue(
                                pNameToGroup,
                                pGroup->groupInfo.pszUnixName,
                                (PVOID*)&pExisting);
                if (dwError != ERROR_NOT_FOUND)
                {
                    BAIL_ON_UMN_ERROR(dwError);

                    dwError = LwAllocateStringPrintf(
                                    &pNewName,
                                    "%s\\%s",
                                    pGroup->pszNetbiosDomainName,
                                    pGroup->pszSamAccountName);
                    BAIL_ON_UMN_ERROR(dwError);

                    UMN_LOG_ERROR("Found conflict on group name '%hhs'. Sid %hhs will now be reported as name '%s' instead because its alias conflicts with sid %hhs.",
                                            pGroup->groupInfo.pszUnixName,
                                            pGroup->pszObjectSid,
                                            pNewName,
                                            pExisting->pszObjectSid);
                    BAIL_ON_UMN_ERROR(dwError);

                    LW_SAFE_FREE_STRING(pGroup->groupInfo.pszUnixName);
                    pGroup->groupInfo.pszUnixName = pNewName;
                    pNewName = NULL;
                }

                dwError = LwHashSetValue(
                                pNameToGroup,
                                pGroup->groupInfo.pszUnixName,
                                pGroup);
                BAIL_ON_UMN_ERROR(dwError);

                if (!pGroup->enabled)
                {
                    UMN_LOG_VERBOSE("Skipping unenabled group %s",
                        pGroup->groupInfo.pszUnixName);
                }
                else
                {
                    dwError = UmnSrvUpdateADGroup(
                                    pEventlog,
                                    hReg,
                                    hGroups,
                                    PreviousRun,
                                    Now,
                                    pGroup);
                    BAIL_ON_UMN_ERROR(dwError);

                    dwError = UmnSrvUpdateADGroupMember(
                                    pEventlog,
                                    hReg,
                                    hGroups,
                                    PreviousRun,
                                    Now,
                                    pGroup,
                                    pUser->userInfo.pszUnixName);
                    BAIL_ON_UMN_ERROR(dwError);
                }
                dwError = LwHashSetValue(
                                pGroups,
                                pGroup->pszObjectSid,
                                pGroup);
                BAIL_ON_UMN_ERROR(dwError);

                ppLookedupGroups[i] = NULL;
            }

            LsaFreeSecurityObjectList(
                lookupGroupSidCount,
                ppLookedupGroups);
            ppLookedupGroups = NULL;
        }
    }

    dwError = UmnSrvFindDeletedUsers(
                    pEventlog,
                    hReg,
                    "AD Users",
                    hUsers,
                    Now);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = UmnSrvFindDeletedGroups(
                    pEventlog,
                    hReg,
                    "AD Groups",
                    hGroups,
                    Now);
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    LW_SAFE_FREE_STRING(pNewName);
    LW_SAFE_FREE_MEMORY(ppLookupGroupSids);
    if (ppGroupSids)
    {
        LsaFreeSidList(
                groupSidCount,
                ppGroupSids);
    }
    if (ppLookedupGroups)
    {
        LsaFreeSecurityObjectList(
            lookupGroupSidCount,
            ppLookedupGroups);
    }
    if (hUsers)
    {
        RegCloseKey(hReg, hUsers);
    }
    if (hGroups)
    {
        RegCloseKey(hReg, hGroups);
    }
    LwHashSafeFree(&pGroups);
    LwHashSafeFree(&pNameToUser);
    LwHashSafeFree(&pNameToGroup);
    return dwError;
    
error:
    goto cleanup;
}
Exemplo n.º 5
0
DWORD
UmnSrvUpdateADAccounts(
    HANDLE hLsass,
    PLW_EVENTLOG_CONNECTION pEventlog,
    HANDLE hReg,
    HKEY hParameters,
    long long PreviousRun,
    long long Now
    )
{
    DWORD dwError = 0;
    PSTR pMemberList = NULL;
    PCSTR pIter = NULL;
    PSTR  pMember = NULL;
    PLW_HASH_TABLE pUsers = NULL;
    LWREG_CONFIG_ITEM ADConfigDescription[] =
    {
        {
            "RequireMembershipOf",
            TRUE,
            LwRegTypeMultiString,
            0,
            MAXDWORD,
            NULL,
            &pMemberList,
            NULL
        },
    };
    PLSASTATUS pLsaStatus = NULL;
    // Do not free
    PSTR pDomain = NULL;
    // Do not free
    PSTR pCell = NULL;
    PLSA_SECURITY_OBJECT pAllUsers = NULL;
    DWORD i = 0;

    dwError = LwHashCreate(
                    100,
                    LwHashStringCompare,
                    LwHashStringHash,
                    UmnSrvHashFreeObjectValue,
                    NULL,
                    &pUsers);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegProcessConfig(
                AD_PROVIDER_REGKEY,
                AD_PROVIDER_POLICY_REGKEY,
                ADConfigDescription,
                sizeof(ADConfigDescription)/sizeof(ADConfigDescription[0]));
    BAIL_ON_UMN_ERROR(dwError);

    if (pMemberList && pMemberList[0])
    {
        pIter = pMemberList;
        while (*pIter != 0)
        {
            dwError = LwStrDupOrNull(
                            pIter,
                            &pMember);
            BAIL_ON_UMN_ERROR(dwError);

            LwStripWhitespace(
                    pMember,
                    TRUE,
                    TRUE);

            dwError = UmnSrvAddUsersFromMembership(
                            hLsass,
                            pUsers,
                            pMember);
            BAIL_ON_UMN_ERROR(dwError);

            pIter += strlen(pIter) + 1;
        }
    }
    else
    {
        dwError = LsaGetStatus2(
                        hLsass,
                        NULL,
                        &pLsaStatus);
        BAIL_ON_UMN_ERROR(dwError);

        for (i = 0; i < pLsaStatus->dwCount; i++)
        {
            if (pLsaStatus->pAuthProviderStatusList[i].pszDomain)
            {
                pDomain = pLsaStatus->pAuthProviderStatusList[i].pszDomain;
            }
            if (pLsaStatus->pAuthProviderStatusList[i].pszCell)
            {
                pCell = pLsaStatus->pAuthProviderStatusList[i].pszCell;
            }
        }

        if (pDomain || pCell)
        {
            dwError = LwAllocateMemory(
                            sizeof(*pAllUsers),
                            (PVOID*)&pAllUsers);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "S-INVALID",
                            &pAllUsers->pszObjectSid);
            BAIL_ON_UMN_ERROR(dwError);

            pAllUsers->enabled = TRUE;
            pAllUsers->bIsLocal = FALSE;

            dwError = LwAllocateString(
                            "AllDomains",
                            &pAllUsers->pszNetbiosDomainName);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "AllUsers",
                            &pAllUsers->pszSamAccountName);
            BAIL_ON_UMN_ERROR(dwError);

            pAllUsers->type = LSA_OBJECT_TYPE_USER;

            dwError = LwAllocateString(
                            "S-INVALID",
                            &pAllUsers->userInfo.pszPrimaryGroupSid);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "All Users",
                            &pAllUsers->userInfo.pszUnixName);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "All Users",
                            &pAllUsers->userInfo.pszGecos);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "",
                            &pAllUsers->userInfo.pszShell);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "",
                            &pAllUsers->userInfo.pszHomedir);
            BAIL_ON_UMN_ERROR(dwError);

            if (pCell)
            {
                dwError = LwAllocateStringPrintf(
                                &pAllUsers->userInfo.pszDisplayName,
                                "All Users in cell %s",
                                pCell);
                BAIL_ON_UMN_ERROR(dwError);
            }
            else
            {
                dwError = LwAllocateStringPrintf(
                                &pAllUsers->userInfo.pszDisplayName,
                                "All Users accessible from domain %s",
                                pDomain);
                BAIL_ON_UMN_ERROR(dwError);
            }

            dwError = LwHashSetValue(
                            pUsers,
                            pAllUsers->pszObjectSid,
                            pAllUsers);
            BAIL_ON_UMN_ERROR(dwError);

            pAllUsers = NULL;
        }
    }

    dwError = UmnSrvUpdateADAccountsByHash(
                    hLsass,
                    pEventlog,
                    hReg,
                    hParameters,
                    pUsers,
                    PreviousRun,
                    Now);
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    if (pLsaStatus)
    {
        LsaFreeStatus(pLsaStatus);
    }
    LW_SAFE_FREE_STRING(pMemberList);
    LW_SAFE_FREE_STRING(pMember);
    LwHashSafeFree(&pUsers);
    if (pAllUsers)
    {
        LsaFreeSecurityObject(pAllUsers);
    }
    return dwError;

error:
    goto cleanup;
}
Exemplo n.º 6
0
DWORD
AD_GroupExpansionDataGetNextGroupToExpand(
    IN PLSA_AD_GROUP_EXPANSION_DATA pExpansionData,
    OUT PLSA_SECURITY_OBJECT* ppGroupToExpand,
    OUT PDWORD pdwGroupToExpandDepth
    )
{
    DWORD dwError = 0;
    PLSA_SECURITY_OBJECT pGroupToExpand = NULL;
    DWORD dwGroupToExpandDepth = 0;
    const LW_HASH_ENTRY* pHashEntry = NULL;

    dwError = pExpansionData->dwLastError;
    BAIL_ON_LSA_ERROR(dwError);

    if (pExpansionData->pGroupsToExpand->sCount < 1)
    {
        // Nothing to return
        goto cleanup;
    }

    if (pExpansionData->bIsIteratorInitialized)
    {
        pHashEntry = LwHashNext(&pExpansionData->GroupsToExpandIterator);
    }

    if (!pHashEntry)
    {
        // Either the iterator is not initialized or we
        // reached the end of the hash table and need to start over.
        dwError = LwHashGetIterator(
                    pExpansionData->pGroupsToExpand,
                    &pExpansionData->GroupsToExpandIterator);
        BAIL_ON_LSA_ERROR(dwError);

        pExpansionData->bIsIteratorInitialized = TRUE;

        pHashEntry = LwHashNext(&pExpansionData->GroupsToExpandIterator);
        if (!pHashEntry)
        {
            dwError = LW_ERROR_INTERNAL;
            BAIL_ON_LSA_ERROR(dwError);
        }
    }

    pGroupToExpand = (PLSA_SECURITY_OBJECT) pHashEntry->pKey;
    dwGroupToExpandDepth = (size_t) pHashEntry->pValue;
    dwGroupToExpandDepth++;

    // Move the object to the expanded list.  Note that the object is
    // not necessarily expanded yet, but we must remove it from
    // the "to expand" list.  It does not hurt to track it in the
    // "expanded" list.

    dwError = LwHashSetValue(pExpansionData->pExpandedGroups,
                              pGroupToExpand,
                              (PVOID)(size_t)dwGroupToExpandDepth);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwHashRemoveKey(pExpansionData->pGroupsToExpand, pGroupToExpand);
    if (dwError)
    {
        LSA_LOG_DEBUG("ASSERT: cannot fail");
    }
    BAIL_ON_LSA_ERROR(dwError);

cleanup:
    *ppGroupToExpand = pGroupToExpand;
    *pdwGroupToExpandDepth = dwGroupToExpandDepth;

    return dwError;

error:
    ADCacheSafeFreeObject(&pGroupToExpand);
    dwGroupToExpandDepth = 0;

    if (dwError && !pExpansionData->dwLastError)
    {
        pExpansionData->dwLastError = dwError;
    }
    goto cleanup;
}
Exemplo n.º 7
0
DWORD
AD_GroupExpansionDataAddExpansionResults(
    IN PLSA_AD_GROUP_EXPANSION_DATA pExpansionData,
    IN DWORD dwExpandedGroupDepth,
    IN OUT size_t* psMembersCount,
    IN OUT PLSA_SECURITY_OBJECT** pppMembers
    )
{
    DWORD dwError = 0;
    size_t sMembersCount = *psMembersCount;
    PLSA_SECURITY_OBJECT* ppMembers = *pppMembers;

    dwError = pExpansionData->dwLastError;
    BAIL_ON_LSA_ERROR(dwError);

    if (dwExpandedGroupDepth > pExpansionData->dwMaxDepth)
    {
        // This should never happen
        dwError = LW_ERROR_INTERNAL;
        BAIL_ON_LSA_ERROR(dwError);
    }

    if ((sMembersCount + pExpansionData->pUsers->sCount) * 2 >
            pExpansionData->pUsers->sTableSize)
    {
        dwError = LwHashResize(
                        pExpansionData->pUsers,
                        (sMembersCount +
                             pExpansionData->pUsers->sCount + 10) * 3);
        BAIL_ON_LSA_ERROR(dwError);
    }

    if ((sMembersCount + pExpansionData->pGroupsToExpand->sCount) * 2 >
            pExpansionData->pGroupsToExpand->sTableSize)
    {
        dwError = LwHashResize(
                        pExpansionData->pGroupsToExpand,
                        (sMembersCount +
                             pExpansionData->pGroupsToExpand->sCount + 10) * 3);
        BAIL_ON_LSA_ERROR(dwError);
    }

    for (; sMembersCount > 0; sMembersCount--)
    {
        PLSA_SECURITY_OBJECT pCurrentMember = ppMembers[sMembersCount-1];

        if (!pCurrentMember)
        {
            continue;
        }

        if (pCurrentMember->type == LSA_OBJECT_TYPE_USER)
        {
            if (!LwHashExists(pExpansionData->pUsers,
                               ppMembers[sMembersCount-1]))
            {
                dwError = LwHashSetValue(
                    pExpansionData->pUsers,
                    ppMembers[sMembersCount-1],
                    (PVOID)(size_t)dwExpandedGroupDepth);
                BAIL_ON_LSA_ERROR(dwError);
                ppMembers[sMembersCount-1] = NULL;
            }
            else
            {
                ADCacheSafeFreeObject(&ppMembers[sMembersCount-1]);
            }
        }
        else if (pCurrentMember->type == LSA_OBJECT_TYPE_GROUP)
        {
            if (dwExpandedGroupDepth >= pExpansionData->dwMaxDepth)
            {
                pExpansionData->bDiscardedDueToDepth = TRUE;
                ADCacheSafeFreeObject(&ppMembers[sMembersCount-1]);
            }
            else if (LwHashExists(pExpansionData->pExpandedGroups,
                                   pCurrentMember) ||
                     LwHashExists(pExpansionData->pGroupsToExpand,
                                   pCurrentMember))
            {
                ADCacheSafeFreeObject(&ppMembers[sMembersCount-1]);
            }
            else
            {
                dwError = LwHashSetValue(
                            pExpansionData->pGroupsToExpand,
                            ppMembers[sMembersCount-1],
                            (PVOID)(size_t)dwExpandedGroupDepth);
                BAIL_ON_LSA_ERROR(dwError);
                ppMembers[sMembersCount-1] = NULL;
            }
        }
        else
        {
            // some other kind of object -- should not happen
            ADCacheSafeFreeObject(&ppMembers[sMembersCount-1]);
        }
    }

cleanup:
    if (ppMembers && (sMembersCount == 0))
    {
        ADCacheSafeFreeObjectList(sMembersCount, &ppMembers);
    }
    *psMembersCount = sMembersCount;
    *pppMembers = ppMembers;
    return dwError;

error:
    ADCacheSafeFreeObjectList(sMembersCount, &ppMembers);
    if (dwError && !pExpansionData->dwLastError)
    {
        pExpansionData->dwLastError = dwError;
    }
    goto cleanup;
}
Exemplo n.º 8
0
DWORD
ADLdap_GetObjectGroupMembership(
    IN PAD_PROVIDER_CONTEXT pContext,
    IN PLSA_SECURITY_OBJECT pObject,
    OUT int* piPrimaryGroupIndex,
    OUT size_t* psNumGroupsFound,
    OUT PLSA_SECURITY_OBJECT** pppGroupInfoList
    )
{
    DWORD dwError =  0;
    PLSA_DM_LDAP_CONNECTION pConn = NULL;
    PSTR pszFullDomainName = NULL;
    INT i = 0;
    PLSA_SECURITY_OBJECT* ppGroupInfoList = NULL;
    size_t sNumGroupsFound = 0;
    int    iPrimaryGroupIndex = -1;
    DWORD gcMembershipCount = 0;
    PSTR* ppGcMembershipList = NULL;
    DWORD dcMembershipCount = 0;
    PSTR* ppDcMembershipList = NULL;
    PLW_HASH_TABLE pGroupHash = NULL;
    LSA_TRUST_DIRECTION trustDirection = LSA_TRUST_DIRECTION_UNKNOWN;
    LSA_TRUST_MODE trustMode = LSA_TRUST_MODE_UNKNOWN;
    DWORD index = 0;
    DWORD totalSidCount = 0;
    PSTR* ppTotalSidList = NULL;

    // If we cannot get dn, then we cannot get DN information for this objects, hence BAIL
    if (LW_IS_NULL_OR_EMPTY_STR(pObject->pszDN))
    {
        dwError = LW_ERROR_NO_SUCH_USER;
        BAIL_ON_LSA_ERROR(dwError);
    }

    dwError = LwLdapConvertDNToDomain(
                 pObject->pszDN,
                 &pszFullDomainName);
    BAIL_ON_LSA_ERROR(dwError);

    // Note that this function is called only for 2-way trusts.  However,
    // the trust could be an external trust or a forest trust.  We can only
    // query the GC if there is a forest trust.

    dwError = AD_DetermineTrustModeandDomainName(
                    pContext->pState,
                    pszFullDomainName,
                    &trustDirection,
                    &trustMode,
                    NULL,
                    NULL);
    BAIL_ON_LSA_ERROR(dwError);

    // We could only have the DN path for the user if (s)he came from a two way
    // trusted domain or the joined domain.
    LSA_ASSERT(LSA_TRUST_DIRECTION_TWO_WAY == trustDirection ||
            LSA_TRUST_DIRECTION_SELF == trustDirection);

    if (trustMode != LSA_TRUST_MODE_EXTERNAL)
    {
        // Get forest info from domain's GC since there is a forest trust.
        // This will only include universal group information.  (The domain
        // global groups will not include membership info in the GC.)
        dwError = LsaDmLdapOpenGc(
                      pContext,
                      pszFullDomainName,
                      &pConn);
        BAIL_ON_LSA_ERROR(dwError);

        dwError = ADLdap_GetAttributeValuesList(
                        pConn,
                        pObject->pszDN,
                        AD_LDAP_MEMBEROF_TAG,
                        TRUE,
                        TRUE,
                        &gcMembershipCount,
                        &ppGcMembershipList);
        BAIL_ON_LSA_ERROR(dwError);

        LsaDmLdapClose(pConn);
        pConn = NULL;
    }

    dwError = LsaDmLdapOpenDc(
                  pContext,
                  pszFullDomainName,
                  &pConn);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = ADLdap_GetAttributeValuesList(
                    pConn,
                    pObject->pszDN,
                    AD_LDAP_MEMBEROF_TAG,
                    TRUE,
                    TRUE,
                    &dcMembershipCount,
                    &ppDcMembershipList);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwHashCreate(
                    (dcMembershipCount + gcMembershipCount + 1) * 2,
                    LwHashCaselessStringCompare,
                    LwHashCaselessStringHash,
                    ADLdap_FreeHashStringValue,
                    NULL,
                    &pGroupHash);
    BAIL_ON_LSA_ERROR(dwError);

    for (index = 0; index < gcMembershipCount; index++)
    {
        PSTR pSid = ppGcMembershipList[index];
        if (!LwHashExists(pGroupHash, pSid))
        {
            // Set the value of the hash entry as NULL so this string is not
            // freed with the hash.
            dwError = LwHashSetValue(pGroupHash, pSid, NULL);
            BAIL_ON_LSA_ERROR(dwError);
        }
    }

    for (index = 0; index < dcMembershipCount; index++)
    {
        PSTR pSid = ppDcMembershipList[index];
        if (!LwHashExists(pGroupHash, pSid))
        {
            // Set the value of the hash entry as NULL so this string is not
            // freed with the hash.
            dwError = LwHashSetValue(pGroupHash, pSid, NULL);
            BAIL_ON_LSA_ERROR(dwError);
        }
    }

    if (pObject->type == LSA_OBJECT_TYPE_USER && pObject->userInfo.pszPrimaryGroupSid)
    {
        // Add the pszPrimaryGroupSID entry to the hash
        PSTR pSid = pObject->userInfo.pszPrimaryGroupSid;
        if (!LwHashExists(pGroupHash, pSid))
        {
            // Set the value of the hash entry as NULL so this string is not
            // freed with the hash.
            dwError = LwHashSetValue(pGroupHash, pSid, NULL);
            BAIL_ON_LSA_ERROR(dwError);
        }
    }

    // Check if the user came from a domain other than the computer's domain
    if (LSA_TRUST_DIRECTION_TWO_WAY == trustDirection)
    {
        dwError = ADLdap_AddDomainLocalGroups(
                        pContext,
                        pObject,
                        pGroupHash);
        BAIL_ON_LSA_ERROR(dwError);
    }

    dwError = ADLdap_MoveHashKeysToArray(
                    pGroupHash,
                    &totalSidCount,
                    (PVOID**)(PVOID)&ppTotalSidList);
    BAIL_ON_LSA_ERROR(dwError);
    
    dwError = AD_FindObjectsBySidList(
                    pContext,
                    totalSidCount,
                    ppTotalSidList,
                    &sNumGroupsFound,
                    &ppGroupInfoList);
    BAIL_ON_LSA_ERROR(dwError);

    AD_FilterNullEntries(
            ppGroupInfoList,
            &sNumGroupsFound);

    // Determine primary group index
    if (pObject->type == LSA_OBJECT_TYPE_USER &&
        pObject->userInfo.pszPrimaryGroupSid &&
        ppGroupInfoList &&
        sNumGroupsFound)
    {
        for (i = (INT)sNumGroupsFound - 1; i >= 0; i--)
        {
            if (!strcmp(ppGroupInfoList[i]->pszObjectSid, pObject->userInfo.pszPrimaryGroupSid))
            {
                iPrimaryGroupIndex = i;
                break;
            }
        }
    }

    *psNumGroupsFound = sNumGroupsFound;
    *pppGroupInfoList = ppGroupInfoList;
    *piPrimaryGroupIndex = iPrimaryGroupIndex;

cleanup:
    LwHashSafeFree(&pGroupHash);
    LW_SAFE_FREE_STRING(pszFullDomainName);
    LwFreeStringArray(ppGcMembershipList, gcMembershipCount);
    LwFreeStringArray(ppDcMembershipList, dcMembershipCount);
    // Do not free the string pointers inside. They are borrowed from the
    // hash.
    LW_SAFE_FREE_MEMORY(ppTotalSidList);

    LsaDmLdapClose(pConn);

    return dwError;

error:

    *pppGroupInfoList = NULL;
    *psNumGroupsFound = 0;
    *piPrimaryGroupIndex = -1;

    if ( dwError != LW_ERROR_DOMAIN_IS_OFFLINE )
    {
        LSA_LOG_ERROR("Failed to group memberships of SID=%s. [error code:%u]",
                      pObject->pszObjectSid, dwError);
    }

    ADCacheSafeFreeObjectList((DWORD)sNumGroupsFound, &ppGroupInfoList);

    goto cleanup;
}
Exemplo n.º 9
0
DWORD
ADLdap_AddDomainLocalGroups(
    IN PAD_PROVIDER_CONTEXT pContext,
    IN PLSA_SECURITY_OBJECT pObject,
    IN OUT PLW_HASH_TABLE pGroupHash
    )
{
    DWORD dwError =  0;
    PLSA_DM_LDAP_CONNECTION pConn = NULL;
    PSTR szAttributeList[] = {
        AD_LDAP_OBJECTSID_TAG,
        NULL
    };
    PSTR pDomainDN = NULL;
    PSTR pszEscapedDN = NULL;
    // Do not free. This is owned by pConn
    HANDLE hDirectory = NULL;
    LDAPMessage* pMessage = NULL;
    // Do not free. This is owned by pConn
    LDAP* pLd = NULL;
    PSTR pGroupSid = NULL;
    PSTR pFilter = NULL;
    // Do not free
    LDAPMessage* pCurrentMessage = NULL;

    dwError = LsaDmLdapOpenDc(
                    pContext,
                    pContext->pState->pszDomainName,
                    &pConn);
    BAIL_ON_LSA_ERROR(dwError);
    
    dwError = LwLdapConvertDomainToDN(
                    pContext->pState->pszDomainName,
                    &pDomainDN);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwLdapEscapeString(&pszEscapedDN, pObject->pszDN);
    BAIL_ON_LSA_ERROR(dwError);

    // groupType: 2147483652 = 0x80000004 = ( GROUP_TYPE_RESOURCE_GROUP |
    // GROUP_TYPE_SECURITY_ENABLED ) = domain local security group
    dwError = LwAllocateStringPrintf(
                    &pFilter,
                    "(&(|(member=%s)(member=CN=%s,CN=ForeignSecurityPrincipals,%s))(groupType=2147483652))",
                    pszEscapedDN,
                    pObject->pszObjectSid,
                    pDomainDN);
    BAIL_ON_LSA_ERROR(dwError);
 
    dwError = LsaDmLdapDirectorySearch(
                    pConn,
                    pDomainDN,
                    LDAP_SCOPE_SUBTREE,
                    pFilter,
                    szAttributeList,
                    &hDirectory,
                    &pMessage);
    BAIL_ON_LSA_ERROR(dwError);                   

    pLd = LwLdapGetSession(hDirectory);

    pCurrentMessage = ldap_first_entry(pLd, pMessage);
    while (pCurrentMessage)
    {
        LW_SAFE_FREE_STRING(pGroupSid);
        dwError = ADLdap_GetObjectSid(
                        hDirectory,
                        pCurrentMessage,
                        &pGroupSid);
        BAIL_ON_LSA_ERROR(dwError);

        if (!LwHashExists(pGroupHash, pGroupSid))
        {
            // Set the value of the hash entry so this string gets freed with
            // the hash.
            dwError = LwHashSetValue(pGroupHash, pGroupSid, pGroupSid);
            BAIL_ON_LSA_ERROR(dwError);

            pGroupSid = NULL;
        }

        pCurrentMessage = ldap_next_entry(pLd, pCurrentMessage);
    }

cleanup:
    LsaDmLdapClose(pConn);
    LW_SAFE_FREE_STRING(pszEscapedDN);
    LW_SAFE_FREE_STRING(pDomainDN);
    LW_SAFE_FREE_STRING(pFilter);
    LW_SAFE_FREE_STRING(pGroupSid);
    if (pMessage)
    {
        ldap_msgfree(pMessage);
    }
    return dwError;

error:
    goto cleanup;
}