Ejemplo n.º 1
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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;
}