Пример #1
0
NTSTATUS
LsaSrvAllocateSidFromWC16String(
    PSID *ppSid,
    PCWSTR pwszSidStr
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PSID pSid = NULL;
    ULONG ulSidSize = 0;
    PSID pSidCopy = NULL;

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

    ulSidSize = RtlLengthSid(pSid);
    ntStatus = LsaSrvAllocateMemory((void**)&pSidCopy,
                                  ulSidSize);
    BAIL_ON_NTSTATUS_ERROR(ntStatus);

    ntStatus = RtlCopySid(ulSidSize, pSidCopy, pSid);
    BAIL_ON_NTSTATUS_ERROR(ntStatus);

    *ppSid = pSidCopy;

cleanup:
    if (pSid) {
        RTL_FREE(&pSid);
    }

    return ntStatus;

error:
    if (pSidCopy) {
        LsaSrvFreeMemory(pSidCopy);
    }

    *ppSid = 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;
}
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;
}
Пример #4
0
DWORD
LocalMarshalAttrToSid(
    PDIRECTORY_ENTRY  pEntry,
    PWSTR             pwszAttrName,
    PSID             *ppSid
    )
{
    DWORD dwError = 0;
    NTSTATUS ntStatus = 0;
    PDIRECTORY_ATTRIBUTE pAttr = NULL;
    PATTRIBUTE_VALUE pAttrValue = NULL;
    PSID pSid = NULL;
    DWORD dwSidSize = 0;
    PSID pRetSid = NULL;

    BAIL_ON_INVALID_POINTER(pEntry);

    dwError = LocalFindAttribute(
                    pEntry,
                    pwszAttrName,
                    &pAttr);
    BAIL_ON_LSA_ERROR(dwError);

    if (pAttr->ulNumValues > 1)
    {
        dwError = LW_ERROR_DATA_ERROR;
    }
    else if (pAttr->ulNumValues == 0)
    {
        dwError = LW_ERROR_NO_ATTRIBUTE_VALUE;
    }
    else
    {
        pAttrValue = &pAttr->pValues[0];

        if (pAttrValue->Type == DIRECTORY_ATTR_TYPE_UNICODE_STRING)
        {
            ntStatus = RtlAllocateSidFromWC16String(
                                  &pSid,
                                  pAttrValue->data.pwszStringValue);
            BAIL_ON_NT_STATUS(ntStatus);
        }
        else if (pAttrValue->Type == DIRECTORY_ATTR_TYPE_ANSI_STRING)
        {
            ntStatus = RtlAllocateSidFromCString(
                                  &pSid,
                                  pAttrValue->data.pszStringValue);
            BAIL_ON_NT_STATUS(ntStatus);
        }
        else
        {
            dwError = LW_ERROR_INVALID_ATTRIBUTE_VALUE;
        }
    }
    BAIL_ON_LSA_ERROR(dwError);

    dwSidSize = RtlLengthSid(pSid);
    dwError = LwAllocateMemory(
                    dwSidSize,
                    OUT_PPVOID(&pRetSid));
    BAIL_ON_LSA_ERROR(dwError);

    ntStatus = RtlCopySid(
                    dwSidSize,
                    pRetSid,
                    pSid);
    BAIL_ON_NT_STATUS(ntStatus);

    *ppSid = pRetSid;

cleanup:
    RTL_FREE(&pSid);

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

    return dwError;

error:
    LW_SAFE_FREE_MEMORY(pRetSid);
    *ppSid = NULL;

    goto cleanup;
}