NTSTATUS
SamrSrvQueryAliasInfo(
    /* [in] */ handle_t hBinding,
    /* [in] */ ACCOUNT_HANDLE hAlias,
    /* [in] */ UINT16 level,
    /* [out] */ AliasInfo **info
    )
{
    PCSTR filterFormat = "%s=%Q";
    NTSTATUS ntStatus = STATUS_SUCCESS;
    DWORD dwError = 0;
    PACCOUNT_CONTEXT pAcctCtx = NULL;
    PDOMAIN_CONTEXT pDomCtx = NULL;
    PCONNECT_CONTEXT pConnCtx = NULL;
    PWSTR pwszBase = NULL;
    WCHAR wszAttrDn[] = DS_ATTR_DISTINGUISHED_NAME;
    WCHAR wszAttrSamAccountName[] = DS_ATTR_SAM_ACCOUNT_NAME;
    WCHAR wszAttrDescription[] = DS_ATTR_DESCRIPTION;
    CHAR szAttrDn[] = DS_ATTR_DISTINGUISHED_NAME;
    DWORD dwScope = 0;
    PSTR pszDn = NULL;
    PWSTR pwszFilter = NULL;
    PDIRECTORY_ENTRY pEntry = NULL;
    DWORD dwEntriesNum = 0;
    PDIRECTORY_ENTRY pMemberEntry = NULL;
    DWORD dwNumMembers = 0;
    AliasInfo *pAliasInfo = NULL;

    PWSTR wszAttributesLevel1[] = {
        wszAttrSamAccountName,
        wszAttrDescription,
        NULL
    };

    PWSTR wszAttributesLevel2[] = {
        wszAttrSamAccountName,
        NULL
    };

    PWSTR wszAttributesLevel3[] = {
        wszAttrDescription,
        NULL
    };

    PWSTR *pwszAttributes[] = {
        wszAttributesLevel1,
        wszAttributesLevel2,
        wszAttributesLevel3
    };

    PWSTR wszMemberAttributes[] = {
        wszAttrDn,
        NULL
    };

    pAcctCtx = (PACCOUNT_CONTEXT)hAlias;

    if (pAcctCtx == NULL || pAcctCtx->Type != SamrContextAccount)
    {
        ntStatus = STATUS_INVALID_HANDLE;
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    if (!(pAcctCtx->dwAccessGranted & ALIAS_ACCESS_LOOKUP_INFO))
    {
        ntStatus = STATUS_ACCESS_DENIED;
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    pDomCtx  = pAcctCtx->pDomCtx;
    pConnCtx = pDomCtx->pConnCtx;

    pwszBase = pDomCtx->pwszDn;

    dwError = LwWc16sToMbs(pAcctCtx->pwszDn,
                           &pszDn);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = DirectoryAllocateWC16StringFilterPrintf(
                            &pwszFilter,
                            filterFormat,
                            szAttrDn, pszDn);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = DirectorySearch(pConnCtx->hDirectory,
                              pwszBase,
                              dwScope,
                              pwszFilter,
                              pwszAttributes[level - 1],
                              FALSE,
                              &pEntry,
                              &dwEntriesNum);
    BAIL_ON_LSA_ERROR(dwError);

    if (dwEntriesNum == 0)
    {
        ntStatus = STATUS_INVALID_HANDLE;

    }
    else if (dwEntriesNum > 1)
    {
        ntStatus = STATUS_INTERNAL_ERROR;
    }

    BAIL_ON_NTSTATUS_ERROR(ntStatus);

    if (level == ALIAS_INFO_ALL)
    {
        dwError = DirectoryGetGroupMembers(pConnCtx->hDirectory,
                                           pAcctCtx->pwszDn,
                                           wszMemberAttributes,
                                           &pMemberEntry,
                                           &dwNumMembers);
        BAIL_ON_LSA_ERROR(dwError);
    }

    ntStatus = SamrSrvAllocateMemory((void**)&pAliasInfo,
                                     sizeof(*pAliasInfo));
    BAIL_ON_NTSTATUS_ERROR(ntStatus);

    switch (level)
    {
    case ALIAS_INFO_ALL:
        ntStatus = SamrFillAliasInfo1(pEntry, dwNumMembers, pAliasInfo);
        break;

    case ALIAS_INFO_NAME:
        ntStatus = SamrFillAliasInfo2(pEntry, pAliasInfo);
        break;

    case ALIAS_INFO_DESCRIPTION:
        ntStatus = SamrFillAliasInfo3(pEntry, pAliasInfo);
        break;

    default:
        ntStatus = STATUS_INVALID_INFO_CLASS;
    }
    
    BAIL_ON_NTSTATUS_ERROR(ntStatus);

    *info = pAliasInfo;
    
cleanup:
    LW_SAFE_FREE_MEMORY(pszDn);
    LW_SAFE_FREE_MEMORY(pwszFilter);

    if (pEntry)
    {
        DirectoryFreeEntries(pEntry, dwEntriesNum);
    }

    if (ntStatus == STATUS_SUCCESS &&
        dwError != ERROR_SUCCESS)
    {
        ntStatus = LwWin32ErrorToNtStatus(dwError);
    }

    return ntStatus;

error:
    if (pAliasInfo)
    {
        SamrSrvFreeMemory(pAliasInfo);
    }

    *info = NULL;
    goto cleanup;
}
Esempio n. 2
0
DWORD
LocalDirOpenEnumMembers(
    IN HANDLE hProvider,
    OUT PHANDLE phEnum,
    IN LSA_FIND_FLAGS FindFlags,
    IN PCSTR pszSid
    )
{
    DWORD dwError = 0;
    PLOCAL_PROVIDER_CONTEXT pContext = (PLOCAL_PROVIDER_CONTEXT)hProvider;
    static WCHAR wszAttrNameObjectClass[]    = LOCAL_DIR_ATTR_OBJECT_CLASS;
    static WCHAR wszAttrNameObjectSID[]      = LOCAL_DIR_ATTR_OBJECT_SID;
    static WCHAR wszAttrNameDN[]             = LOCAL_DIR_ATTR_DISTINGUISHED_NAME;
    static PWSTR wszResolveAttrs[] =
    {
        wszAttrNameObjectClass,
        wszAttrNameDN,
        NULL
    };
    static PWSTR wszEnumAttrs[] =
    {
        wszAttrNameObjectSID,
        NULL
    };

    PWSTR pwszFilter = NULL;
    LOCAL_ENUM_HANDLE hEnum = NULL;
    PDIRECTORY_ENTRY pEntry = NULL;
    DWORD dwNumEntries = 0;
    PWSTR pwszDN = NULL;

    dwError = LwAllocateMemory(sizeof(*hEnum), OUT_PPVOID(&hEnum));
    BAIL_ON_LSA_ERROR(dwError);

    hEnum->hProvider = hProvider;
    hEnum->type = LOCAL_ENUM_HANDLE_MEMBERS;

    dwError = DirectoryAllocateWC16StringFilterPrintf(
        &pwszFilter,
        LOCAL_DB_DIR_ATTR_OBJECT_SID " = %Q",
        pszSid);
    BAIL_ON_LSA_ERROR(dwError);
    
    dwError = DirectorySearch(
        pContext->hDirectory,
        NULL,
        0,
        pwszFilter,
        wszResolveAttrs,
        FALSE,
        &pEntry,
        &dwNumEntries);
    BAIL_ON_LSA_ERROR(dwError);

    if (dwNumEntries == 0)
    {
        dwError = LW_ERROR_NO_SUCH_OBJECT;
        BAIL_ON_LSA_ERROR(dwError);
    }
    else if (dwNumEntries > 1)
    {
        dwError = LW_ERROR_DATA_ERROR;
        BAIL_ON_LSA_ERROR(dwError);
    }
    else
    {
        /* FIXME: ensure that sid resolved to a group */
        dwError = LocalMarshalAttrToUnicodeString(
            pEntry,
            wszAttrNameDN,
            &pwszDN);
        BAIL_ON_LSA_ERROR(dwError);

        dwError = DirectoryGetGroupMembers(
            pContext->hDirectory,
            pwszDN,
            wszEnumAttrs,
            &hEnum->pEntries,
            &hEnum->dwCount);
        BAIL_ON_LSA_ERROR(dwError);

        dwError = LocalGetSequenceNumber(
            pContext,
            &hEnum->llSequenceNumber);
        BAIL_ON_LSA_ERROR(dwError);
    }

    *phEnum = hEnum;
        
cleanup:

    LW_SAFE_FREE_MEMORY(pwszFilter);
    LW_SAFE_FREE_MEMORY(pwszDN);

    if (pEntry)
    {
        DirectoryFreeEntries(pEntry, dwNumEntries);
    }

    return dwError;

error:

    if (hEnum)
    {
        LocalDirCloseEnum(hEnum);
    }

    goto cleanup;
}
NTSTATUS
SamrSrvGetMembersInAlias(
    IN  handle_t        hBinding,
    IN  ACCOUNT_HANDLE  hAlias,
    OUT SID_ARRAY      *pSids
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    DWORD dwError = 0;
    PACCOUNT_CONTEXT pAcctCtx = NULL;
    PCONNECT_CONTEXT pConnCtx = NULL;
    HANDLE hDirectory = NULL;
    PWSTR pwszAliasDn = NULL;
    WCHAR wszAttrObjectSid[] = DS_ATTR_OBJECT_SID;
    PDIRECTORY_ENTRY pMemberEntries;
    DWORD dwMembersNum = 0;
    DWORD i = 0;
    PWSTR pwszMemberSid = NULL;
    PSID pMemberSid = NULL;
    SID_ARRAY Sids = {0};

    PWSTR wszAttributes[] = {
        wszAttrObjectSid,
        NULL
    };

    pAcctCtx = (PACCOUNT_CONTEXT)hAlias;

    if (pAcctCtx == NULL || pAcctCtx->Type != SamrContextAccount)
    {
        ntStatus = STATUS_INVALID_HANDLE;
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    if (!(pAcctCtx->dwAccessGranted & ALIAS_ACCESS_GET_MEMBERS))
    {
        ntStatus = STATUS_ACCESS_DENIED;
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    pConnCtx    = (PCONNECT_CONTEXT)pAcctCtx->pDomCtx->pConnCtx;
    hDirectory  = pConnCtx->hDirectory;
    pwszAliasDn = pAcctCtx->pwszDn;

    dwError = DirectoryGetGroupMembers(hDirectory,
                                       pwszAliasDn,
                                       wszAttributes,
                                       &pMemberEntries,
                                       &dwMembersNum);
    BAIL_ON_LSA_ERROR(dwError);

    Sids.dwNumSids = dwMembersNum;
    ntStatus = SamrSrvAllocateMemory((PVOID*)&Sids.pSids,
                                   sizeof(*Sids.pSids) * Sids.dwNumSids);
    BAIL_ON_NTSTATUS_ERROR(ntStatus);

    for (i = 0; i < dwMembersNum; i++)
    {
        PDIRECTORY_ENTRY pEntry = &(pMemberEntries[i]);

        dwError = DirectoryGetEntryAttrValueByName(
                                    pEntry,
                                    wszAttrObjectSid,
                                    DIRECTORY_ATTR_TYPE_UNICODE_STRING,
                                    &pwszMemberSid);
        BAIL_ON_LSA_ERROR(dwError);

        ntStatus = SamrSrvAllocateSidFromWC16String(
                                    &pMemberSid,
                                    pwszMemberSid);
        BAIL_ON_NTSTATUS_ERROR(ntStatus);

        Sids.pSids[i].pSid = pMemberSid;
    }

    pSids->dwNumSids = Sids.dwNumSids;
    pSids->pSids     = Sids.pSids;

cleanup:
    if (pMemberEntries)
    {
        DirectoryFreeEntries(pMemberEntries, dwMembersNum);
    }

    if (ntStatus == STATUS_SUCCESS &&
        dwError != ERROR_SUCCESS)
    {
        ntStatus = LwWin32ErrorToNtStatus(dwError);
    }

    return ntStatus;

error:
    for (i = 0; i < dwMembersNum; i++)
    {
        SamrSrvFreeMemory(Sids.pSids[i].pSid);
    }
    SamrSrvFreeMemory(Sids.pSids);

    memset(pSids, 0, sizeof(*pSids));
    goto cleanup;
}