Exemplo n.º 1
2
int main(void)
{
  // GetCurrentProcess cannot fail
  HANDLE hProcess = GetCurrentProcess();

  if (OpenProcessToken(hProcess, TOKEN_READ, &hProcess))
  {
    LUID seCreateSymbolicLinkPrivilege;

    if (LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &seCreateSymbolicLinkPrivilege))
    {
      DWORD length;

      printf("SeCreateSymbolicLinkPrivilege = %ld, %ld\n", seCreateSymbolicLinkPrivilege.HighPart, seCreateSymbolicLinkPrivilege.LowPart);

      if (!GetTokenInformation(hProcess, TokenPrivileges, NULL, 0, &length))
      {
        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
        {
          TOKEN_PRIVILEGES* privileges = (TOKEN_PRIVILEGES*)malloc(length);
          if (GetTokenInformation(hProcess, TokenPrivileges, privileges, length, &length))
          {
            BOOL found = FALSE;
            DWORD count = privileges->PrivilegeCount;

            printf("User has %ld privileges\n", count);

            if (count > 0)
            {
              LUID_AND_ATTRIBUTES* privs = privileges->Privileges;
              while (count-- > 0 && !luid_eq(privs->Luid, seCreateSymbolicLinkPrivilege))
                privs++;
              found = (count > 0);
            }

            printf("User does%s have the SeCreateSymbolicLinkPrivilege\n", (found ? "" : "n't"));
          }
          else
          {
            fprintf(stderr, "Second GetTokenInformation failed\n");
          }

          free(privileges);
        }
        else
        {
          fprintf(stderr, "First GetTokenInformation failed\n");
        }
      }
      else
      {
        fprintf(stderr, "Impossible output from GetTokenInformation\n");
      }
    }
    else
    {
      fprintf(stderr, "LookupPrivilegeValue failed\n");
    }

    CloseHandle(hProcess);
  }
  else
  {
    fprintf(stderr, "OpenProcessToken failed\n");
  }

  LSA_HANDLE hPolicy;
  NTSTATUS r;
  LSA_OBJECT_ATTRIBUTES attributes = {0, NULL, NULL, 0, NULL, NULL};
  attributes.Length = sizeof(attributes);

  LUID seCreateSymbolicLinkPrivilege;

  if (LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &seCreateSymbolicLinkPrivilege))
  {
    // POLICY_LOOKUP_NAMES: LsaLookupNames2, LsaEnumerateAccountRights, LsaLookupSids, LsaAddAccountRights
    // POLICY_VIEW_LOCAL_INFORMATION: LsaEnumerateAccountsWithUserRight
    // Elevation: LsaEnumerateAccountRights, LsaEnumerateAccountsWithUserRight, LsaRemoveAccountRights, LsaAddAccountRights
    if (NT_SUCCESS(r = LsaOpenPolicy(NULL, &attributes, POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION, &hPolicy)))
    {
      LSA_REFERENCED_DOMAIN_LIST* referencedDomains;
      LSA_TRANSLATED_SID2* sids;
      LSA_UNICODE_STRING name;
      name.Buffer = L"Users";
      name.Length = wcslen(name.Buffer) * sizeof(WCHAR);
      name.MaximumLength = name.Length + sizeof(WCHAR);
  
      if (NT_SUCCESS(r = LsaLookupNames2(hPolicy, LSA_LOOKUP_ISOLATED_AS_LOCAL, 1, &name, &referencedDomains, &sids)))
      {
        LSA_UNICODE_STRING* rights;
        ULONG count;
        LsaFreeMemory(referencedDomains);

        if (NT_SUCCESS(r = LsaEnumerateAccountRights(hPolicy, sids->Sid, &rights, &count)))
        {
          LSA_UNICODE_STRING* right = rights;
          printf("%ld right%s found\n", count, PLURAL(count));
          while (count-- > 0)
          {
            printf("  %.*S\n", right->Length / 2, right->Buffer);
            right++;
          }

          LsaFreeMemory(rights);

          LSA_ENUMERATION_INFORMATION* allSidsRaw;
          LSA_UNICODE_STRING lsaCreateSymbolicLinkPrivilege;
          lsaCreateSymbolicLinkPrivilege.Buffer = SE_CREATE_SYMBOLIC_LINK_NAME;
          lsaCreateSymbolicLinkPrivilege.Length = wcslen(lsaCreateSymbolicLinkPrivilege.Buffer) * sizeof(WCHAR);
          lsaCreateSymbolicLinkPrivilege.MaximumLength = lsaCreateSymbolicLinkPrivilege.Length + sizeof(WCHAR);
          if (NT_SUCCESS(r = LsaEnumerateAccountsWithUserRight(hPolicy, &lsaCreateSymbolicLinkPrivilege, (void**)&allSidsRaw, &count)))
          {
            LSA_ENUMERATION_INFORMATION* sid = allSidsRaw;
            PSID* allSids;
            PSID* p;
            PLSA_TRANSLATED_NAME names;
            ULONG i = count;

            printf("%ld SID%s found\n", count, PLURAL(count));
            p = allSids = (PSID*)malloc(count * sizeof(PSID));

            while (i-- > 0)
              *p++ = (sid++)->Sid;

            if (NT_SUCCESS(r = LsaLookupSids(hPolicy, count, allSids, &referencedDomains, &names)))
            {
              PLSA_TRANSLATED_NAME name = names;
              BOOL usersAssigned = FALSE;

              LsaFreeMemory(referencedDomains);

              while (count-- > 0)
              {
                LPTSTR sidString;
                USHORT len = name->Name.Length / 2;
                ConvertSidToStringSid(*allSids++, &sidString);
                printf("  %.*S (%S)\n", len, name->Name.Buffer, sidString);
                usersAssigned |= (len > 4 && !wcsncmp(L"Users", name->Name.Buffer, len));
                name++;
                LocalFree(sidString);
              }

              printf("Users had%s got SeCreateSymbolicLinkPrivilege\n", (usersAssigned ? "" : "n't"));
              if (usersAssigned)
              {
                if (!NT_SUCCESS(r = LsaRemoveAccountRights(hPolicy, sids->Sid, FALSE, &lsaCreateSymbolicLinkPrivilege, 1)))
                {
                  fprintf(stderr, "Lsa failed with code %x\n", r);
                }
              }
              else
              {
                if (!NT_SUCCESS(r = LsaAddAccountRights(hPolicy, sids->Sid, &lsaCreateSymbolicLinkPrivilege, 1)))
                {
                  fprintf(stderr, "LsaAddAccountRights failed with code %x\n", r);
                }
              }

              LsaFreeMemory(names);
            }
            else
            {
              fprintf(stderr, "LsaLookupSids2 failed with code %x\n", r);
            }
              
            LsaFreeMemory(allSidsRaw);
            free(allSids);
          }
          else
          {
            fprintf(stderr, "LsaEnumerateAccountsWithUserRight failed with code %x\n", r);
          }
        }
        else
        {
          fprintf(stderr, "LsaEnumerateAccountRights failed with code %x\n", r);
        }

        LsaFreeMemory(sids);
      }
      else
      {
        fprintf(stderr, "LsaLookupNames2 failed with code %x\n", r);
      }
  
      LsaClose(hPolicy);
    }
    else
    {
      fprintf(stderr, "LsaOpenPolicy failed with code %x\n", r);
    }
  }
  else
  {
    fprintf(stderr, "LookupPrivilegeValue failed\n");
  }
}
Exemplo n.º 2
0
BOOL lsa_account_from_sid(LSA_HANDLE lsa_handle, PSID sid, PLSA_ACCOUNT account)
{
  LSA_REFERENCED_DOMAIN_LIST*   domain = 0;
  LSA_TRANSLATED_NAME*          name = 0;
  NTSTATUS                      nt_status;
  BOOL                          success;

  if (sid == NULL)
    return print_error(L"Error in lsa_account_from_sid: sid is NULL.\n");

  if (account == NULL)
    return print_error(L"Error in lsa_account_from_sid: account is NULL.\n");

  nt_status = LsaLookupSids(lsa_handle, 1, &sid, &domain, &name);
  if (nt_status!=STATUS_SUCCESS)
    return lsa_error(nt_status, L"LsaLookupSids");

  account->use = name->Use;

  if (name->DomainIndex >= 0 && name->DomainIndex < domain->Entries)
    success = copy_lsa_string_to_wchar(account->domain, sizeof(account->domain), &domain->Domains[name->DomainIndex].Name);
  else
    success = copy_lsa_string_to_wchar(account->domain, sizeof(account->domain), NULL);

  success &= copy_lsa_string_to_wchar(account->name, sizeof(account->name), &name->Name);

  LsaFreeMemory(domain);
  LsaFreeMemory(name);

  return success;
}
Exemplo n.º 3
0
Arquivo: lsa.c Projeto: Jactry/wine
static void test_LsaLookupSids(void)
{
    LSA_REFERENCED_DOMAIN_LIST *list;
    LSA_OBJECT_ATTRIBUTES attrs;
    LSA_TRANSLATED_NAME *names;
    LSA_HANDLE policy;
    TOKEN_USER *user;
    NTSTATUS status;
    HANDLE token;
    DWORD size;
    BOOL ret;
    PSID sid;

    memset(&attrs, 0, sizeof(attrs));
    attrs.Length = sizeof(attrs);

    status = LsaOpenPolicy(NULL, &attrs, POLICY_LOOKUP_NAMES, &policy);
    ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);

    ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
    ok(ret, "got %d\n", ret);

    ret = GetTokenInformation(token, TokenUser, NULL, 0, &size);
    ok(!ret, "got %d\n", ret);

    user = HeapAlloc(GetProcessHeap(), 0, size);
    ret = GetTokenInformation(token, TokenUser, user, size, &size);
    ok(ret, "got %d\n", ret);

    status = LsaLookupSids(policy, 1, &user->User.Sid, &list, &names);
    ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);

    ok(list->Entries > 0, "got %d\n", list->Entries);
    if (list->Entries)
    {
       ok((char*)list->Domains - (char*)list > 0, "%p, %p\n", list, list->Domains);
       ok((char*)list->Domains[0].Sid - (char*)list->Domains > 0, "%p, %p\n", list->Domains, list->Domains[0].Sid);
       ok(list->Domains[0].Name.MaximumLength > list->Domains[0].Name.Length, "got %d, %d\n", list->Domains[0].Name.MaximumLength,
           list->Domains[0].Name.Length);
    }

    LsaFreeMemory(names);
    LsaFreeMemory(list);

    HeapFree(GetProcessHeap(), 0, user);

    CloseHandle(token);

    ret = ConvertStringSidToSidA("S-1-1-0", &sid);
    ok(ret == TRUE, "ConvertStringSidToSidA returned false\n");

    status = LsaLookupSids(policy, 1, &sid, &list, &names);
    ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);

    ok(list->Entries > 0, "got %d\n", list->Entries);

    if (list->Entries)
    {
       ok((char*)list->Domains - (char*)list > 0, "%p, %p\n", list, list->Domains);
       ok((char*)list->Domains[0].Sid - (char*)list->Domains > 0, "%p, %p\n", list->Domains, list->Domains[0].Sid);
       ok(list->Domains[0].Name.MaximumLength > list->Domains[0].Name.Length, "got %d, %d\n", list->Domains[0].Name.MaximumLength,
           list->Domains[0].Name.Length);
       ok(list->Domains[0].Name.Buffer != NULL, "domain[0] name buffer is null\n");
    }

    LsaFreeMemory(names);
    LsaFreeMemory(list);

    FreeSid(sid);

    status = LsaClose(policy);
    ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
}
Exemplo n.º 4
0
static
NTSTATUS
LsaSrvLookupForeignDomainSids(
    PPOLICY_CONTEXT        pPolCtx,
    PACCOUNT_SIDS          pAccountSids,
    DWORD                  dwLevel,
    RefDomainList         *pDomains,
    TranslatedNameArray2  *pNamesArray
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    DWORD dwError = ERROR_SUCCESS;
    PDOMAIN_ENTRY pDomEntry = NULL;
    handle_t hLsaBinding = NULL;
    POLICY_HANDLE hDcPolicy = NULL;
    PSID pDomSid = NULL;
    DWORD iDomSid = 0;
    DWORD iResolvSid = 0;
    DWORD iSid = 0;
    DWORD dwDomIndex = 0;
    ACCOUNT_SIDS ForeignSids = {0};
    SID_ARRAY Sids = {0};
    RefDomainList *pForeignDomains = NULL;
    TranslatedName *pForeignNames = NULL;
    DWORD dwForeignNamesCount = 0;
    DWORD iDomain = 0;
    DWORD i = 0;
    PSID pSid = NULL;
    DWORD dwSidIndex = 0;

    /*
     * Allocate enough space for potential sequence of sid lookups
     */
    dwError = LwAllocateMemory(
                    sizeof(ForeignSids.ppSids[0]) * pAccountSids->dwCount,
                    OUT_PPVOID(&ForeignSids.ppSids));
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwAllocateMemory(
                    sizeof(ForeignSids.pdwIndices[0]) * pAccountSids->dwCount,
                    OUT_PPVOID(&ForeignSids.pdwIndices));
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwAllocateMemory(
                    sizeof(Sids.pSids[0]) * pAccountSids->dwCount,
                    OUT_PPVOID(&Sids.pSids));
    BAIL_ON_LSA_ERROR(dwError);

    while (iDomSid < pAccountSids->dwCount)
    {
        ntStatus = RtlDuplicateSid(&pDomSid,
                                   pAccountSids->ppSids[iDomSid]);
        BAIL_ON_NTSTATUS_ERROR(ntStatus);

        pDomSid->SubAuthorityCount--;
        pDomSid->SubAuthority[pDomSid->SubAuthorityCount] = 0;

        iResolvSid = 0;

        for (iSid = iDomSid; iSid < pAccountSids->dwCount; iSid++)
        {
            pSid       = pAccountSids->ppSids[iSid];
            dwSidIndex = pAccountSids->pdwIndices[iSid];

            if (RtlIsPrefixSid(pDomSid, pSid))
            {
                ntStatus = RtlDuplicateSid(
                                    &(ForeignSids.ppSids[iResolvSid]),
                                    pSid);
                BAIL_ON_NTSTATUS_ERROR(ntStatus);

                ForeignSids.pdwIndices[iResolvSid] = dwSidIndex;

                ForeignSids.dwCount = ++iResolvSid;

                /*
                 * Free the sid so it's not looked up again
                 */
                RTL_FREE(&pAccountSids->ppSids[iSid]);
                pAccountSids->ppSids[iSid] = NULL;
                pSid = NULL;
            }
        }

        for (i = 0; i < ForeignSids.dwCount; i++)
        {
            Sids.pSids[i].pSid = ForeignSids.ppSids[i];
        }
        Sids.dwNumSids = ForeignSids.dwCount;

        ntStatus = LsaSrvConnectDomainBySid(pPolCtx,
                                            pDomSid,
                                            &pDomEntry);
        BAIL_ON_NTSTATUS_ERROR(ntStatus);

        hLsaBinding = pDomEntry->hLsaBinding;
        hDcPolicy   = pDomEntry->hPolicy;

        ntStatus = LsaLookupSids(hLsaBinding,
                                 hDcPolicy,
                                 &Sids,
                                 &pForeignDomains,
                                 &pForeignNames,
                                 dwLevel,
                                 &dwForeignNamesCount);
        if (ntStatus == STATUS_SUCCESS ||
            ntStatus == STATUS_SOME_NOT_MAPPED)
        {
            for (iDomain = 0; iDomain < pForeignDomains->count; iDomain++)
            {
                LsaDomainInfo *pSrcDomInfo = NULL;
                LsaDomainInfo *pDstDomInfo = NULL;

                dwDomIndex  = pDomains->count;
                pSrcDomInfo = &(pForeignDomains->domains[iDomain]);
                pDstDomInfo = &(pDomains->domains[dwDomIndex]);

                ntStatus = LsaSrvDuplicateUnicodeStringEx(&pDstDomInfo->name,
                                                          &pSrcDomInfo->name);
                BAIL_ON_NTSTATUS_ERROR(ntStatus);

                ntStatus = LsaSrvDuplicateSid(&pDstDomInfo->sid,
                                              pSrcDomInfo->sid);
                BAIL_ON_NTSTATUS_ERROR(ntStatus);

                for (iSid = 0; iSid < dwForeignNamesCount; iSid++)
                {
                    DWORD iTransName          = ForeignSids.pdwIndices[iSid];
                    TranslatedName *pSrcName  = &(pForeignNames[iSid]);
                    TranslatedName2 *pDstName = &(pNamesArray->names[iTransName]);

                    if (iDomain != pSrcName->sid_index)
                    {
                        continue;
                    }

                    ntStatus = LsaSrvDuplicateUnicodeString(&pDstName->name,
                                                            &pSrcName->name);
                    BAIL_ON_NTSTATUS_ERROR(ntStatus);

                    pDstName->type      = pSrcName->type;
                    pDstName->sid_index = dwDomIndex;
                    pDstName->unknown1  = 0;
                }

                pDomains->count  = (++dwDomIndex);
            }

            pNamesArray->count += dwForeignNamesCount;
        }
        else if (ntStatus == STATUS_NONE_MAPPED)
        {
            for (i = 0; i < ForeignSids.dwCount; i++)
            {
                DWORD iTransName = ForeignSids.pdwIndices[i];
                TranslatedName2 *pDstName = &(pNamesArray->names[iTransName]);

                pDstName->type      = SID_TYPE_UNKNOWN;
                pDstName->sid_index = 0;
                pDstName->unknown1  = 0;
            }

            pNamesArray->count += ForeignSids.dwCount;
        }
        else
        {
            BAIL_ON_NTSTATUS_ERROR(ntStatus);
        }

        /*
         * Free the sids array before the next round of lookup.
         * The entire allocated space (i.e. as big as pAccountSids)
         * is cleaned up.
         */
        for (i = 0; i < pAccountSids->dwCount; i++)
        {
            RTL_FREE(&(ForeignSids.ppSids[i]));
            ForeignSids.ppSids[i]     = NULL;
            Sids.pSids[i].pSid        = NULL;
            ForeignSids.pdwIndices[i] = -1;
        }
        Sids.dwNumSids = 0;

        if (pDomEntry)
        {
            LsaSrvDomainEntryFree(&pDomEntry);
        }

        if (pForeignDomains)
        {
            LsaRpcFreeMemory(pForeignDomains);
            pForeignDomains = NULL;
        }

        if (pForeignNames)
        {
            LsaRpcFreeMemory(pForeignNames);
            pForeignNames = NULL;
        }

        RTL_FREE(&pDomSid);

        /*
         * Find another domain name (first name that hasn't
         * been nulled out)
         */
        iDomSid = 0;
        while (iDomSid < pAccountSids->dwCount &&
               pAccountSids->ppSids[iDomSid] == NULL)
        {
            iDomSid++;
        }
    }

    /*
     * Lookup status is checked later by the caller
     * so avoid bailing accidentally because other lookups
     * may be successful
     */
    if (ntStatus == STATUS_SOME_NOT_MAPPED ||
        ntStatus == STATUS_NONE_MAPPED)
    {
        ntStatus = STATUS_SUCCESS;
    }

cleanup:
    for (i = 0; i < pAccountSids->dwCount; i++)
    {
        RTL_FREE(&(ForeignSids.ppSids[i]));
    }

    LW_SAFE_FREE_MEMORY(ForeignSids.ppSids);
    LW_SAFE_FREE_MEMORY(ForeignSids.pdwIndices);
    LW_SAFE_FREE_MEMORY(Sids.pSids);

    if (pDomEntry)
    {
        LsaSrvDomainEntryFree(&pDomEntry);
    }

    if (pForeignDomains)
    {
        LsaRpcFreeMemory(pForeignDomains);
    }

    if (pForeignNames)
    {
        LsaRpcFreeMemory(pForeignNames);
    }

    RTL_FREE(&pDomSid);

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

    return ntStatus;

error:
    goto cleanup;
}
Exemplo n.º 5
0
static
NTSTATUS
LsaSrvLookupDomainSids(
    PPOLICY_CONTEXT        pPolCtx,
    PACCOUNT_SIDS          pAccountSids,
    DWORD                  dwLevel,
    RefDomainList         *pDomains,
    TranslatedNameArray2  *pNamesArray
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    DWORD dwError = ERROR_SUCCESS;
    PDOMAIN_ENTRY pDomEntry = NULL;
    handle_t hLsaBinding = NULL;
    POLICY_HANDLE hDcPolicy = NULL;
    DWORD dwDomIndex = 0;
    SID_ARRAY Sids = {0};
    RefDomainList *pDomain = NULL;
    TranslatedName *pDomainNames = NULL;
    DWORD dwDomainNamesCount = 0;
    DWORD iDomain = 0;
    DWORD iSid = 0;
    DWORD i = 0;

    ntStatus = LsaSrvGetDomainBySid(pPolCtx,
                                    pPolCtx->pDomainSid,
                                    &pDomEntry);
    if (ntStatus == STATUS_NO_SUCH_DOMAIN)
    {
        ntStatus = LsaSrvConnectDomainBySid(pPolCtx,
                                           pPolCtx->pDomainSid,
                                           &pDomEntry);
        BAIL_ON_NTSTATUS_ERROR(ntStatus);

        hLsaBinding = pDomEntry->hLsaBinding;
        hDcPolicy   = pDomEntry->hPolicy;
    }
    else if (ntStatus == STATUS_SUCCESS)
    {
        hLsaBinding = pDomEntry->hLsaBinding;
        hDcPolicy   = pDomEntry->hPolicy;
    }
    else
    {
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    Sids.dwNumSids = pAccountSids->dwCount;

    dwError = LwAllocateMemory(sizeof(Sids.pSids[0]) * Sids.dwNumSids,
                               OUT_PPVOID(&Sids.pSids));
    BAIL_ON_LSA_ERROR(dwError);

    for (i = 0; i < Sids.dwNumSids; i++)
    {
        Sids.pSids[i].pSid = pAccountSids->ppSids[i];
    }

    ntStatus = LsaLookupSids(hLsaBinding,
                             hDcPolicy,
                             &Sids,
                             &pDomain,
                             &pDomainNames,
                             dwLevel,
                             &dwDomainNamesCount);
    if (ntStatus == STATUS_SUCCESS ||
        ntStatus == STATUS_SOME_NOT_MAPPED)
    {
        for (iDomain = 0; iDomain < pDomain->count; iDomain++)
        {
            LsaDomainInfo *pSrcDomInfo = NULL;
            LsaDomainInfo *pDstDomInfo = NULL;

            dwDomIndex  = pDomains->count;
            pSrcDomInfo = &(pDomain->domains[iDomain]);
            pDstDomInfo = &(pDomains->domains[dwDomIndex]);

            ntStatus = LsaSrvDuplicateUnicodeStringEx(&pDstDomInfo->name,
                                                      &pSrcDomInfo->name);
            BAIL_ON_NTSTATUS_ERROR(ntStatus);

            ntStatus = LsaSrvDuplicateSid(&pDstDomInfo->sid,
                                          pSrcDomInfo->sid);
            BAIL_ON_NTSTATUS_ERROR(ntStatus);

            for (iSid = 0; iSid < dwDomainNamesCount; iSid++)
            {
                DWORD iTransName = pAccountSids->pdwIndices[iSid];
                TranslatedName *pSrcName = &(pDomainNames[iSid]);
                TranslatedName2 *pDstName = &(pNamesArray->names[iTransName]);

                if (iDomain != pSrcName->sid_index)
                {
                    continue;
                }

                ntStatus = LsaSrvDuplicateUnicodeString(&pDstName->name,
                                                        &pSrcName->name);
                BAIL_ON_NTSTATUS_ERROR(ntStatus);

                pDstName->type      = pSrcName->type;
                pDstName->sid_index = dwDomIndex;
                pDstName->unknown1  = 0;
            }

            pDomains->count  = (++dwDomIndex);
        }

        pNamesArray->count += dwDomainNamesCount;
    }
    else if (ntStatus == STATUS_NONE_MAPPED)
    {
        for (i = 0; i < pAccountSids->dwCount; i++)
        {
            DWORD iTransName = pAccountSids->pdwIndices[i];
            TranslatedName2 *pDstName = &(pNamesArray->names[iTransName]);

            pDstName->type      = SID_TYPE_UNKNOWN;
            pDstName->sid_index = 0;
            pDstName->unknown1  = 0;
        }

        pNamesArray->count += pAccountSids->dwCount;
    }
    else
    {
        BAIL_ON_NTSTATUS_ERROR(ntStatus);
    }

    /*
     * Lookup status is checked later by the caller
     * so avoid bailing accidentally because other lookups
     * may be successful
     */
    if (ntStatus == STATUS_SOME_NOT_MAPPED ||
        ntStatus == STATUS_NONE_MAPPED)
    {
        ntStatus = STATUS_SUCCESS;
    }

cleanup:
    LW_SAFE_FREE_MEMORY(Sids.pSids);

    if (pDomEntry)
    {
        LsaSrvDomainEntryFree(&pDomEntry);
    }

    if (pDomain)
    {
        LsaRpcFreeMemory(pDomain);
    }

    if (pDomainNames)
    {
        LsaRpcFreeMemory(pDomainNames);
    }

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

    return ntStatus;

error:
    goto cleanup;
}
NET_API_STATUS
NetLocalGroupGetMembers(
    IN  PCWSTR  pwszHostname,
    IN  PCWSTR  pwszAliasname,
    IN  DWORD   dwLevel,
    OUT PVOID  *ppBuffer,
    IN  DWORD   dwMaxBufferSize,
    OUT PDWORD  pdwNumEntries,
    OUT PDWORD  pdwTotalEntries,
    OUT PDWORD  pdwResume
    )
{
    const DWORD dwLsaAccessFlags = LSA_ACCESS_LOOKUP_NAMES_SIDS;
    const DWORD dwAliasAccessFlags = ALIAS_ACCESS_GET_MEMBERS;
    const WORD wLookupLevel = 1;

    NTSTATUS status = STATUS_SUCCESS;
    WINERROR err = ERROR_SUCCESS;
    PNET_CONN pConn = NULL;
    SAMR_BINDING hSamrBinding = NULL;
    LSA_BINDING hLsaBinding = NULL;
    ACCOUNT_HANDLE hAlias = NULL;
    PSID *ppSids = NULL;
    DWORD dwInfoLevelSize = 0;
    DWORD dwTotalNumEntries = 0;
    DWORD dwResume = 0;
    DWORD dwAliasRid = 0;
    DWORD i = 0;
    DWORD dwNumSids = 0;
    DWORD dwCount = 0;
    POLICY_HANDLE hLsaPolicy = NULL;
    SID_ARRAY Sids = {0};
    RefDomainList *pDomains = NULL;
    TranslatedName *pNames = NULL;
    PNET_RESOLVED_NAME pResolvedNames = NULL;
    PVOID pSourceBuffer = NULL;
    PVOID pBuffer = NULL;
    PVOID pBufferCursor = NULL;
    DWORD dwSize = 0;
    DWORD dwTotalSize = 0;
    DWORD dwNumEntries = 0;
    DWORD dwSpaceAvailable = 0;
    PIO_CREDS pCreds = NULL;
    NET_VALIDATION_LEVEL eValidation = NET_VALIDATION_NONE;

    BAIL_ON_INVALID_PTR(pwszAliasname, err);
    BAIL_ON_INVALID_PTR(ppBuffer, err);
    BAIL_ON_INVALID_PTR(pdwNumEntries, err);
    BAIL_ON_INVALID_PTR(pdwTotalEntries, err);
    BAIL_ON_INVALID_PTR(pdwResume, err);

    switch (dwLevel)
    {
    case 0:
        dwInfoLevelSize = sizeof(LOCALGROUP_MEMBERS_INFO_0);
        break;

    case 3:
        dwInfoLevelSize = sizeof(LOCALGROUP_MEMBERS_INFO_3);
        break;

    case 1:
    case 2:
    default:
        err = ERROR_INVALID_LEVEL;
        BAIL_ON_WIN_ERROR(err);
    }

    dwResume = *pdwResume;

    status = LwIoGetActiveCreds(NULL, &pCreds);
    BAIL_ON_NT_STATUS(status);

    status = NetConnectSamr(&pConn,
                            pwszHostname,
                            0,
                            0,
                            pCreds);
    BAIL_ON_NT_STATUS(status);

    hSamrBinding = pConn->Rpc.Samr.hBinding;

    status = NetOpenAlias(pConn,
                          pwszAliasname,
                          dwAliasAccessFlags,
                          &hAlias,
                          &dwAliasRid);
    if (status == STATUS_NONE_MAPPED)
    {
        /* No such alias in host's domain.
           Try to look in builtin domain. */
        status = NetOpenAlias(pConn,
                              pwszAliasname,
                              dwAliasAccessFlags,
                              &hAlias,
                              &dwAliasRid);
        BAIL_ON_NT_STATUS(status);

    }
    else if (status != STATUS_SUCCESS)
    {
        BAIL_ON_NT_STATUS(status);
    }

    status = SamrGetMembersInAlias(hSamrBinding,
                                   hAlias,
                                   &ppSids,
                                   &dwNumSids);
    BAIL_ON_NT_STATUS(status);

    status = SamrClose(hSamrBinding, hAlias);
    BAIL_ON_NT_STATUS(status);

    dwTotalNumEntries = dwNumSids;

    if (dwLevel == 0)
    {
        for (i = 0; i + dwResume < dwNumSids; i++)
        {
            pSourceBuffer = ppSids[i + dwResume];

            err = NetAllocateLocalGroupMembersInfo(NULL,
                                                   NULL,
                                                   dwLevel,
                                                   pSourceBuffer,
                                                   &dwSize,
                                                   eValidation);
            BAIL_ON_WIN_ERROR(err);

            dwTotalSize += dwSize;
            dwNumEntries++;

            if (dwTotalSize > dwMaxBufferSize)
            {
                dwTotalSize -= dwSize;
                dwNumEntries--;
                break;
            }
        }
    }
    else
    {
        status = NetConnectLsa(&pConn,
                               pwszHostname,
                               dwLsaAccessFlags,
                               pCreds);
        BAIL_ON_NT_STATUS(status);

        hLsaBinding  = pConn->Rpc.Lsa.hBinding;
        hLsaPolicy   = pConn->Rpc.Lsa.hPolicy;

        Sids.dwNumSids = dwNumSids;
        status = NetAllocateMemory(OUT_PPVOID(&Sids.pSids),
                                   sizeof(Sids.pSids[0]) * Sids.dwNumSids);
        BAIL_ON_NT_STATUS(status);
    
        for (i = 0; i < Sids.dwNumSids; i++)
        {
            Sids.pSids[i].pSid = ppSids[i];
        }

        status = LsaLookupSids(hLsaBinding,
                               hLsaPolicy,
                               &Sids,
                               &pDomains,
                               &pNames,
                               wLookupLevel,
                               &dwCount);
        if (status != STATUS_SUCCESS &&
            status != LW_STATUS_SOME_NOT_MAPPED)
        {
            BAIL_ON_NT_STATUS(status);
        }

        status = NetAllocateMemory(OUT_PPVOID(&pResolvedNames),
                                   sizeof(*pResolvedNames) * dwCount);
        BAIL_ON_NT_STATUS(status);

        for (i = 0; i + dwResume < dwCount; i++)
        {
            DWORD iDomain = pNames[i + dwResume].sid_index;

            pResolvedNames[i].AccountName = pNames[i + dwResume].name;
            pResolvedNames[i].usType      = pNames[i + dwResume].type;
            pResolvedNames[i].DomainName  = pDomains->domains[iDomain].name;

            pSourceBuffer = pResolvedNames;

            err = NetAllocateLocalGroupMembersInfo(NULL,
                                                   NULL,
                                                   dwLevel,
                                                   pSourceBuffer,
                                                   &dwSize,
                                                   eValidation);
            BAIL_ON_WIN_ERROR(err);

            dwTotalSize += dwSize;
            dwNumEntries++;

            if (dwTotalSize > dwMaxBufferSize)
            {
                dwTotalSize -= dwSize;
                dwNumEntries--;
                break;
            }
        }
    }

    if (dwTotalNumEntries > 0 && dwNumEntries == 0)
    {
        err = ERROR_INSUFFICIENT_BUFFER;
        BAIL_ON_WIN_ERROR(err);
    }

    if (dwTotalSize)
    {
        status = NetAllocateMemory(OUT_PPVOID(&pBuffer),
                                   dwTotalSize);
        BAIL_ON_NT_STATUS(status);
    }

    dwSize           = 0;
    pBufferCursor    = pBuffer;
    dwSpaceAvailable = dwTotalSize;

    for (i = 0; i < dwNumEntries; i++)
    {
        if (dwLevel == 0)
        {
            pSourceBuffer = ppSids[i + dwResume];
        }
        else
        {
            pSourceBuffer = &(pResolvedNames[i]);
        }

        pBufferCursor = pBuffer + (i * dwInfoLevelSize);

        err = NetAllocateLocalGroupMembersInfo(pBufferCursor,
                                               &dwSpaceAvailable,
                                               dwLevel,
                                               pSourceBuffer,
                                               &dwSize,
                                               eValidation);
        BAIL_ON_WIN_ERROR(err);
    }

    if (dwResume + dwNumEntries < dwTotalNumEntries)
    {
        err = ERROR_MORE_DATA;
    }

    *ppBuffer        = pBuffer;
    *pdwResume       = dwResume + dwNumEntries;
    *pdwNumEntries   = dwNumEntries;
    *pdwTotalEntries = dwTotalNumEntries;

cleanup:
    NetDisconnectSamr(&pConn);

    if (Sids.pSids)
    {
        NetFreeMemory(Sids.pSids);
    }

    if (ppSids)
    {
        SamrFreeMemory(ppSids);
    }

    if (pNames)
    {
        SamrFreeMemory(pNames);
    }

    if (pDomains)
    {
        SamrFreeMemory(pDomains);
    }

    if (pCreds)
    {
        LwIoDeleteCreds(pCreds);
    }

    if (err == ERROR_SUCCESS &&
        status != STATUS_SUCCESS)
    {
        err = LwNtStatusToWin32Error(status);
    }

    return err;

error:
    if (pBuffer)
    {
        NetFreeMemory(pBuffer);
    }

    *ppBuffer = NULL;

    goto cleanup;
}
Exemplo n.º 7
0
static
DWORD
ProcessEnumerateAccounts(
    IN PRPC_PARAMETERS pRpcParams,
    IN PSTR UserRightName
    )
{
    DWORD err = ERROR_SUCCESS;
    NTSTATUS ntStatus = STATUS_SUCCESS;
    LSA_BINDING hLsa = NULL;
    LW_PIO_CREDS pCreds = NULL;
    WCHAR wszSysName[] = {'\\', '\\', '\0'};
    DWORD policyAccessMask = LSA_ACCESS_LOOKUP_NAMES_SIDS |
                             LSA_ACCESS_VIEW_POLICY_INFO;
    POLICY_HANDLE hPolicy = NULL;
    PWSTR pwszUserRightName = NULL;
    DWORD resume = 0;
    PSID *ppSids = NULL;
    DWORD numSids = 0;
    DWORD prefMaxSize = 64;
    DWORD i = 0;
    SID_ARRAY sids = {0};
    RefDomainList *pDomList = NULL;
    TranslatedName *pTransNames = NULL;
    DWORD count = 0;
    PSTR pszAccountSid = NULL;
    PSTR pszAccountDomain = NULL;
    PSTR pszAccountName = NULL;
    BOOLEAN moreEntries = FALSE;
    
    err = CreateRpcCredentials(pRpcParams,
                               &pCreds);
    BAIL_ON_LSA_ERROR(err);

    err = CreateLsaRpcBinding(pRpcParams,
                              pCreds,
                              &hLsa);
    BAIL_ON_LSA_ERROR(err);

    ntStatus = LsaOpenPolicy2(hLsa,
                              wszSysName,
                              NULL,
                              policyAccessMask,
                              &hPolicy);
    BAIL_ON_NT_STATUS(ntStatus);

    fprintf(stdout,
            "LSA Accounts");

    do
    {
        moreEntries = FALSE;

        if (UserRightName)
        {
            fprintf(stdout, " with AccountRight = %s:\n", UserRightName);
            fprintf(stdout,
                    "=================================================="
                    "==============================\n");

            err = LwMbsToWc16s(UserRightName,
                               &pwszUserRightName);
            BAIL_ON_LSA_ERROR(err);

            ntStatus = LsaEnumAccountsWithUserRight(
                                       hLsa,
                                       hPolicy,
                                       pwszUserRightName,
                                       &ppSids,
                                       &numSids);
            BAIL_ON_NT_STATUS(ntStatus);
        }
        else
        {
            fprintf(stdout, ":\n");
            fprintf(stdout,
                    "=================================================="
                    "==============================\n");

            ntStatus = LsaEnumAccounts(hLsa,
                                       hPolicy,
                                       &resume,
                                       &ppSids,
                                       &numSids,
                                       prefMaxSize);
            if (ntStatus == STATUS_MORE_ENTRIES)
            {
                ntStatus = STATUS_SUCCESS;
                moreEntries = TRUE;
            }
            else if (ntStatus != STATUS_SUCCESS)
            {
                BAIL_ON_NT_STATUS(ntStatus);
            }
        }

        err = LwAllocateMemory(
                       sizeof(sids.pSids[0]) * numSids,
                       OUT_PPVOID(&sids.pSids));
        BAIL_ON_LSA_ERROR(err);

        sids.dwNumSids = numSids;

        for (i = 0; i < sids.dwNumSids; i++)
        {
            sids.pSids[i].pSid = ppSids[i];
        }

        ntStatus = LsaLookupSids(hLsa,
                                 hPolicy,
                                 &sids,
                                 &pDomList,
                                 &pTransNames,
                                 LSA_LOOKUP_NAMES_ALL,
                                 &count);
        if (ntStatus == STATUS_SOME_NOT_MAPPED ||
            ntStatus == STATUS_NONE_MAPPED)
        {
            ntStatus = STATUS_SUCCESS;
        }
        else if (ntStatus != STATUS_SUCCESS)
        {
            BAIL_ON_NT_STATUS(ntStatus);
        }

        for (i = 0; i < sids.dwNumSids; i++)
        {
            DWORD domainIndex = 0;

            ntStatus = RtlAllocateCStringFromSid(
                                 &pszAccountSid,
                                 sids.pSids[i].pSid);
            BAIL_ON_NT_STATUS(ntStatus);

            if (pTransNames[i].type == SID_TYPE_USER ||
                pTransNames[i].type == SID_TYPE_DOM_GRP ||
                pTransNames[i].type == SID_TYPE_DOMAIN ||
                pTransNames[i].type == SID_TYPE_ALIAS ||
                pTransNames[i].type == SID_TYPE_WKN_GRP)
            {
                ntStatus = RtlCStringAllocateFromUnicodeString(
                                     &pszAccountName,
                                     &pTransNames[i].name);
                BAIL_ON_NT_STATUS(ntStatus);

                domainIndex = pTransNames[i].sid_index;

                ntStatus = RtlCStringAllocateFromUnicodeString(
                                      &pszAccountDomain,
                                      &pDomList->domains[domainIndex].name);
                BAIL_ON_NT_STATUS(ntStatus);
            }

            if (pszAccountSid)
            {
                fprintf(stdout, "%s ", pszAccountSid);
            }

            if (pszAccountDomain && pszAccountName)
            {
                fprintf(stdout, "(%s\\%s)", pszAccountDomain, pszAccountName);
            }
            else if (pszAccountDomain && !pszAccountName)
            {
                fprintf(stdout, "(%s\\)", pszAccountDomain);
            }
            else if (!pszAccountDomain && pszAccountName)
            {
                fprintf(stdout, "(%s)", pszAccountName);
            }
            else
            {
                fprintf(stdout, "(unknown)");
            }

            fprintf(stdout, "\n");

            RTL_FREE(&pszAccountSid);
            RTL_FREE(&pszAccountDomain);
            RTL_FREE(&pszAccountName);

        }

        if (pTransNames)
        {
            LsaRpcFreeMemory(pTransNames);
            pTransNames = NULL;
        }

        if (pDomList)
        {
            LsaRpcFreeMemory(pDomList);
            pDomList = NULL;
        }

        if (ppSids)
        {
            LsaRpcFreeMemory(ppSids);
            ppSids = NULL;
        }

        LW_SAFE_FREE_MEMORY(sids.pSids);

    } while (moreEntries && ntStatus == STATUS_SUCCESS);

error:
    if (ntStatus || err)
    {
        PCSTR errName = LwNtStatusToName(ntStatus);
        PCSTR errDescription = LwNtStatusToDescription(ntStatus);

        if (ntStatus)
        {
            errName = LwNtStatusToName(ntStatus);
            errDescription = LwNtStatusToDescription(ntStatus);
        }
        else
        {
            errName = LwWin32ErrorToName(err);
            errDescription = LwWin32ErrorToDescription(err);
        }

        fprintf(stderr, "Error: %s (%s)\n",
                LSA_SAFE_LOG_STRING(errName),
                LSA_SAFE_LOG_STRING(errDescription));
    }

    if (hPolicy)
    {
        LsaClose(hLsa, hPolicy);
    }

    if (hLsa)
    {
        LsaFreeBinding(&hLsa);
    }

    if (pCreds)
    {
        LwIoDeleteCreds(pCreds);
    }

    LW_SAFE_FREE_MEMORY(pwszUserRightName);
    RTL_FREE(&pszAccountSid);
    RTL_FREE(&pszAccountDomain);
    RTL_FREE(&pszAccountName);

    if (pTransNames)
    {
        LsaRpcFreeMemory(pTransNames);
    }

    if (pDomList)
    {
        LsaRpcFreeMemory(pDomList);
    }

    if (ppSids)
    {
        LsaRpcFreeMemory(ppSids);
    }

    LW_SAFE_FREE_MEMORY(sids.pSids);

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

    return err;
}