static NTSTATUS SamrFillAliasInfo1( PDIRECTORY_ENTRY pEntry, DWORD dwNumMembers, AliasInfo *pInfo ) { NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = 0; AliasInfoAll *pInfoAll = NULL; WCHAR wszAttrSamAccountName[] = DS_ATTR_SAM_ACCOUNT_NAME; WCHAR wszAttrDescription[] = DS_ATTR_DESCRIPTION; PWSTR pwszName = NULL; PWSTR pwszDescription = NULL; pInfoAll = &(pInfo->all); /* name */ dwError = DirectoryGetEntryAttrValueByName(pEntry, wszAttrSamAccountName, DIRECTORY_ATTR_TYPE_UNICODE_STRING, &pwszName); BAIL_ON_LSA_ERROR(dwError); ntStatus = SamrSrvInitUnicodeString(&pInfoAll->name, pwszName); BAIL_ON_NTSTATUS_ERROR(ntStatus); /* num_members */ pInfoAll->num_members = dwNumMembers; /* description */ dwError = DirectoryGetEntryAttrValueByName(pEntry, wszAttrDescription, DIRECTORY_ATTR_TYPE_UNICODE_STRING, &pwszDescription); BAIL_ON_LSA_ERROR(dwError); ntStatus = SamrSrvInitUnicodeString(&pInfoAll->description, pwszDescription); BAIL_ON_NTSTATUS_ERROR(ntStatus); cleanup: return ntStatus; error: memset(pInfo, 0, sizeof(*pInfo)); goto cleanup; }
static NTSTATUS SamrFillAliasInfo3( PDIRECTORY_ENTRY pEntry, AliasInfo *pInfo ) { NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = 0; WCHAR wszAttrDescription[] = DS_ATTR_DESCRIPTION; PWSTR pwszDescription = NULL; /* name */ dwError = DirectoryGetEntryAttrValueByName(pEntry, wszAttrDescription, DIRECTORY_ATTR_TYPE_UNICODE_STRING, &pwszDescription); BAIL_ON_LSA_ERROR(dwError); ntStatus = SamrSrvInitUnicodeString(&pInfo->description, pwszDescription); BAIL_ON_NTSTATUS_ERROR(ntStatus); cleanup: return ntStatus; error: memset(pInfo, 0, sizeof(*pInfo)); goto cleanup; }
static NTSTATUS SamrFillAliasInfo2( PDIRECTORY_ENTRY pEntry, AliasInfo *pInfo ) { NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = 0; WCHAR wszAttrSamrAccountName[] = DS_ATTR_SAM_ACCOUNT_NAME; PWSTR pwszName = NULL; /* name */ dwError = DirectoryGetEntryAttrValueByName(pEntry, wszAttrSamrAccountName, DIRECTORY_ATTR_TYPE_UNICODE_STRING, &pwszName); BAIL_ON_LSA_ERROR(dwError); ntStatus = SamrSrvInitUnicodeString(&pInfo->name, pwszName); BAIL_ON_NTSTATUS_ERROR(ntStatus); cleanup: return ntStatus; error: memset(pInfo, 0, sizeof(*pInfo)); goto cleanup; }
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 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; }
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; }
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; }