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; }
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 ) { const wchar_t wszFilterFmt[] = L"%ws='%ws'"; 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 wszAttrDn[] = DS_ATTR_DISTINGUISHED_NAME; WCHAR wszAttrSecDesc[] = DS_ATTR_SECURITY_DESCRIPTOR; size_t sDnLen = 0; DWORD dwFilterLen = 0; 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 = LwWc16sLen(pwszDn, &sDnLen); BAIL_ON_LSA_ERROR(dwError); dwFilterLen = ((sizeof(wszAttrDn)/sizeof(wszAttrDn[0])) - 1) + sDnLen + (sizeof(wszFilterFmt)/sizeof(wszFilterFmt[0])); dwError = LwAllocateMemory(sizeof(WCHAR) * dwFilterLen, OUT_PPVOID(&pwszFilter)); BAIL_ON_LSA_ERROR(dwError); if (sw16printfw(pwszFilter, dwFilterLen, wszFilterFmt, wszAttrDn, pwszDn) < 0) { ntStatus = LwErrnoToNtStatus(errno); BAIL_ON_NTSTATUS_ERROR(ntStatus); } 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(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 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 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; }
NTSTATUS NetrInitIdentityInfo( OUT PVOID *pIdentity, IN OUT PDWORD pdwOffset, IN OUT PDWORD pdwSpaceLeft, IN PCWSTR pwszDomain, IN PCWSTR pwszWorkstation, IN PCWSTR pwszAccount, IN UINT32 ParamControl, IN UINT32 LogonIdLow, IN UINT32 LogonIdHigh, IN OUT PDWORD pdwSize ) { NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = ERROR_SUCCESS; PVOID pBuffer = pIdentity; PWSTR pwszNbtWorkstation = NULL; size_t sNbtWorkstationLen = 0; BAIL_ON_INVALID_PTR(pdwOffset, ntStatus); BAIL_ON_INVALID_PTR(pwszWorkstation, ntStatus); BAIL_ON_INVALID_PTR(pwszAccount, ntStatus); BAIL_ON_INVALID_PTR(pdwSize, ntStatus); /* * Create "\\WORKSTATION" name */ dwError = LwWc16sLen(pwszWorkstation, &sNbtWorkstationLen); BAIL_ON_WIN_ERROR(dwError); ntStatus = NetrAllocateMemory(OUT_PPVOID(&pwszNbtWorkstation), sizeof(WCHAR) * (sNbtWorkstationLen + 3)); BAIL_ON_NT_STATUS(ntStatus); if (sw16printfw( pwszNbtWorkstation, sNbtWorkstationLen + 3, L"\\\\%ws", pwszWorkstation) < 0) { ntStatus = ErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(ntStatus); } LWBUF_ALLOC_UNICODE_STRING_FROM_WC16STR(pBuffer, pwszDomain); LWBUF_ALLOC_DWORD(pBuffer, ParamControl); LWBUF_ALLOC_DWORD(pBuffer, LogonIdLow); LWBUF_ALLOC_DWORD(pBuffer, LogonIdHigh); LWBUF_ALLOC_UNICODE_STRING_FROM_WC16STR(pBuffer, pwszAccount); LWBUF_ALLOC_UNICODE_STRING_FROM_WC16STR(pBuffer, pwszNbtWorkstation); cleanup: if (pwszNbtWorkstation) { NetrFreeMemory(pwszNbtWorkstation); } if (ntStatus == STATUS_SUCCESS && dwError != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(dwError); } return ntStatus; error: 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; }