示例#1
0
VOID
LocalDirCloseEnum(
    IN OUT HANDLE hEnum
    )
{
    LOCAL_ENUM_HANDLE pEnum = (LOCAL_ENUM_HANDLE) hEnum;

    if (pEnum)
    {
        if (pEnum->pEntries)
        {
            DirectoryFreeEntries(pEnum->pEntries, pEnum->dwCount);
        }

        LwFreeMemory(pEnum);
    }
}
示例#2
0
static
DWORD
LocalDirFindObjectsInternal(
    IN HANDLE hProvider,
    IN LSA_FIND_FLAGS FindFlags,
    IN OPTIONAL LSA_OBJECT_TYPE ObjectType,
    IN LSA_QUERY_TYPE QueryType,
    IN DWORD dwCount,
    IN LSA_QUERY_LIST QueryList,
    IN OUT PLSA_SECURITY_OBJECT* ppObjects
    )
{
    DWORD dwError = 0;
    PLOCAL_PROVIDER_CONTEXT pContext = (PLOCAL_PROVIDER_CONTEXT)hProvider;
    static WCHAR wszAttrNameObjectClass[]    = LOCAL_DIR_ATTR_OBJECT_CLASS;
    static WCHAR wszAttrNameUID[]            = LOCAL_DIR_ATTR_UID;
    static WCHAR wszAttrNameGID[]            = LOCAL_DIR_ATTR_GID;
    static WCHAR wszAttrNamePrimaryGroup[]   = LOCAL_DIR_ATTR_PRIMARY_GROUP;
    static WCHAR wszAttrNameSamAccountName[] = LOCAL_DIR_ATTR_SAM_ACCOUNT_NAME;
    static WCHAR wszAttrNamePassword[]       = LOCAL_DIR_ATTR_PASSWORD;
    static WCHAR wszAttrNameGecos[]          = LOCAL_DIR_ATTR_GECOS;
    static WCHAR wszAttrNameShell[]          = LOCAL_DIR_ATTR_SHELL;
    static WCHAR wszAttrNameHomedir[]        = LOCAL_DIR_ATTR_HOME_DIR;
    static WCHAR wszAttrNameUPN[]            = LOCAL_DIR_ATTR_USER_PRINCIPAL_NAME;
    static WCHAR wszAttrNameObjectSID[]      = LOCAL_DIR_ATTR_OBJECT_SID;
    static WCHAR wszAttrNameDN[]             = LOCAL_DIR_ATTR_DISTINGUISHED_NAME;
    static WCHAR wszAttrNameNetBIOSDomain[]  = LOCAL_DIR_ATTR_NETBIOS_NAME;
    static WCHAR wszAttrNameUserInfoFlags[]  = LOCAL_DIR_ATTR_ACCOUNT_FLAGS;
    static WCHAR wszAttrNameAccountExpiry[]  = LOCAL_DIR_ATTR_ACCOUNT_EXPIRY;
    static WCHAR wszAttrNamePasswdLastSet[]  = LOCAL_DIR_ATTR_PASSWORD_LAST_SET;
    static WCHAR wszAttrNameNTHash[]         = LOCAL_DIR_ATTR_NT_HASH;
    static WCHAR wszAttrNameLMHash[]         = LOCAL_DIR_ATTR_LM_HASH;
    static PWSTR wszAttrs[] =
    {
        wszAttrNameObjectClass,
        wszAttrNameUID,
        wszAttrNameGID,
        wszAttrNamePrimaryGroup,
        wszAttrNameSamAccountName,
        wszAttrNamePassword,
        wszAttrNameGecos,
        wszAttrNameShell,
        wszAttrNameHomedir,
        wszAttrNameUPN,
        wszAttrNameObjectSID,
        wszAttrNameDN,
        wszAttrNameNetBIOSDomain,
        wszAttrNameUserInfoFlags,
        wszAttrNameAccountExpiry,
        wszAttrNamePasswdLastSet,
        wszAttrNameNTHash,
        wszAttrNameLMHash,
        NULL
    };
    PDIRECTORY_ENTRY pEntries = NULL;
    PDIRECTORY_ENTRY pEntry = NULL;
    DWORD dwNumEntries = 0;
    PCSTR pszFilterTemplateQualified = 
        LOCAL_DB_DIR_ATTR_NETBIOS_NAME " = %Q" \
        " AND " LOCAL_DB_DIR_ATTR_SAM_ACCOUNT_NAME " = %Q%s";
    PCSTR pszFilterTemplateString = "%s = %Q%s";
    PCSTR pszFilterTemplateDword = "%s = %u%s";
    PCSTR pszFilterTemplateType = " AND " LOCAL_DB_DIR_ATTR_OBJECT_CLASS " = %u";
    PCSTR pszFilterTemplateUserOrGroup = " AND (" \
            LOCAL_DB_DIR_ATTR_OBJECT_CLASS " = %u OR " \
            LOCAL_DB_DIR_ATTR_OBJECT_CLASS " = %u)";
    PCSTR pszFilterBy = NULL;
    PSTR pszFilterType = NULL;
    PWSTR pwszFilter = NULL;
    DWORD dwObjectClass = LOCAL_OBJECT_CLASS_UNKNOWN;
    DWORD dwIndex = 0;
    PLSA_LOGIN_NAME_INFO pLoginInfo = NULL;
    BOOLEAN bLocked = FALSE;
    BOOLEAN bFoundInvalidObject = FALSE;

    /* FIXME: support generic queries */
    switch (ObjectType)
    {
    case LSA_OBJECT_TYPE_UNDEFINED:
        dwObjectClass = LOCAL_OBJECT_CLASS_UNKNOWN;
        break;
    case LSA_OBJECT_TYPE_USER:
        dwObjectClass = LOCAL_OBJECT_CLASS_USER;
        break;
    case LSA_OBJECT_TYPE_GROUP:
        dwObjectClass = LOCAL_OBJECT_CLASS_GROUP;
        break;
    default:
        dwError = LW_ERROR_INVALID_PARAMETER;
        BAIL_ON_LSA_ERROR(dwError);
    }

    switch (QueryType)
    {
    case LSA_QUERY_TYPE_BY_DN:
        pszFilterBy = LOCAL_DB_DIR_ATTR_DISTINGUISHED_NAME;
        break;
    case LSA_QUERY_TYPE_BY_SID:
        pszFilterBy = LOCAL_DB_DIR_ATTR_OBJECT_SID;
        break;
    case LSA_QUERY_TYPE_BY_NT4:
    case LSA_QUERY_TYPE_BY_ALIAS:
        break;
    case LSA_QUERY_TYPE_BY_UPN:
        pszFilterBy = LOCAL_DB_DIR_ATTR_USER_PRINCIPAL_NAME;
        break;
    case LSA_QUERY_TYPE_BY_UNIX_ID:
        if (dwObjectClass == LOCAL_OBJECT_CLASS_USER)
        {
            pszFilterBy = LOCAL_DB_DIR_ATTR_UID;
        }
        else
        {
            pszFilterBy = LOCAL_DB_DIR_ATTR_GID;
        }
        break;
    default:
        dwError = LW_ERROR_INVALID_PARAMETER;
        BAIL_ON_LSA_ERROR(dwError);
    }

    if (dwObjectClass == LOCAL_OBJECT_CLASS_UNKNOWN)
    {
        dwError = LwAllocateStringPrintf(
            &pszFilterType,
            pszFilterTemplateUserOrGroup,
            LOCAL_OBJECT_CLASS_USER,
            LOCAL_OBJECT_CLASS_GROUP);
        BAIL_ON_LSA_ERROR(dwError);
    }
    else
    {
        dwError = LwAllocateStringPrintf(
            &pszFilterType,
            pszFilterTemplateType,
            dwObjectClass);
        BAIL_ON_LSA_ERROR(dwError);
    }

    for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
    {
        bFoundInvalidObject = FALSE;

        switch (QueryType)
        {
        case LSA_QUERY_TYPE_BY_ALIAS:
        case LSA_QUERY_TYPE_BY_NT4:
            dwError = LsaSrvCrackDomainQualifiedName(
                QueryList.ppszStrings[dwIndex],
                &pLoginInfo);
            BAIL_ON_LSA_ERROR(dwError);

            if (!pLoginInfo->pszDomain)
            {
                LOCAL_RDLOCK_RWLOCK(bLocked, &gLPGlobals.rwlock);

                dwError = LwAllocateString(
                                gLPGlobals.pszNetBIOSName,
                                &pLoginInfo->pszDomain);
                BAIL_ON_LSA_ERROR(dwError);

                LOCAL_UNLOCK_RWLOCK(bLocked, &gLPGlobals.rwlock);
            }

            dwError = DirectoryAllocateWC16StringFilterPrintf(
                &pwszFilter,
                pszFilterTemplateQualified,
                pLoginInfo->pszDomain,
                pLoginInfo->pszName,
                pszFilterType ? pszFilterType : "");
            BAIL_ON_LSA_ERROR(dwError);
            break;

        case LSA_QUERY_TYPE_BY_DN:
        case LSA_QUERY_TYPE_BY_SID:
        case LSA_QUERY_TYPE_BY_UPN:
            dwError = DirectoryAllocateWC16StringFilterPrintf(
                &pwszFilter,
                pszFilterTemplateString,
                pszFilterBy,
                QueryList.ppszStrings[dwIndex],
                pszFilterType ? pszFilterType : "");
            BAIL_ON_LSA_ERROR(dwError);
            break;

        case LSA_QUERY_TYPE_BY_UNIX_ID:
            dwError = DirectoryAllocateWC16StringFilterPrintf(
                &pwszFilter,
                pszFilterTemplateDword,
                pszFilterBy,
                QueryList.pdwIds[dwIndex],
                pszFilterType ? pszFilterType : "");
            BAIL_ON_LSA_ERROR(dwError);
            break;
        default:
            dwError = LW_ERROR_INVALID_PARAMETER;
            BAIL_ON_LSA_ERROR(dwError);
        }
        
        dwError = DirectorySearch(
            pContext->hDirectory,
            NULL,
            0,
            pwszFilter,
            wszAttrs,
            FALSE,
            &pEntries,
            &dwNumEntries);
        BAIL_ON_LSA_ERROR(dwError);
        
        if (dwNumEntries > 1)
        {
            dwError = LW_ERROR_DATA_ERROR;
            BAIL_ON_LSA_ERROR(dwError);
        }
        else if (dwNumEntries == 1)
        {
            pEntry = &pEntries[0];
            
            dwError = LocalMarshalEntryToSecurityObject(
                pEntry,
                &ppObjects[dwIndex]);
            if (dwError)
            {
                if (dwError == LW_ERROR_NO_SUCH_OBJECT)
                {
                    bFoundInvalidObject = TRUE;
                    dwError = 0;
                }
                else
                {
                    BAIL_ON_LSA_ERROR(dwError);
                }
            }
            else
            {
                dwError = LocalDirResolveUserObjectPrimaryGroupSid(
                    hProvider,
                    ppObjects[dwIndex]);
                BAIL_ON_LSA_ERROR(dwError);
            }
        }

        if ((dwNumEntries == 0 || bFoundInvalidObject) && QueryType == LSA_QUERY_TYPE_BY_UPN)
        {
            /* UPN lookup might fail because the UPN is generated, so try
               again as an NT4 lookup */
            LSA_QUERY_LIST Single;

            Single.ppszStrings = &QueryList.ppszStrings[dwIndex];
            
            dwError = LocalDirFindObjectsInternal(
                hProvider,
                FindFlags,
                ObjectType,
                LSA_QUERY_TYPE_BY_NT4,
                1,
                Single,
                &ppObjects[dwIndex]);
            BAIL_ON_LSA_ERROR(dwError);
        }

        LW_SAFE_FREE_MEMORY(pwszFilter);

        if (pEntries)
        {
            DirectoryFreeEntries(pEntries, dwNumEntries);
            pEntries = NULL;
        }

        if (pLoginInfo)
        {
            LsaSrvFreeNameInfo(pLoginInfo);
            pLoginInfo = NULL;
        }
    }

cleanup:
    LOCAL_UNLOCK_RWLOCK(bLocked, &gLPGlobals.rwlock);
    LW_SAFE_FREE_STRING(pszFilterType);
    LW_SAFE_FREE_MEMORY(pwszFilter);

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

    if (pLoginInfo)
    {
        LsaSrvFreeNameInfo(pLoginInfo);
    }

    return dwError;

error:

    goto cleanup;
}
示例#3
0
static
DWORD
LocalDirResolveUserObjectPrimaryGroupSid(
    IN HANDLE hProvider,
    IN OUT PLSA_SECURITY_OBJECT pUserObject
    )
{
    DWORD dwError = 0;
    PLOCAL_PROVIDER_CONTEXT pContext = (PLOCAL_PROVIDER_CONTEXT)hProvider;
    static WCHAR wszAttrNameObjectSID[] = LOCAL_DIR_ATTR_OBJECT_SID;
    static PWSTR wszAttrs[] =
    {
        wszAttrNameObjectSID,
        NULL
    };
    PCSTR pszTemplate = LOCAL_DB_DIR_ATTR_GID " = %u";
    PWSTR pwszFilter = NULL;
    PDIRECTORY_ENTRY pEntry = NULL;
    DWORD dwNumEntries = 0;
    
    if (pUserObject->type != LSA_OBJECT_TYPE_USER)
    {
        goto cleanup;
    }

    dwError = DirectoryAllocateWC16StringFilterPrintf(
        &pwszFilter,
        pszTemplate,
        pUserObject->userInfo.gid);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = DirectorySearch(
        pContext->hDirectory,
        NULL,
        0,
        pwszFilter,
        wszAttrs,
        FALSE,
        &pEntry,
        &dwNumEntries);
    BAIL_ON_LSA_ERROR(dwError);

    if (dwNumEntries != 1)
    {
        dwError = LW_ERROR_DATA_ERROR;
        BAIL_ON_LSA_ERROR(dwError);
    }

    dwError = LocalMarshalAttrToANSIFromUnicodeString(
        pEntry,
        wszAttrNameObjectSID,
        &pUserObject->userInfo.pszPrimaryGroupSid);
    BAIL_ON_LSA_ERROR(dwError);

cleanup:
    LW_SAFE_FREE_MEMORY(pwszFilter);

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

    return dwError;

error:

    goto cleanup;
}
示例#4
0
static
DWORD
LocalDirQueryMemberOfInternal(
    IN HANDLE hProvider,
    IN LSA_FIND_FLAGS FindFlags,
    IN PSTR pszSid,
    IN OUT PLW_HASH_TABLE pGroupHash
    )
{
    DWORD dwError = 0;
    PLOCAL_PROVIDER_CONTEXT pContext = (PLOCAL_PROVIDER_CONTEXT)hProvider;
    static WCHAR wszAttrNameDN[] = LOCAL_DIR_ATTR_DISTINGUISHED_NAME;
    static PWSTR wszResolveAttrs[] =
    {
        wszAttrNameDN,
        NULL
    };
    PDIRECTORY_ENTRY pEntries = NULL;
    DWORD dwNumEntries = 0;
    PWSTR pwszFilter = NULL;
    PWSTR pwszDN = NULL;

    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,
        &pEntries,
        &dwNumEntries);
    BAIL_ON_LSA_ERROR(dwError);
    
    if (dwNumEntries > 1)
    {
        dwError = LW_ERROR_DATA_ERROR;
        BAIL_ON_LSA_ERROR(dwError);
    }
    else if (dwNumEntries == 1)
    {
        dwError = LocalMarshalAttrToUnicodeString(
            pEntries,
            wszAttrNameDN,
            &pwszDN);
        BAIL_ON_LSA_ERROR(dwError);
        
        dwError = LocalDirQueryMemberOfDN(
            hProvider,
            FindFlags,
            pwszDN,
            pGroupHash);
        BAIL_ON_LSA_ERROR(dwError);
    }
    
cleanup:

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

    if (dwError == LW_ERROR_NO_SUCH_USER ||
        dwError == LW_ERROR_NO_SUCH_GROUP ||
        dwError == LW_ERROR_NO_SUCH_OBJECT)
    {
        dwError = 0;
    }

    return dwError;

error:

    goto cleanup;
}
示例#5
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;
}
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;
}
NTSTATUS
SamrSrvDeleteAliasMember(
    handle_t IDL_handle,
    ACCOUNT_HANDLE hAlias,
    PSID pSid
    )
{
    const wchar_t wszFilterFmt[] = L"%ws='%ws'";

    NTSTATUS ntStatus = STATUS_SUCCESS;
    DWORD dwError = ERROR_SUCCESS;
    PACCOUNT_CONTEXT pAcctCtx = NULL;
    PDOMAIN_CONTEXT pDomCtx = NULL;
    PCONNECT_CONTEXT pConnCtx = NULL;
    PWSTR pwszGroupDn = NULL;
    PWSTR pwszSid = NULL;
    size_t sSidStrLen = 0;
    HANDLE hDirectory = NULL;
    PWSTR pwszBaseDn = NULL;
    WCHAR wszAttrDn[] = DS_ATTR_DISTINGUISHED_NAME;
    WCHAR wszAttrObjectClass[] = DS_ATTR_OBJECT_CLASS;
    WCHAR wszAttrObjectSid[] = DS_ATTR_OBJECT_SID;
    DWORD dwScope = 0;
    DWORD dwFilterLen = 0;
    PWSTR pwszFilter = NULL;
    PDIRECTORY_ENTRY pEntry = NULL;
    DWORD dwEntriesNum = 0;

    PWSTR wszAttributes[] = {
        wszAttrDn,
        wszAttrObjectClass,
        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_REMOVE_MEMBER))
    {
        ntStatus = STATUS_ACCESS_DENIED;
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    pDomCtx     = pAcctCtx->pDomCtx;
    pConnCtx    = pDomCtx->pConnCtx;
    hDirectory  = pConnCtx->hDirectory;
    pwszGroupDn = pAcctCtx->pwszDn;

    ntStatus = RtlAllocateWC16StringFromSid(&pwszSid,
                                            pSid);
    BAIL_ON_NTSTATUS_ERROR(ntStatus);

    dwError = LwWc16sLen(pwszSid, &sSidStrLen);
    BAIL_ON_LSA_ERROR(dwError);

    dwFilterLen = ((sizeof(wszAttrObjectClass)/sizeof(WCHAR) - 1)) +
                  sSidStrLen +
                  (sizeof(wszFilterFmt)/sizeof(wszFilterFmt[0]));

    dwError = LwAllocateMemory(sizeof(WCHAR) * dwFilterLen,
                               OUT_PPVOID(&pwszFilter));
    BAIL_ON_LSA_ERROR(dwError);

    if (sw16printfw(pwszFilter, dwFilterLen, wszFilterFmt,
                    wszAttrObjectSid, pwszSid) < 0)
    {
        ntStatus = LwErrnoToNtStatus(errno);
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    dwError = DirectorySearch(hDirectory,
                              pwszBaseDn,
                              dwScope,
                              pwszFilter,
                              wszAttributes,
                              FALSE,
                              &pEntry,
                              &dwEntriesNum);
    BAIL_ON_LSA_ERROR(dwError);

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

    dwError = DirectoryRemoveFromGroup(hDirectory,
                                       pwszGroupDn,
                                       pEntry);
    BAIL_ON_LSA_ERROR(dwError);

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

    LW_SAFE_FREE_MEMORY(pwszFilter);
    RTL_FREE(&pwszSid);

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

    return ntStatus;

error:
    goto cleanup;
}
示例#8
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;
}
NTSTATUS
SamrSrvEnumDomainAccounts(
    IN  handle_t          hBinding,
    IN  DOMAIN_HANDLE     hDomain,
    IN OUT PDWORD         pdwResume,
    IN  DWORD             dwObjectClass,
    IN  DWORD             dwFlagsFilter,
    IN  DWORD             dwMaxSize,
    OUT RID_NAME_ARRAY  **ppNames,
    OUT UINT32           *pdwNumEntries
    )
{
    wchar_t wszFilterFmt[] = L"%ws=%u AND %ws='%ws'";
    NTSTATUS ntStatus = STATUS_SUCCESS;
    NTSTATUS ntEnumStatus = STATUS_SUCCESS;
    DWORD dwError = 0;
    PDOMAIN_CONTEXT pDomCtx = NULL;
    PCONNECT_CONTEXT pConnCtx = NULL;
    PWSTR pwszBase = NULL;
    WCHAR wszAttrObjectClass[] = DS_ATTR_OBJECT_CLASS;
    WCHAR wszAttrDomainName[] = DS_ATTR_DOMAIN;
    WCHAR wszAttrAccountFlags[] = DS_ATTR_ACCOUNT_FLAGS;
    WCHAR wszAttrSamAccountName[] = DS_ATTR_SAM_ACCOUNT_NAME;
    WCHAR wszAttrObjectSid[] = DS_ATTR_OBJECT_SID;
    DWORD dwScope = 0;
    PWSTR pwszFilter = NULL;
    size_t sDomainNameLen = 0;
    PWSTR pwszDomainName = NULL;
    DWORD dwFilterLen = 0;
    PDIRECTORY_ENTRY pEntries = NULL;
    PDIRECTORY_ENTRY pEntry = NULL;
    DWORD dwNumEntries = 0;
    DWORD dwTotalSize = 0;
    DWORD dwSize = 0;
    DWORD i = 0;
    DWORD dwCount = 0;
    DWORD dwNumEntriesReturned = 0;
    DWORD dwResume = 0;
    DWORD dwAccountFlags = 0;
    size_t sNameLen = 0;
    PWSTR pwszName = NULL;
    PWSTR pwszSid = NULL;
    PSID pSid = NULL;
    DWORD dwRid = 0;
    RID_NAME_ARRAY *pNames = NULL;
    RID_NAME *pName = NULL;
    DWORD dwNewResumeIdx = 0;

    PWSTR wszAttributes[] = {
        wszAttrSamAccountName,
        wszAttrObjectSid,
        wszAttrAccountFlags,
        NULL
    };

    BAIL_ON_INVALID_PTR(hDomain);
    BAIL_ON_INVALID_PTR(pdwResume);
    BAIL_ON_INVALID_PTR(ppNames);
    BAIL_ON_INVALID_PTR(pdwNumEntries);

    pDomCtx  = (PDOMAIN_CONTEXT)hDomain;
    dwResume = *pdwResume;

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

    if (!(pDomCtx->dwAccessGranted & DOMAIN_ACCESS_ENUM_ACCOUNTS))
    {
        ntStatus = STATUS_ACCESS_DENIED;
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    pConnCtx       = pDomCtx->pConnCtx;
    pwszBase       = pDomCtx->pwszDn;
    pwszDomainName = pDomCtx->pwszDomainName;

    dwError = LwWc16sLen(pwszDomainName, &sDomainNameLen);
    BAIL_ON_LSA_ERROR(dwError);

    dwFilterLen = ((sizeof(wszAttrObjectClass)/sizeof(WCHAR)) - 1) +
                  10 +
                  ((sizeof(wszAttrDomainName)/sizeof(WCHAR)) - 1) +
                  (sDomainNameLen + 1) +
                  (sizeof(wszFilterFmt)/sizeof(wszFilterFmt[0]));

    dwError = LwAllocateMemory(dwFilterLen * sizeof(pwszFilter[0]),
                               OUT_PPVOID(&pwszFilter));
    BAIL_ON_LSA_ERROR(dwError);

    if (sw16printfw(pwszFilter, dwFilterLen, wszFilterFmt,
                    wszAttrObjectClass,
                    dwObjectClass,
                    wszAttrDomainName,
                    pwszDomainName) < 0)
    {
        ntStatus = LwErrnoToNtStatus(errno);
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    dwError = DirectorySearch(pConnCtx->hDirectory,
                              pwszBase,
                              dwScope,
                              pwszFilter,
                              wszAttributes,
                              FALSE,
                              &pEntries,
                              &dwNumEntries);
    BAIL_ON_LSA_ERROR(dwError);

    ntStatus = SamrSrvAllocateMemory(OUT_PPVOID(&pNames),
                                     sizeof(*pNames));
    BAIL_ON_NTSTATUS_ERROR(ntStatus);


    if (dwResume >= dwNumEntries)
    {
        ntEnumStatus = STATUS_NO_MORE_ENTRIES;
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    dwTotalSize += sizeof(pNames->dwCount);

    for (i = 0; i + dwResume < dwNumEntries; i++)
    {
        pEntry = &(pEntries[i + dwResume]);

        dwError = DirectoryGetEntryAttrValueByName(
                                     pEntry,
                                     wszAttrSamAccountName,
                                     DIRECTORY_ATTR_TYPE_UNICODE_STRING,
                                     &pwszName);
        BAIL_ON_LSA_ERROR(dwError);

        dwError = DirectoryGetEntryAttrValueByName(
                                     pEntry,
                                     wszAttrAccountFlags,
                                     DIRECTORY_ATTR_TYPE_INTEGER,
                                     &dwAccountFlags);
        BAIL_ON_LSA_ERROR(dwError);

        dwSize = 0;

        if (dwFlagsFilter &&
            !(dwAccountFlags & dwFlagsFilter))
        {
            continue;
        }

        dwError = LwWc16sLen(pwszName, &sNameLen);
        BAIL_ON_LSA_ERROR(dwError);

        dwSize += sizeof(UINT32);
        dwSize += sNameLen * sizeof(pwszName[0]);
        dwSize += 2 * sizeof(UINT16);

        dwTotalSize += dwSize;
        dwCount++;

        if (dwTotalSize > dwMaxSize)
        {
            dwTotalSize -= dwSize;
            dwCount--;

            ntEnumStatus = STATUS_MORE_ENTRIES;
            break;
        }
    }

    /*
     * At least one entry is returned regardless of declared
     * max response size
     */
    dwNumEntriesReturned = (dwSize > 0 && dwCount == 0) ? 1 : dwCount;

    pNames->dwCount = dwNumEntriesReturned;
    ntStatus = SamrSrvAllocateMemory(
                           OUT_PPVOID(&pNames->pEntries),
                           sizeof(pNames->pEntries[0]) * pNames->dwCount);
    BAIL_ON_NTSTATUS_ERROR(ntStatus);

    for (i = 0, dwCount = 0;
         dwCount < dwNumEntriesReturned && i + dwResume < dwNumEntries;
         i++)
    {
        pEntry = &(pEntries[i + dwResume]);

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

        dwError = DirectoryGetEntryAttrValueByName(pEntry,
                                                   wszAttrSamAccountName,
                                                   DIRECTORY_ATTR_TYPE_UNICODE_STRING,
                                                   &pwszName);
        BAIL_ON_LSA_ERROR(dwError);

        dwError = DirectoryGetEntryAttrValueByName(pEntry,
                                                   wszAttrAccountFlags,
                                                   DIRECTORY_ATTR_TYPE_INTEGER,
                                                   &dwAccountFlags);
        BAIL_ON_LSA_ERROR(dwError);

        dwNewResumeIdx = i + dwResume + 1;

        if (dwFlagsFilter &&
            !(dwAccountFlags & dwFlagsFilter))
        {
            continue;
        }

        pName = &(pNames->pEntries[dwCount++]);

        ntStatus = RtlAllocateSidFromWC16String(&pSid, pwszSid);
        BAIL_ON_NTSTATUS_ERROR(ntStatus);

        dwRid        = pSid->SubAuthority[pSid->SubAuthorityCount - 1];
        pName->dwRid = (UINT32)dwRid;
        
        ntStatus = SamrSrvInitUnicodeString(&pName->Name,
                                            pwszName);
        BAIL_ON_NTSTATUS_ERROR(ntStatus);

        RTL_FREE(&pSid);
    }

    *pdwResume      = dwNewResumeIdx;
    *pdwNumEntries  = dwNumEntriesReturned;
    *ppNames        = pNames;

cleanup:
    LW_SAFE_FREE_MEMORY(pwszFilter);
    RTL_FREE(&pSid);

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

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

    if (ntStatus == STATUS_SUCCESS &&
        ntEnumStatus != STATUS_SUCCESS)
    {
        ntStatus = ntEnumStatus;
    }

    return ntStatus;

error:
    if (pNames)
    {
        for (i = 0; i < pNames->dwCount; i++)
        {
            SamrSrvFreeUnicodeString(&(pNames->pEntries[i].Name));
        }
        SamrSrvFreeMemory(pNames->pEntries);
        SamrSrvFreeMemory(pNames);
    }

    *pdwResume      = 0;
    *pdwNumEntries  = 0;
    *ppNames        = NULL;
    goto cleanup;
}
示例#11
0
static
DWORD
SamDbSearchMarshallResultsAttributesValues(
    PSAM_DIRECTORY_CONTEXT pDirectoryContext,
    PCSTR                  pszQuery,
    PSAM_DB_COLUMN_VALUE   pColumnValueList,
    ULONG                  ulAttributesOnly,
    PDIRECTORY_ENTRY*      ppDirectoryEntries,
    PDWORD                 pdwNumEntries
    )
{
    DWORD                dwError = 0;
    PDIRECTORY_ENTRY     pDirectoryEntries = NULL;
    DWORD                dwNumEntries = 0;
    DWORD                dwTotalEntries = 0;
    DWORD                dwEntriesAvailable = 0;
    sqlite3_stmt*        pSqlStatement = NULL;
    DWORD                dwNumCols = 0;
    PSAM_DB_COLUMN_VALUE pIter = NULL;
    PDIRECTORY_ATTRIBUTE pAttrs = NULL;
    DWORD                dwNumAttrs = 0;

    for (pIter = pColumnValueList; pIter; pIter = pIter->pNext)
    {
        dwNumCols++;
    }

    dwError = sqlite3_prepare_v2(
                    pDirectoryContext->pDbContext->pDbHandle,
                    pszQuery,
                    -1,
                    &pSqlStatement,
                    NULL);
    BAIL_ON_SAMDB_SQLITE_ERROR_DB(dwError, pDirectoryContext->pDbContext->pDbHandle);

    while ((dwError = sqlite3_step(pSqlStatement)) == SQLITE_ROW)
    {
        DWORD iCol = 0;

        dwNumAttrs = sqlite3_column_count(pSqlStatement);
        if (dwNumAttrs != dwNumCols)
        {
            dwError = LW_ERROR_DATA_ERROR;
            BAIL_ON_SAMDB_ERROR(dwError);
        }

        if (!dwEntriesAvailable)
        {
            DWORD dwNewEntryCount = dwTotalEntries + 5;

            dwError = DirectoryReallocMemory(
                            pDirectoryEntries,
                            (PVOID*)&pDirectoryEntries,
                            dwNewEntryCount * sizeof(DIRECTORY_ENTRY));
            BAIL_ON_SAMDB_ERROR(dwError);

            dwEntriesAvailable = dwNewEntryCount - dwTotalEntries;

            memset((PBYTE)pDirectoryEntries+(dwTotalEntries * sizeof(DIRECTORY_ENTRY)),
                   0,
                   dwEntriesAvailable * sizeof(DIRECTORY_ENTRY));

            dwTotalEntries = dwNewEntryCount;
        }

        dwError = DirectoryAllocateMemory(
                        sizeof(DIRECTORY_ATTRIBUTE) * dwNumAttrs,
                        (PVOID*)&pAttrs);
        BAIL_ON_SAMDB_ERROR(dwError);

        for (pIter = pColumnValueList; pIter; pIter = pIter->pNext, iCol++)
        {
            PDIRECTORY_ATTRIBUTE pAttr = &pAttrs[iCol];
            DWORD dwAttrLen = 0;

            dwError = DirectoryAllocateStringW(
                            pIter->pAttrMap->wszDirectoryAttribute,
                            &pAttr->pwszName);
            BAIL_ON_SAMDB_ERROR(dwError);

            switch (pIter->pAttrMap->attributeType)
            {
                case SAMDB_ATTR_TYPE_TEXT:

                    dwAttrLen = sqlite3_column_bytes(pSqlStatement, iCol);
                    if (dwAttrLen)
                    {
                        PATTRIBUTE_VALUE pAttrVal = NULL;

                        const unsigned char* pszStringVal = NULL;

                        pszStringVal = sqlite3_column_text(
                                            pSqlStatement,
                                            iCol);

                        dwError = DirectoryAllocateMemory(
                                        sizeof(ATTRIBUTE_VALUE),
                                        (PVOID*)&pAttr->pValues);
                        BAIL_ON_SAMDB_ERROR(dwError);

                        pAttr->ulNumValues = 1;

                        pAttrVal = &pAttr->pValues[0];

                        pAttrVal->Type = DIRECTORY_ATTR_TYPE_UNICODE_STRING;

                        dwError = LwMbsToWc16s(
                                        (PCSTR)pszStringVal,
                                        &pAttrVal->data.pwszStringValue);
                        BAIL_ON_SAMDB_ERROR(dwError);
                    }
                    else
                    {
                        pAttr->ulNumValues = 0;
                    }

                    break;

                case SAMDB_ATTR_TYPE_INT32:
                case SAMDB_ATTR_TYPE_DATETIME:

                    dwError = DirectoryAllocateMemory(
                            sizeof(ATTRIBUTE_VALUE),
                            (PVOID*)&pAttr->pValues);
                    BAIL_ON_SAMDB_ERROR(dwError);

                    pAttr->ulNumValues = 1;

                    pAttr->pValues[0].Type = DIRECTORY_ATTR_TYPE_INTEGER;
                    pAttr->pValues[0].data.ulValue = sqlite3_column_int(
                                                        pSqlStatement,
                                                        iCol);

                    break;

                case SAMDB_ATTR_TYPE_INT64:

                    dwError = DirectoryAllocateMemory(
                                    sizeof(ATTRIBUTE_VALUE),
                                    (PVOID*)&pAttr->pValues);
                    BAIL_ON_SAMDB_ERROR(dwError);

                    pAttr->ulNumValues = 1;

                    pAttr->pValues[0].Type = DIRECTORY_ATTR_TYPE_LARGE_INTEGER;
                    pAttr->pValues[0].data.llValue = sqlite3_column_int64(
                                                        pSqlStatement,
                                                        iCol);

                    break;

                case SAMDB_ATTR_TYPE_BOOLEAN:

                    dwError = DirectoryAllocateMemory(
                                    sizeof(ATTRIBUTE_VALUE),
                                    (PVOID*)&pAttr->pValues);
                    BAIL_ON_SAMDB_ERROR(dwError);

                    pAttr->ulNumValues = 1;

                    pAttr->pValues[0].Type = DIRECTORY_ATTR_TYPE_BOOLEAN;

                    if (sqlite3_column_int(pSqlStatement, iCol))
                    {
                        pAttr->pValues[0].data.bBooleanValue = TRUE;
                    }
                    else
                    {
                        pAttr->pValues[0].data.bBooleanValue = FALSE;
                    }

                    break;

                case SAMDB_ATTR_TYPE_BLOB:
                case SAMDB_ATTR_TYPE_SECURITY_DESCRIPTOR:

                    dwAttrLen = sqlite3_column_bytes(pSqlStatement, iCol);
                    if (dwAttrLen)
                    {
                        PATTRIBUTE_VALUE pAttrVal = NULL;

                        PCVOID pBlob = sqlite3_column_blob(
                                                pSqlStatement,
                                                iCol);

                        dwError = DirectoryAllocateMemory(
                                        sizeof(ATTRIBUTE_VALUE),
                                        (PVOID*)&pAttr->pValues);
                        BAIL_ON_SAMDB_ERROR(dwError);

                        pAttr->ulNumValues = 1;

                        pAttrVal = &pAttr->pValues[0];

                        if (pIter->pAttrMap->attributeType == SAMDB_ATTR_TYPE_BLOB)
                        {
                            pAttrVal->Type = DIRECTORY_ATTR_TYPE_OCTET_STREAM;
                        }
                        else
                        {
                            pAttrVal->Type = DIRECTORY_ATTR_TYPE_NT_SECURITY_DESCRIPTOR;
                        }

                        dwError = DirectoryAllocateMemory(
                                    sizeof(OCTET_STRING),
                                    (PVOID*)&pAttrVal->data.pOctetString);
                        BAIL_ON_SAMDB_ERROR(dwError);

                        dwError = DirectoryAllocateMemory(
                                    dwAttrLen,
                                    (PVOID*)&pAttrVal->data.pOctetString->pBytes);
                        BAIL_ON_SAMDB_ERROR(dwError);

                        memcpy(pAttrVal->data.pOctetString->pBytes,
                                pBlob,
                                dwAttrLen);

                        pAttrVal->data.pOctetString->ulNumBytes = dwAttrLen;
                    }
                    else
                    {
                        pAttr->ulNumValues = 0;
                    }

                    break;

                default:

                    dwError = LW_ERROR_INTERNAL;
                    BAIL_ON_SAMDB_ERROR(dwError);
            }
        }

        pDirectoryEntries[dwNumEntries].ulNumAttributes = dwNumAttrs;
        pDirectoryEntries[dwNumEntries].pAttributes = pAttrs;

        pAttrs = NULL;
        dwNumAttrs = 0;

        dwNumEntries++;
        dwEntriesAvailable--;
    }

    if (dwError == SQLITE_DONE)
    {
        dwError = LW_ERROR_SUCCESS;
    }
    BAIL_ON_SAMDB_SQLITE_ERROR_STMT(dwError, pSqlStatement);

    *ppDirectoryEntries = pDirectoryEntries;
    *pdwNumEntries = dwNumEntries;

cleanup:

    if (pSqlStatement)
    {
        sqlite3_finalize(pSqlStatement);
    }

    return dwError;

error:

    *ppDirectoryEntries = NULL;
    *pdwNumEntries = 0;

    if (pAttrs)
    {
        DirectoryFreeAttributes(pAttrs, dwNumAttrs);
    }

    if (pDirectoryEntries)
    {
        DirectoryFreeEntries(pDirectoryEntries, dwTotalEntries);
    }

    goto cleanup;
}
示例#12
0
static
DWORD
SamDbSearchMarshallResultsAttributes(
    PSAM_DIRECTORY_CONTEXT pDirectoryContext,
    PCSTR                  pszQuery,
    PSAM_DB_COLUMN_VALUE   pColumnValueList,
    ULONG                  ulAttributesOnly,
    PDIRECTORY_ENTRY*      ppDirectoryEntries,
    PDWORD                 pdwNumEntries
    )
{
    DWORD                dwError = 0;
    PDIRECTORY_ENTRY     pDirectoryEntries = NULL;
    PDIRECTORY_ENTRY     pDirEntry = NULL;
    DWORD                dwNumEntries = 0;
    DWORD                iCol = 0;
    PSAM_DB_COLUMN_VALUE pIter = NULL;

    dwError = DirectoryAllocateMemory(
                    sizeof(DIRECTORY_ENTRY),
                    (PVOID*)&pDirectoryEntries);
    BAIL_ON_SAMDB_ERROR(dwError);

    dwNumEntries = 1;

    pDirEntry = &pDirectoryEntries[0];

    for (pIter = pColumnValueList; pIter; pIter = pIter->pNext)
    {
        pDirEntry->ulNumAttributes++;
    }

    dwError = DirectoryAllocateMemory(
                    sizeof(DIRECTORY_ATTRIBUTE) * pDirEntry->ulNumAttributes,
                    (PVOID*)&pDirEntry->pAttributes);
    BAIL_ON_SAMDB_ERROR(dwError);

    for (pIter = pColumnValueList; pIter; pIter = pIter->pNext, iCol++)
    {
        PDIRECTORY_ATTRIBUTE pAttr = &pDirEntry->pAttributes[iCol];

        dwError = DirectoryAllocateStringW(
                        pIter->pAttrMap->wszDirectoryAttribute,
                        &pAttr->pwszName);
        BAIL_ON_SAMDB_ERROR(dwError);

        dwError = DirectoryAllocateMemory(
                        sizeof(ATTRIBUTE_VALUE),
                        (PVOID*)&pAttr->pValues);
        BAIL_ON_SAMDB_ERROR(dwError);

        pAttr->ulNumValues = 1;

        switch (pIter->pAttrMap->attributeType)
        {
            case SAMDB_ATTR_TYPE_TEXT:

                pAttr->pValues[0].Type = DIRECTORY_ATTR_TYPE_UNICODE_STRING;

                break;

            case SAMDB_ATTR_TYPE_INT32:
            case SAMDB_ATTR_TYPE_BOOLEAN:
            case SAMDB_ATTR_TYPE_DATETIME:

                pAttr->pValues[0].Type = DIRECTORY_ATTR_TYPE_INTEGER;

                break;

            case SAMDB_ATTR_TYPE_INT64:

                pAttr->pValues[0].Type = DIRECTORY_ATTR_TYPE_LARGE_INTEGER;

                break;

            case SAMDB_ATTR_TYPE_BLOB:

                pAttr->pValues[0].Type = DIRECTORY_ATTR_TYPE_OCTET_STREAM;

                break;

            default:

                dwError = LW_ERROR_DATA_ERROR;
                BAIL_ON_SAMDB_ERROR(dwError);

                break;
        }
    }

    *ppDirectoryEntries = pDirectoryEntries;
    *pdwNumEntries = dwNumEntries;

cleanup:

    return dwError;

error:

    *ppDirectoryEntries = NULL;
    *pdwNumEntries = 0;

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

    goto cleanup;
}
示例#13
0
DWORD
SamDbSearchObject_inlock(
    HANDLE            hDirectory,
    PWSTR             pwszBase,
    ULONG             ulScope,
    PWSTR             pwszFilter,
    PWSTR             wszAttributes[],
    ULONG             ulAttributesOnly,
    PDIRECTORY_ENTRY* ppDirectoryEntries,
    PDWORD            pdwNumEntries
    )
{
    DWORD dwError = 0;
    PSAM_DIRECTORY_CONTEXT pDirectoryContext = NULL;
    PSTR  pszQuery = NULL;
    BOOLEAN bMembersAttrExists = FALSE;
    PSAM_DB_COLUMN_VALUE pColumnValueList = NULL;
    PDIRECTORY_ENTRY pDirectoryEntries = NULL;
    DWORD            dwNumEntries = 0;

    pDirectoryContext = (PSAM_DIRECTORY_CONTEXT)hDirectory;

    dwError = SamDbBuildSqlQuery(
                    pDirectoryContext,
                    pwszFilter,
                    wszAttributes,
                    ulAttributesOnly,
                    &pszQuery,
                    &bMembersAttrExists,
                    &pColumnValueList);
    BAIL_ON_SAMDB_ERROR(dwError);

    dwError = SamDbSearchExecute(
                    pDirectoryContext,
                    pszQuery,
                    pColumnValueList,
                    ulAttributesOnly,
                    &pDirectoryEntries,
                    &dwNumEntries);
    BAIL_ON_SAMDB_ERROR(dwError);

    *ppDirectoryEntries = pDirectoryEntries;
    *pdwNumEntries = dwNumEntries;

cleanup:

    if (pColumnValueList)
    {
        SamDbFreeColumnValueList(pColumnValueList);
    }

    DIRECTORY_FREE_STRING(pszQuery);

    return(dwError);

error:

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

    goto cleanup;
}
NTSTATUS
SamrSrvQueryUserInfo(
    /* [in] */ handle_t hBinding,
    /* [in] */ ACCOUNT_HANDLE hUser,
    /* [in] */ UINT16 level,
    /* [out] */ UserInfo **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 wszAttrObjectSid[] = DS_ATTR_OBJECT_SID;
    WCHAR wszAttrSamAccountName[] = DS_ATTR_SAM_ACCOUNT_NAME;
    WCHAR wszAttrFullName[] = DS_ATTR_FULL_NAME;
    WCHAR wszAttrPrimaryGroup[] = DS_ATTR_PRIMARY_GROUP;
    WCHAR wszAttrDescription[] = DS_ATTR_DESCRIPTION;
    WCHAR wszAttrComment[] = DS_ATTR_COMMENT;
    WCHAR wszAttrCountryCode[] = DS_ATTR_COUNTRY_CODE;
    WCHAR wszAttrCodePage[] = DS_ATTR_CODE_PAGE;
    WCHAR wszAttrHomeDirectory[] = DS_ATTR_HOME_DIR;
    WCHAR wszAttrHomeDrive[] = DS_ATTR_HOME_DRIVE;
    WCHAR wszAttrLogonScript[] = DS_ATTR_LOGON_SCRIPT;
    WCHAR wszAttrProfilePath[] = DS_ATTR_PROFILE_PATH;
    WCHAR wszAttrWorkstations[]= DS_ATTR_WORKSTATIONS;
    WCHAR wszAttrParameters[] = DS_ATTR_PARAMETERS;
    WCHAR wszAttrLastLogon[] = DS_ATTR_LAST_LOGON;
    WCHAR wszAttrLastLogoff[] = DS_ATTR_LAST_LOGOFF;
    WCHAR wszAttrPasswordLastSet[] = DS_ATTR_PASSWORD_LAST_SET;
    WCHAR wszAttrAllowPasswordChange[] = DS_ATTR_ALLOW_PASSWORD_CHANGE;
    WCHAR wszAttrForcePasswordChange[] = DS_ATTR_FORCE_PASSWORD_CHANGE;
    WCHAR wszAttrLogonHours[] = DS_ATTR_LOGON_HOURS;
    WCHAR wszAttrBadPasswordCount[] = DS_ATTR_BAD_PASSWORD_COUNT;
    WCHAR wszAttrLogonCount[] = DS_ATTR_LOGON_COUNT;
    WCHAR wszAttrAccountFlags[] = DS_ATTR_ACCOUNT_FLAGS;
    WCHAR wszAttrAccountExpiry[] = DS_ATTR_ACCOUNT_EXPIRY;
    WCHAR wszAttrLmHash[] = DS_ATTR_LM_HASH;
    WCHAR wszAttrNtHash[] = DS_ATTR_NT_HASH;
    CHAR szAttrDn[] = DS_ATTR_DISTINGUISHED_NAME;
    DWORD dwScope = 0;
    PSTR pszDn = NULL;
    PWSTR pwszFilter = NULL;
    PDIRECTORY_ENTRY pEntry = NULL;
    DWORD dwEntriesNum = 0;
    UserInfo *pUserInfo = NULL;

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

    PWSTR wszAttributesLevel2[] = {
        wszAttrComment,
        wszAttrCountryCode,
        wszAttrCodePage,
        NULL
    };

    PWSTR wszAttributesLevel3[] = {
        wszAttrSamAccountName,
        wszAttrFullName,
        wszAttrObjectSid,
        wszAttrPrimaryGroup,
        wszAttrHomeDirectory,
        wszAttrHomeDrive,
        wszAttrLogonScript,
        wszAttrProfilePath,
        wszAttrWorkstations,
        wszAttrLastLogon,
        wszAttrLastLogoff,
        wszAttrPasswordLastSet,
        wszAttrAllowPasswordChange,
        wszAttrForcePasswordChange,
        wszAttrLogonHours,
        wszAttrBadPasswordCount,
        wszAttrLogonCount,
        wszAttrAccountFlags,
        NULL
    };

    PWSTR wszAttributesLevel4[] = {
        wszAttrLogonHours,
        NULL
    };

    PWSTR wszAttributesLevel5[] = {
        wszAttrSamAccountName,
        wszAttrFullName,
        wszAttrObjectSid,
        wszAttrPrimaryGroup,
        wszAttrHomeDirectory,
        wszAttrHomeDrive,
        wszAttrLogonScript,
        wszAttrProfilePath,
        wszAttrDescription,
        wszAttrWorkstations,
        wszAttrLastLogon,
        wszAttrLastLogoff,
        wszAttrLogonHours,
        wszAttrBadPasswordCount,
        wszAttrLogonCount,
        wszAttrPasswordLastSet,
        wszAttrAccountExpiry,
        wszAttrAccountFlags,
        NULL
    };

    PWSTR wszAttributesLevel6[] = {
        wszAttrSamAccountName,
        wszAttrFullName,
        NULL
    };

    PWSTR wszAttributesLevel7[] = {
        wszAttrSamAccountName,
        NULL
    };

    PWSTR wszAttributesLevel8[] = {
        wszAttrFullName,
        NULL
    };

    PWSTR wszAttributesLevel9[] = {
        wszAttrPrimaryGroup,
        NULL
    };

    PWSTR wszAttributesLevel10[] = {
        wszAttrHomeDirectory,
        wszAttrHomeDrive,
        NULL
    };

    PWSTR wszAttributesLevel11[] = {
        wszAttrLogonScript,
        NULL
    };

    PWSTR wszAttributesLevel12[] = {
        wszAttrProfilePath,
        NULL
    };

    PWSTR wszAttributesLevel13[] = {
        wszAttrDescription,
        NULL
    };

    PWSTR wszAttributesLevel14[] = {
        wszAttrWorkstations,
        NULL
    };

    PWSTR wszAttributesLevel16[] = {
        wszAttrAccountFlags,
        NULL
    };

    PWSTR wszAttributesLevel17[] = {
        wszAttrAccountExpiry,
        NULL
    };

    PWSTR wszAttributesLevel20[] = {
        wszAttrParameters,
        NULL
    };

    PWSTR wszAttributesLevel21[] = {
        wszAttrLastLogon,
        wszAttrLastLogoff,
        wszAttrPasswordLastSet,
        wszAttrAccountExpiry,
        wszAttrAllowPasswordChange,
        wszAttrForcePasswordChange,
        wszAttrSamAccountName,
        wszAttrFullName,
        wszAttrHomeDirectory,
        wszAttrHomeDrive,
        wszAttrLogonScript,
        wszAttrProfilePath,
        wszAttrDescription,
        wszAttrWorkstations,
        wszAttrComment,
        wszAttrParameters,
        wszAttrObjectSid,
        wszAttrPrimaryGroup,
        wszAttrAccountFlags,
        wszAttrLogonHours,
        wszAttrBadPasswordCount,
        wszAttrLogonCount,
        wszAttrCountryCode,
        wszAttrCodePage,
        wszAttrLmHash,
        wszAttrNtHash,
        NULL
    };

    PWSTR *pwszAttributes[] = {
        wszAttributesLevel1,
        wszAttributesLevel2,
        wszAttributesLevel3,
        wszAttributesLevel4,
        wszAttributesLevel5,
        wszAttributesLevel6,
        wszAttributesLevel7,
        wszAttributesLevel8,
        wszAttributesLevel9,
        wszAttributesLevel10,
        wszAttributesLevel11,
        wszAttributesLevel12,
        wszAttributesLevel13,
        wszAttributesLevel14,
        NULL,
        wszAttributesLevel16,
        wszAttributesLevel17,
        NULL,
        NULL,
        wszAttributesLevel20,
        wszAttributesLevel21
    };

    pAcctCtx = (PACCOUNT_CONTEXT)hUser;

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

    switch (level)
    {
    case 15:
    case 18:
    case 19:
        ntStatus = STATUS_INVALID_INFO_CLASS;
        break;

    default:
        ntStatus = STATUS_SUCCESS;
    }
    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);

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

    switch (level)
    {
    case 1:
    case 6:
    case 7:
    case 8:
    case 13:
        if (!(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_NAME_ETC) ||
            !(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_ATTRIBUTES))
        {
            ntStatus = STATUS_ACCESS_DENIED;
            BAIL_ON_NTSTATUS_ERROR(ntStatus);
        }
        break;

    case 2:
        if (!(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_LOCALE) ||
            !(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_ATTRIBUTES))
        {
            ntStatus = STATUS_ACCESS_DENIED;
            BAIL_ON_NTSTATUS_ERROR(ntStatus);
        }
        break;

    case 4:
    case 5:
    case 10:
    case 11:
    case 12:
    case 14:
    case 17:
        if (!(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_LOGONINFO) ||
            !(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_ATTRIBUTES))
        {
            ntStatus = STATUS_ACCESS_DENIED;
            BAIL_ON_NTSTATUS_ERROR(ntStatus);
        }
        break;

    case 3:
    case 9:
    case 16:
    case 20:
    case 21:
        if (!(pAcctCtx->dwAccessGranted & USER_ACCESS_GET_ATTRIBUTES))
        {
            ntStatus = STATUS_ACCESS_DENIED;
            BAIL_ON_NTSTATUS_ERROR(ntStatus);
        }
        break;
    }

    switch (level) {
    case 1:
        ntStatus = SamrFillUserInfo1(pEntry, pUserInfo);
        break;

    case 2:
        ntStatus = SamrFillUserInfo2(pEntry, pUserInfo);
        break;

    case 3:
        ntStatus = SamrFillUserInfo3(pAcctCtx, pEntry, pUserInfo);
        break;

    case 4:
        ntStatus = SamrFillUserInfo4(pEntry, pUserInfo);
        break;

    case 5:
        ntStatus = SamrFillUserInfo5(pEntry, pUserInfo);
        break;

    case 6:
        ntStatus = SamrFillUserInfo6(pEntry, pUserInfo);
        break;

    case 7:
        ntStatus = SamrFillUserInfo7(pEntry, pUserInfo);
        break;

    case 8:
        ntStatus = SamrFillUserInfo8(pEntry, pUserInfo);
        break;

    case 9:
        ntStatus = SamrFillUserInfo9(pEntry, pUserInfo);
        break;

    case 10:
        ntStatus = SamrFillUserInfo10(pEntry, pUserInfo);
        break;

    case 11:
        ntStatus = SamrFillUserInfo11(pEntry, pUserInfo);
        break;

    case 12:
        ntStatus = SamrFillUserInfo12(pEntry, pUserInfo);
        break;

    case 13:
        ntStatus = SamrFillUserInfo13(pEntry, pUserInfo);
        break;

    case 14:
        ntStatus = SamrFillUserInfo14(pEntry, pUserInfo);
        break;

    case 16:
        ntStatus = SamrFillUserInfo16(pEntry, pUserInfo);
        break;

    case 17:
        ntStatus = SamrFillUserInfo17(pEntry, pUserInfo);
        break;

    case 20:
        ntStatus = SamrFillUserInfo20(pEntry, pUserInfo);
        break;

    case 21:
        ntStatus = SamrFillUserInfo21(pAcctCtx, pEntry, pUserInfo);
        break;

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

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

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

    return ntStatus;

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

    *info = NULL;
    goto cleanup;
}
示例#15
0
DWORD
LocalFindObjectByName(
    HANDLE hProvider,
    PCSTR  pszName,
    PCSTR  pszDomainName,
    PDWORD pdwObjectClass,
    PWSTR* ppwszObjectDN
    )
{
    DWORD dwError = 0;
    PLOCAL_PROVIDER_CONTEXT pContext = (PLOCAL_PROVIDER_CONTEXT)hProvider;
    wchar16_t  wszAttrNameObjectClass[] = LOCAL_DIR_ATTR_OBJECT_CLASS;
    wchar16_t wszAttrNameDN[]           = LOCAL_DIR_ATTR_DISTINGUISHED_NAME;
    PWSTR wszAttrs[] =
    {
        &wszAttrNameObjectClass[0],
        &wszAttrNameDN[0],
        NULL
    };
    DWORD dwNumAttrs = (sizeof(wszAttrs)/sizeof(wszAttrs[0])) - 1;
    PDIRECTORY_ENTRY pEntries = NULL;
    PDIRECTORY_ENTRY pEntry = NULL;
    DWORD dwNumEntries = 0;
    PCSTR pszFilterTemplate =
                    LOCAL_DB_DIR_ATTR_SAM_ACCOUNT_NAME " = %Q" \
                    " AND " LOCAL_DB_DIR_ATTR_DOMAIN   " = %Q";
    PWSTR pwszFilter = NULL;
    PWSTR pwszObjectDN = NULL;
    DWORD dwObjectClass = LOCAL_OBJECT_CLASS_UNKNOWN;

    dwError = DirectoryAllocateWC16StringFilterPrintf(
                    &pwszFilter,
                    pszFilterTemplate,
                    pszName,
                    pszDomainName);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = DirectorySearch(
                    pContext->hDirectory,
                    NULL,
                    0,
                    pwszFilter,
                    wszAttrs,
                    FALSE,
                    &pEntries,
                    &dwNumEntries);
    BAIL_ON_LSA_ERROR(dwError);

    if (dwNumEntries == 0)
    {
        dwError = LW_ERROR_NO_SUCH_OBJECT;
    }
    else if (dwNumEntries != 1)
    {
        dwError = LW_ERROR_DATA_ERROR;
    }
    BAIL_ON_LSA_ERROR(dwError);

    pEntry = &pEntries[0];
    if (pEntry->ulNumAttributes != dwNumAttrs)
    {
        dwError = LW_ERROR_DATA_ERROR;
        BAIL_ON_LSA_ERROR(dwError);
    }

    dwError = LocalMarshalAttrToInteger(
                    pEntry,
                    &wszAttrNameObjectClass[0],
                    &dwObjectClass);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LocalMarshalAttrToUnicodeString(
                    pEntry,
                    &wszAttrNameDN[0],
                    &pwszObjectDN);
    BAIL_ON_LSA_ERROR(dwError);

    *pdwObjectClass = dwObjectClass;
    *ppwszObjectDN = pwszObjectDN;

cleanup:

    LW_SAFE_FREE_MEMORY(pwszFilter);

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

    return dwError;

error:

    *pdwObjectClass = LOCAL_OBJECT_CLASS_UNKNOWN;
    *ppwszObjectDN = NULL;

    LW_SAFE_FREE_MEMORY(pwszObjectDN);

    goto cleanup;
}
NTSTATUS
SamrSrvQuerySecurity(
    IN  handle_t                          hBinding,
    IN  void                             *hObject,
    IN  DWORD                             dwSecurityInfo,
    OUT PSAMR_SECURITY_DESCRIPTOR_BUFFER *ppSecDescBuf
    )
{
    PCSTR filterFormat = "%s=%Q";
    NTSTATUS ntStatus = STATUS_SUCCESS;
    DWORD dwError = ERROR_SUCCESS;
    PSAMR_GENERIC_CONTEXT pCtx = (PSAMR_GENERIC_CONTEXT)hObject;
    PDOMAIN_CONTEXT pDomCtx = NULL;
    PACCOUNT_CONTEXT pAcctCtx = NULL;
    PWSTR pwszDn = NULL;
    HANDLE hDirectory = NULL;
    PWSTR pwszBaseDn = NULL;
    DWORD dwScope = 0;
    WCHAR wszAttrSecDesc[] = DS_ATTR_SECURITY_DESCRIPTOR;
    CHAR szAttrDn[] = DS_ATTR_DISTINGUISHED_NAME;
    PSTR pszDn = NULL;
    PWSTR pwszFilter = NULL;
    PDIRECTORY_ENTRY pEntries = NULL;
    DWORD dwNumEntries = 0;
    PDIRECTORY_ENTRY pObjectEntry = NULL;
    POCTET_STRING pSecDescBlob = NULL;
    PSAMR_SECURITY_DESCRIPTOR_BUFFER pSecDescBuf = NULL;

    PWSTR wszAttributes[] = {
        wszAttrSecDesc,
        NULL
    };

    /*
     * Only querying security descriptor on an account is allowed
     */
    if (pCtx->Type == SamrContextAccount)
    {
        pAcctCtx    = (PACCOUNT_CONTEXT)hObject;
        pDomCtx     = pAcctCtx->pDomCtx;
        pwszDn      = pAcctCtx->pwszDn;
        hDirectory  = pDomCtx->pConnCtx->hDirectory;
    }
    else if (pCtx->Type == SamrContextConnect ||
             pCtx->Type == SamrContextDomain)
    {
        ntStatus = STATUS_ACCESS_DENIED;
    }
    else
    {
        ntStatus = STATUS_INVALID_HANDLE;
    }
    BAIL_ON_NTSTATUS_ERROR(ntStatus);

    /*
     * 1) READ_CONTROL right is required to read a security descriptor
     * 2) Querying SACL part of the SD is not permitted over rpc
     */
    if (!(pAcctCtx->dwAccessGranted & READ_CONTROL) ||
        dwSecurityInfo & SACL_SECURITY_INFORMATION)
    {
        ntStatus = STATUS_ACCESS_DENIED;
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    dwError = LwWc16sToMbs(pwszDn, &pszDn);
    BAIL_ON_LSA_ERROR(dwError);

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

    dwError = DirectorySearch(hDirectory,
                              pwszBaseDn,
                              dwScope,
                              pwszFilter,
                              wszAttributes,
                              FALSE,
                              &pEntries,
                              &dwNumEntries);
    BAIL_ON_LSA_ERROR(dwError);

    if (dwNumEntries == 0)
    {
        ntStatus = STATUS_INVALID_HANDLE;
    }
    else if (dwNumEntries > 1)
    {
        ntStatus = STATUS_INTERNAL_ERROR;
    }
    BAIL_ON_NTSTATUS_ERROR(ntStatus);

    pObjectEntry = &(pEntries[0]);

    dwError = DirectoryGetEntryAttrValueByName(
                              pObjectEntry,
                              wszAttrSecDesc,
                              DIRECTORY_ATTR_TYPE_NT_SECURITY_DESCRIPTOR,
                              &pSecDescBlob);
    BAIL_ON_LSA_ERROR(dwError);

    ntStatus = SamrSrvAllocateSecDescBuffer(
                              &pSecDescBuf,
                              (SECURITY_INFORMATION)dwSecurityInfo,
                              pSecDescBlob);
    BAIL_ON_NTSTATUS_ERROR(ntStatus);

    *ppSecDescBuf = pSecDescBuf;

cleanup:
    if (pEntries)
    {
        DirectoryFreeEntries(pEntries, dwNumEntries);
    }

    LW_SAFE_FREE_MEMORY(pszDn);
    LW_SAFE_FREE_MEMORY(pwszFilter);

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

    return ntStatus;

error:
    if (pSecDescBuf)
    {
        if (pSecDescBuf->pBuffer)
        {
            SamrSrvFreeMemory(pSecDescBuf->pBuffer);
        }

        SamrSrvFreeMemory(pSecDescBuf);
    }

    *ppSecDescBuf = NULL;

    goto cleanup;
}
示例#17
0
NTSTATUS
SamrSrvLookupDomain(
    /* [in] */ handle_t hBinding,
    /* [in] */ CONNECT_HANDLE hConn,
    /* [in] */ UNICODE_STRING *domain_name,
    /* [out] */ SID **ppSid
    )
{
    CHAR szDnToken[] = "DC";
    wchar_t wszFilter[] = L"%ws=%u AND %ws=\'%ws\'";
    NTSTATUS ntStatus = STATUS_SUCCESS;
    DWORD dwError = 0;
    PCONNECT_CONTEXT pConnCtx = NULL;
    PWSTR pwszBase = NULL;
    WCHAR wszAttrObjectClass[] = DS_ATTR_OBJECT_CLASS;
    WCHAR wszAttrDomain[] = DS_ATTR_DOMAIN;
    WCHAR wszAttrObjectSID[] = DS_ATTR_OBJECT_SID;
    DWORD dwObjectClass = DS_OBJECT_CLASS_DOMAIN;
    WCHAR wszBuiltinDomainName[] = SAMR_BUILTIN_DOMAIN_NAME;
    PWSTR pwszDomainName = NULL;
    DWORD dwBaseLen = 0;
    DWORD dwScope = 0;
    PWSTR pwszFilter = NULL;
    DWORD dwFilterLen = 0;
    PWSTR wszAttributes[2];
    PDIRECTORY_ENTRY pEntries = NULL;
    DWORD dwCount = 0;
    PDIRECTORY_ATTRIBUTE pAttr = NULL;
    PATTRIBUTE_VALUE pAttrVal = NULL;
    PSID pDomainSid = NULL;

    BAIL_ON_INVALID_PARAMETER(ppSid);
    BAIL_ON_INVALID_PARAMETER(domain_name);

    memset(wszAttributes, 0, sizeof(wszAttributes));

    pConnCtx = (PCONNECT_CONTEXT)hConn;

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

    ntStatus = SamrSrvGetFromUnicodeString(&pwszDomainName,
                                           domain_name);
    BAIL_ON_NO_MEMORY(pwszDomainName);

    if (!wc16scasecmp(pwszDomainName, wszBuiltinDomainName))
    {
        dwObjectClass = DS_OBJECT_CLASS_BUILTIN_DOMAIN;
    }

    dwBaseLen = domain_name->MaximumLength +
                ((sizeof(szDnToken) + 2) * sizeof(WCHAR));

    dwFilterLen = (sizeof(wszAttrObjectClass) - 1) +
                  10 +
                  (sizeof(wszAttrDomain) - 1) +
                  domain_name->Length +
                  sizeof(wszFilter);

    ntStatus = SamrSrvAllocateMemory(OUT_PPVOID(&pwszFilter),
                                     dwFilterLen);
    BAIL_ON_NTSTATUS_ERROR(ntStatus);

    if (sw16printfw(pwszFilter, dwFilterLen/sizeof(WCHAR), wszFilter,
                    wszAttrObjectClass, dwObjectClass,
                    wszAttrDomain, pwszDomainName) < 0)
    {
        ntStatus = LwErrnoToNtStatus(errno);
        BAIL_ON_NT_STATUS(ntStatus);
    }

    wszAttributes[0] = wszAttrObjectSID;
    wszAttributes[1] = NULL;

    dwError = DirectorySearch(pConnCtx->hDirectory,
                              pwszBase,
                              dwScope,
                              pwszFilter,
                              wszAttributes,
                              FALSE,
                              &pEntries,
                              &dwCount);
    BAIL_ON_LSA_ERROR(dwError);

    if (dwCount == 1) {
        dwError = DirectoryGetEntryAttributeSingle(pEntries,
                                                   &pAttr);
        BAIL_ON_LSA_ERROR(dwError);

        dwError = DirectoryGetAttributeValue(pAttr, &pAttrVal);
        BAIL_ON_LSA_ERROR(dwError);

        if (pAttrVal->Type == DIRECTORY_ATTR_TYPE_UNICODE_STRING) {
            ntStatus = SamrSrvAllocateSidFromWC16String(
                            &pDomainSid,
                            pAttrVal->data.pwszStringValue);
            BAIL_ON_NTSTATUS_ERROR(ntStatus);

        } else {
            ntStatus = STATUS_INTERNAL_ERROR;
            BAIL_ON_NTSTATUS_ERROR(ntStatus);
        }

    } else if (dwCount == 0) {
        ntStatus = STATUS_NO_SUCH_DOMAIN;
        BAIL_ON_NTSTATUS_ERROR(ntStatus);

    } else {
        ntStatus = STATUS_INTERNAL_ERROR;
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    *ppSid = pDomainSid;

cleanup:
    if (pwszBase) {
        SamrSrvFreeMemory(pwszBase);
    }

    if (pwszDomainName) {
        SamrSrvFreeMemory(pwszDomainName);
    }

    if (pwszFilter) {
        SamrSrvFreeMemory(pwszFilter);
    }

    if (pEntries) {
        DirectoryFreeEntries(pEntries, dwCount);
    }

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

    return ntStatus;

error:
    if (pDomainSid) {
        SamrSrvFreeMemory(&pDomainSid);
    }

    *ppSid = NULL;
    goto cleanup;
}
示例#18
0
DWORD
DirectoryAddObject(
    HANDLE        hDirectory,
    PWSTR         pwszObjectDN,
    DIRECTORY_MOD attributes[]
    )
{
    DWORD dwError = 0;
    PDIRECTORY_CONTEXT pContext = (PDIRECTORY_CONTEXT)hDirectory;
    PWSTR pwszBase = NULL;
    DWORD dwScope = 0;
    wchar_t wszFilterFmt[] = L"%ws='%ws'";
    size_t sDnLen = 0;
    DWORD dwFilterLen = 0;
    PWSTR pwszFilter = NULL;
    WCHAR wszAttrDn[] = DIRECTORY_ATTR_DISTINGUISHED_NAME;
    WCHAR wszAttrObjectClass[] = DIRECTORY_ATTR_OBJECT_CLASS;
    PDIRECTORY_ENTRY pEntries = NULL;
    PDIRECTORY_ENTRY pEntry = NULL;
    DWORD dwNumEntries = 0;
    DWORD dwObjectClass = 0;

    PWSTR wszAttributes[] = {
        wszAttrDn,
        wszAttrObjectClass,
        NULL
    };

    if (!pContext || !pContext->pProvider)
    {
        dwError = LW_ERROR_INVALID_PARAMETER;
        BAIL_ON_DIRECTORY_ERROR(dwError);
    }

    dwError = LwWc16sLen(pwszObjectDN, &sDnLen);
    BAIL_ON_DIRECTORY_ERROR(dwError);

    dwFilterLen = ((sizeof(wszFilterFmt)/sizeof(wszFilterFmt[0])) - 1) +
                   sizeof(wszAttrDn) +
                   (sizeof(WCHAR) * sDnLen);

    dwError = DirectoryAllocateMemory(dwFilterLen,
                                      OUT_PPVOID(&pwszFilter));
    BAIL_ON_DIRECTORY_ERROR(dwError);

    if (sw16printfw(pwszFilter, dwFilterLen, wszFilterFmt,
                    wszAttrDn,
                    pwszObjectDN) < 0)
    {
        dwError = LwErrnoToWin32Error(errno);
        BAIL_ON_DIRECTORY_ERROR(dwError);
    }

    dwError = DirectorySearch(hDirectory,
                              pwszBase,
                              dwScope,
                              pwszFilter,
                              wszAttributes,
                              FALSE,
                              &pEntries,
                              &dwNumEntries);
    BAIL_ON_DIRECTORY_ERROR(dwError);

    if (dwNumEntries == 1)
    {
        pEntry = &(pEntries[0]);

        dwError = DirectoryGetEntryAttrValueByName(
                              pEntry,
                              wszAttrObjectClass,
                              DIRECTORY_ATTR_TYPE_INTEGER,
                              &dwObjectClass);
        BAIL_ON_DIRECTORY_ERROR(dwError);

        switch (dwObjectClass)
        {
        case DIR_OBJECT_CLASS_USER:
            dwError = ERROR_USER_EXISTS;
            break;

        case DIR_OBJECT_CLASS_LOCAL_GROUP:
            dwError = ERROR_ALIAS_EXISTS;
            break;

        default:
            dwError = ERROR_ALREADY_EXISTS;
            break;
        }
        BAIL_ON_DIRECTORY_ERROR(dwError);
    }
    else if (dwNumEntries > 1)
    {
        dwError = LW_ERROR_SAM_DATABASE_ERROR;
        BAIL_ON_DIRECTORY_ERROR(dwError);
    }

    dwError = pContext->pProvider->pProviderFnTbl->pfnDirectoryAdd(
                    pContext->hBindHandle,
                    pwszObjectDN,
                    attributes);

error:
    if (pEntries)
    {
        DirectoryFreeEntries(pEntries, dwNumEntries);
    }

    DIRECTORY_FREE_MEMORY(pwszFilter);

    return dwError;
}
NTSTATUS
SamrSrvRemoveMemberFromForeignDomain(
    /* [in] */ handle_t hBinding,
    /* [in] */ DOMAIN_HANDLE hDomain,
    /* [in] */ PSID pSid
    )
{
    const DWORD dwAccessMask = ALIAS_ACCESS_REMOVE_MEMBER;
    const wchar_t wszDomainFilterFmt[] = L"%ws=%u";
    const wchar_t wszFilterFmt[] = L"%ws=%u AND %ws='%ws'";

    NTSTATUS ntStatus = STATUS_SUCCESS;
    DWORD dwError = ERROR_SUCCESS;
    PDOMAIN_CONTEXT pDomCtx = NULL;
    PCONNECT_CONTEXT pConnCtx = NULL;
    HANDLE hDirectory = NULL;
    DWORD i = 0;
    WCHAR wszAttrObjectClass[] = DS_ATTR_OBJECT_CLASS;
    WCHAR wszAttrObjectSid[] = DS_ATTR_OBJECT_SID;
    WCHAR wszAttrDomainName[] = DS_ATTR_DOMAIN;
    DWORD dwDomainObjectClass = DIR_OBJECT_CLASS_DOMAIN;
    DWORD dwDomainFilterLen = 0;
    PWSTR pwszDomainFilter = NULL;
    PWSTR pwszBase = NULL;
    DWORD dwScope = 0;
    PDIRECTORY_ENTRY pDomainEntries = NULL;
    DWORD dwNumDomainEntries = 0;
    PWSTR pwszDomainSid = NULL;
    PSID pDomainSid = NULL;
    PWSTR pwszDomainName = NULL;
    DWORD dwFilterLen = 0;
    PWSTR pwszFilter = NULL;
    DWORD dwObjectClass = DS_OBJECT_CLASS_LOCAL_GROUP;
    PDIRECTORY_ENTRY pEntries = NULL;
    DWORD dwEntriesNum = 0;
    PWSTR pwszAliasSid = NULL;
    PSID pAliasSid = NULL;
    DWORD dwRid = 0;
    ACCOUNT_HANDLE hAlias = NULL;
    PACCOUNT_CONTEXT pAcctCtx = NULL;

    PWSTR wszAttributes[] = {
        wszAttrObjectSid,
        NULL
    };

    pDomCtx = (PDOMAIN_CONTEXT)hDomain;

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

    pConnCtx       = pDomCtx->pConnCtx;
    pwszDomainName = pDomCtx->pwszDomainName;
    hDirectory     = pConnCtx->hDirectory;

    /*
     * Get the local domain SID and make sure we're not trying to
     * remove one of well-known SIDs from given domain
     */
    dwDomainFilterLen = ((sizeof(wszAttrObjectClass)/sizeof(WCHAR)) - 1) +
                        10 +
                        (sizeof(wszDomainFilterFmt)/
                         sizeof(wszDomainFilterFmt[0]));

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

    if (sw16printfw(pwszDomainFilter, dwDomainFilterLen, wszDomainFilterFmt,
                    wszAttrObjectClass,
                    dwDomainObjectClass) < 0)
    {
        ntStatus = LwErrnoToNtStatus(errno);
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    dwError = DirectorySearch(hDirectory,
                              pwszBase,
                              dwScope,
                              pwszDomainFilter,
                              wszAttributes,
                              FALSE,
                              &pDomainEntries,
                              &dwNumDomainEntries);
    BAIL_ON_LSA_ERROR(dwError);

    if (dwNumDomainEntries != 1)
    {
        ntStatus = STATUS_INTERNAL_ERROR;
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    dwError = DirectoryGetEntryAttrValueByName(
                                &(pDomainEntries[0]),
                                wszAttrObjectSid,
                                DIRECTORY_ATTR_TYPE_UNICODE_STRING,
                                &pwszDomainSid);
    BAIL_ON_LSA_ERROR(dwError);

    ntStatus = RtlAllocateSidFromWC16String(&pDomainSid,
                                            pwszDomainSid);
    BAIL_ON_NTSTATUS_ERROR(ntStatus);

    if (SamrSrvIsBuiltinAccount(pDomainSid,
                                pSid))
    {
        ntStatus = STATUS_SPECIAL_ACCOUNT;
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    dwFilterLen = ((sizeof(wszAttrObjectClass)/sizeof(WCHAR)) - 1) +
                  10 +
                  ((sizeof(wszAttrDomainName)/sizeof(WCHAR)) - 1) +
                  (wc16slen(pwszDomainName) + 1) +
                  (sizeof(wszFilterFmt)/sizeof(wszFilterFmt[0]));

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

    if (sw16printfw(pwszFilter, dwFilterLen, wszFilterFmt,
                    wszAttrObjectClass,
                    dwObjectClass,
                    wszAttrDomainName,
                    pwszDomainName) < 0)
    {
        ntStatus = LwErrnoToNtStatus(errno);
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    dwError = DirectorySearch(hDirectory,
                              pwszBase,
                              dwScope,
                              pwszFilter,
                              wszAttributes,
                              FALSE,
                              &pEntries,
                              &dwEntriesNum);
    BAIL_ON_LSA_ERROR(dwError);

    /*
     * Attempt to remove the SID from any alias it might be a member of
     */
    for (i = 0; i < dwEntriesNum; i++)
    {
        PDIRECTORY_ENTRY pEntry = &(pEntries[i]);

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

        ntStatus = RtlAllocateSidFromWC16String(&pAliasSid,
                                                pwszAliasSid);
        BAIL_ON_NTSTATUS_ERROR(ntStatus);

        dwRid = pAliasSid->SubAuthority[pAliasSid->SubAuthorityCount - 1];

        ntStatus = SamrSrvOpenAccount(hBinding,
                                      hDomain,
                                      dwAccessMask,
                                      dwRid,
                                      DS_OBJECT_CLASS_LOCAL_GROUP,
                                      &hAlias);
        BAIL_ON_NTSTATUS_ERROR(ntStatus);

        ntStatus = SamrSrvDeleteAliasMember(hBinding,
                                            hAlias,
                                            pSid);
        if (ntStatus == STATUS_NO_SUCH_MEMBER ||
            ntStatus == STATUS_MEMBER_NOT_IN_ALIAS)
        {
            /* Member is not in this alias so juts ignore it
               and try another one */
            ntStatus = STATUS_SUCCESS;
        }
        BAIL_ON_NTSTATUS_ERROR(ntStatus);

        ntStatus = SamrSrvClose(hBinding, &hAlias);
        BAIL_ON_NTSTATUS_ERROR(ntStatus);

        RTL_FREE(&pAliasSid);
    }

cleanup:
    LW_SAFE_FREE_MEMORY(pwszDomainFilter);
    LW_SAFE_FREE_MEMORY(pwszFilter);

    if (pDomainEntries)
    {
        DirectoryFreeEntries(pDomainEntries, dwNumDomainEntries);
    }

    RTL_FREE(&pDomainSid);

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

    if (hAlias)
    {
        pAcctCtx = (PACCOUNT_CONTEXT)hAlias;
        hAlias   = NULL;

        SamrSrvAccountContextFree(pAcctCtx);
    }

    RTL_FREE(&pAliasSid);

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

    return ntStatus;

error:
    goto cleanup;
}