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; }
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; }