Пример #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");
  }
}
Пример #2
0
HRESULT TCUserAccount::HasRight(LPTSTR pszPrivilege) const
{
  // Not supported under Windows9x
  if (IsWin9x())
    return S_FALSE;

  // Fail if Init has not been called successfully
  if (!m_hPolicy || m_spSIDPrincipal.IsNull())
    return E_UNEXPECTED;

  // Fail if the specified pointer is NULL
  if (!pszPrivilege)
    return E_POINTER;

  // Get the array of user rights
  PLSA_UNICODE_STRING pUserRights = NULL;
  ULONG cRights = 0;
  RETURN_FAILED(LsaEnumerateAccountRights(m_hPolicy, m_spSIDPrincipal,
    &pUserRights, &cRights));

  // Get a pointer to a UNICODE version of the specified privilege
  USES_CONVERSION;
  LPCWSTR pszWidePrivilege = T2CW(pszPrivilege);

  // Loop through the array of privileges
  for (ULONG i = 0; i < cRights; ++i)
    if (0 == _wcsicmp(pUserRights[i].Buffer, pszWidePrivilege))
      return S_OK;

  // Specified privilege wasnt' found
  return S_FALSE;
}
Пример #3
0
NTSTATUS
GetPrivilegesOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
		       wchar_t **PrivList, unsigned int *PrivCount)
{
	NTSTATUS Status;
	LSA_UNICODE_STRING *UserRights;
	ULONG CountOfRights;
	unsigned int retlen = 0;
	DWORD i, j;
	int found;

	Status = LsaEnumerateAccountRights(PolicyHandle, AccountSid,
		&UserRights, &CountOfRights);
	/* Only continue if there is something */
	if (UserRights == NULL || Status != STATUS_SUCCESS)
		return (Status);

	for (i = 0; i < CountOfRights; i++) {
		found = -1;
		retlen = UserRights[i].Length/sizeof(wchar_t);
		for (j = 0; j < *PrivCount; j++) {
			found = wcsncmp(PrivList[j], UserRights[i].Buffer,
					retlen);
			if (found == 0)
				break;
		}
		if (found != 0) {
			PrivList[*PrivCount] =
			    (wchar_t *)malloc(UserRights[i].MaximumLength);
			if (PrivList[*PrivCount] == NULL)
				return (RTN_NOMEMORY);

			wcsncpy(PrivList[*PrivCount], UserRights[i].Buffer,
				retlen);
			PrivList[*PrivCount][retlen] = L'\0';
			(*PrivCount)++;
		}

	}

	return (Status);
}
Пример #4
0
BOOL lsp_list_by_user(LSA_HANDLE lsa_handle, LPTSTR user)
{
  LSA_ACCOUNT         account;
  LSA_UNICODE_STRING* array;
  ULONG               count;
  ULONG               i;
  NTSTATUS            nt_status;
  PSID                sid;

  if (!valid_user(lsa_handle, &sid, user))
    return FALSE;

  if (!lsa_account_from_sid(lsa_handle, sid, &account))
  {
    FreeSid(sid);
    return FALSE;
  }

  print_string(L"Privileges for ");
  print_account(&account);
  print_string(L":\n");

  nt_status = LsaEnumerateAccountRights(lsa_handle, sid, &array, &count);
  if (nt_status != STATUS_SUCCESS)
  {
    FreeSid(sid);
    return lsa_error(nt_status, L"LsaEnumerateAccountRights");
  }

  for(i=0; i<count; i++)
  {    
    print_string(L" - ");
    print_lsa_string(&array[i]);
    print_string(L"\n");
  }

  LsaFreeMemory(array);
  FreeSid(sid);

  return TRUE;
}
Пример #5
0
std::vector<std::wstring> GetPrivileges(PSID sid)
{
    LSA_HANDLE hPolicy = OpenPolicy(POLICY_LOOKUP_NAMES);
    PLSA_UNICODE_STRING userRights = NULL;

    try
    {
        ULONG rightsCount = 0;

        CheckRetVal(LsaEnumerateAccountRights(hPolicy, sid, &userRights, &rightsCount), ERROR_FILE_NOT_FOUND);

        std::vector<std::wstring> v;
        for (int i = 0; i < rightsCount; i++)
        {
            std::wstring s(userRights[i].Buffer, userRights[i].Length / sizeof(WCHAR));
            v.push_back(s);
        }

        LsaFreeMemory(userRights);
        userRights = NULL;
        LsaClose(hPolicy);
        hPolicy = NULL;

        return v;
    }
    catch (const std::exception&)
    {
        if (userRights)
        {
            LsaFreeMemory(userRights);
        }

        if (hPolicy)
        {
            LsaClose(hPolicy);
        }

        throw;
    }
}
int SetupTokenPrivileges(PTOKEN_PRIVILEGES *pPrivToken, PSID userSid)
{
  DWORD ntStat = 0;
  
  int exitCode = 1;
  
  LSA_OBJECT_ATTRIBUTES lsaOA = {0};

  PLSA_UNICODE_STRING userRights = NULL;
  
  ULONG nRights = 0;
  
  DWORD size;
  
  int i, j;
  
  /*
   * Open local policy.
   */

  LSA_HANDLE hPolicy;
  
  lsaOA.Length = sizeof(lsaOA);
  
  ACCESS_MASK mask = POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES;
  
  debug("Opening local policy...");
  
  ntStat = LsaOpenPolicy(NULL, &lsaOA, mask, &hPolicy);
  
  FAIL(ntStat);
  
  /*
   * Retrieve user's privileges.
   */
  
  debug("Retrieving user's privileges list...");
  
  ntStat = LsaEnumerateAccountRights(hPolicy, userSid, &userRights, &nRights);

  /*
   * This error code means there is no any rights.
   * In this case, we should create empty list.
   */
  
  if (ntStat == STATUS_OBJECT_NAME_NOT_FOUND)
  {
    nRights = 0;
    ntStat  = 0;
  }
  
  FAIL(ntStat);
  
  /*
   * FIXME. Now if some privilege name is not recognized by
   * LookupPrivilegeName() part of pPrivToken buffer will be
   * unused.
   */
   
  /*
   * Allocate buffer for TOKEN_PRIVILEGES.
   */
  
  debug("Allocating buffer for TOKEN_PRIVILEGES [%u]...", nRights);
  
  size = sizeof(DWORD) + nRights * sizeof(LUID_AND_ATTRIBUTES);
  
  (*pPrivToken) = LocalAlloc(LPTR, size);
  
  FAIL(pPrivToken == NULL);
  
  /*
   * Fill TOKEN_PRIVILEGES with LUIDs of retrieved privileges.
   */
  
  j = 0;
  
  for (i = 0; i < nRights; i++)
  {
    /*
     * Retrieve unicode name of privilege.
     * Make sure there is a zero word at the end.
     */
    
    wchar_t privName[128];
    
    int len = userRights[i].Length;
    
    memcpy(privName, userRights[i].Buffer, len * sizeof(wchar_t));
    
    privName[len] = 0;
    
    debug("Adding %ls... ", privName);

    /*
     * Retrieve LUID for given privilege name.
     */
    
    if(LookupPrivilegeValueW(NULL, privName,
                                   &(*pPrivToken) -> Privileges[i].Luid) == FALSE)
    {
      debug("WARNING. Cannot add privilege to token (%u).", GetLastError());
    }
    else
    {
      (*pPrivToken) -> Privileges[j].Attributes = SE_PRIVILEGE_ENABLED;

      j++;
    }  
  }
  
  /*
   * j = number of privileges, which were recognized by
   * LookupPrivilegesValue().
   */
  
  (*pPrivToken) -> PrivilegeCount = j;
  
  exitCode = 0;

fail:

  /*
   * Clenup.
   */
  
  if (userRights)
  {
    LsaFreeMemory(userRights);
  }
  
  if (hPolicy)
  {
    CloseHandle(hPolicy);
  }  
  
  if (exitCode)
  {
    debug("ERROR. Cannot setup TOKEN_PRIVILEGES (err=%u, ntStat=%x).",
              GetLastError(), ntStat);
  }
}
Пример #7
0
USHORT SERVICES_grant_privilege(const TEXT* account, pfnSvcError err_handler, const WCHAR* privilege)
{
/***************************************************
 *
 * S E R V I C E _ g r a n t _ l o g o n _ r i g h t
 *
 ***************************************************
 *
 * Functional description
 *  Grants the "Log on as a service" right to account.
 *  This is a Windows NT, 2000, XP, 2003 security thing.
 *  To run a service under an account other than LocalSystem, the account
 *  must have this right. To succeed granting the right, the current user
 *  must be an Administrator.
 *  Returns FB_SUCCESS when actually granted the right.
 *  Returns FB_LOGON_SRVC_RIGHT_ALREADY_DEFINED if right was already granted
 *  to the user.
 *  Returns FB_FAILURE on any error.
 *
 *  OM - AUG 2003 - Initial implementation
 *  OM - SEP 2003 - Control flow revision, no functional change
 *
 ***************************************************/

	LSA_OBJECT_ATTRIBUTES ObjectAttributes;
	LSA_HANDLE PolicyHandle;

	// Open the policy on the local machine.
	ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
	NTSTATUS lsaErr = LsaOpenPolicy(NULL, &ObjectAttributes,
		POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &PolicyHandle);
	if (lsaErr != (NTSTATUS) 0)
		return (*err_handler)(LsaNtStatusToWinError(lsaErr), "LsaOpenPolicy", NULL);

	// Obtain the SID of the user/group.
	// First, dummy call to LookupAccountName to get the required buffer sizes.
	DWORD cbSid;
	DWORD cchDomain;
	cbSid = cchDomain = 0;
	SID_NAME_USE peUse;
	LookupAccountName(NULL, account, NULL, &cbSid, NULL, &cchDomain, &peUse);
	PSID pSid = (PSID) LocalAlloc(LMEM_ZEROINIT, cbSid);
	if (pSid == 0)
	{
		DWORD err = GetLastError();
		LsaClose(PolicyHandle);
		return (*err_handler)(err, "LocalAlloc(Sid)", NULL);
	}
	TEXT* pDomain = (LPTSTR) LocalAlloc(LMEM_ZEROINIT, cchDomain);
	if (pDomain == 0)
	{
		DWORD err = GetLastError();
		LsaClose(PolicyHandle);
		LocalFree(pSid);
		return (*err_handler)(err, "LocalAlloc(Domain)", NULL);
	}
	// Now, really obtain the SID of the user/group.
	if (LookupAccountName(NULL, account, pSid, &cbSid, pDomain, &cchDomain, &peUse) == 0)
	{
		DWORD err = GetLastError();
		LsaClose(PolicyHandle);
		LocalFree(pSid);
		LocalFree(pDomain);
		return (*err_handler)(err, "LookupAccountName", NULL);
	}

	PLSA_UNICODE_STRING UserRights;
	ULONG CountOfRights = 0;
	NTSTATUS ntStatus = LsaEnumerateAccountRights(PolicyHandle, pSid, &UserRights, &CountOfRights);
	if (ntStatus == (NTSTATUS) 0xC0000034L) //STATUS_OBJECT_NAME_NOT_FOUND
		CountOfRights = 0;
	// Check if the seServiceLogonRight is already granted
	ULONG i;
	for (i = 0; i < CountOfRights; i++)
	{
		if (wcscmp(UserRights[i].Buffer, privilege) == 0)
			break;
	}
	LsaFreeMemory(UserRights); // Don't leak
	LSA_UNICODE_STRING PrivilegeString;
	if (CountOfRights == 0 || i == CountOfRights)
	{
		// Grant the SeServiceLogonRight to users represented by pSid.
		const int string_buff_size = 100;
		WCHAR tempStr[string_buff_size];
		wcsncpy(tempStr, privilege, string_buff_size - 1);
		tempStr[string_buff_size - 1] = 0;

		PrivilegeString.Buffer = tempStr;
		PrivilegeString.Length = wcslen(tempStr) * sizeof(WCHAR);
		PrivilegeString.MaximumLength = sizeof(tempStr);
		if ((lsaErr = LsaAddAccountRights(PolicyHandle, pSid, &PrivilegeString, 1)) != (NTSTATUS) 0)
		{
			LsaClose(PolicyHandle);
			LocalFree(pSid);
			LocalFree(pDomain);
			return (*err_handler)(LsaNtStatusToWinError(lsaErr), "LsaAddAccountRights", NULL);
		}
	}
	else
	{
		LsaClose(PolicyHandle);
		LocalFree(pSid);
		LocalFree(pDomain);
		return FB_PRIVILEGE_ALREADY_GRANTED;
	}

	LsaClose(PolicyHandle);
	LocalFree(pSid);
	LocalFree(pDomain);

	return FB_SUCCESS;
}
Пример #8
0
Файл: lsa.c Проект: Jactry/wine
static void test_lsa(void)
{
    NTSTATUS status;
    LSA_HANDLE handle;
    LSA_OBJECT_ATTRIBUTES object_attributes;

    ZeroMemory(&object_attributes, sizeof(object_attributes));
    object_attributes.Length = sizeof(object_attributes);

    status = LsaOpenPolicy( NULL, &object_attributes, POLICY_ALL_ACCESS, &handle);
    ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED,
       "LsaOpenPolicy(POLICY_ALL_ACCESS) returned 0x%08x\n", status);

    /* try a more restricted access mask if necessary */
    if (status == STATUS_ACCESS_DENIED) {
        trace("LsaOpenPolicy(POLICY_ALL_ACCESS) failed, trying POLICY_VIEW_LOCAL_INFORMATION|POLICY_LOOKUP_NAMES\n");
        status = LsaOpenPolicy( NULL, &object_attributes, POLICY_VIEW_LOCAL_INFORMATION|POLICY_LOOKUP_NAMES, &handle);
        ok(status == STATUS_SUCCESS, "LsaOpenPolicy(POLICY_VIEW_LOCAL_INFORMATION|POLICY_LOOKUP_NAMES) returned 0x%08x\n", status);
    }

    if (status == STATUS_SUCCESS) {
        PPOLICY_AUDIT_EVENTS_INFO audit_events_info;
        PPOLICY_PRIMARY_DOMAIN_INFO primary_domain_info;
        PPOLICY_ACCOUNT_DOMAIN_INFO account_domain_info;
        PPOLICY_DNS_DOMAIN_INFO dns_domain_info;
        HANDLE token;
        BOOL ret;

        status = LsaQueryInformationPolicy(handle, PolicyAuditEventsInformation, (void **)&audit_events_info);
        if (status == STATUS_ACCESS_DENIED)
            skip("Not enough rights to retrieve PolicyAuditEventsInformation\n");
        else
            ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy(PolicyAuditEventsInformation) failed, returned 0x%08x\n", status);
        if (status == STATUS_SUCCESS)
            LsaFreeMemory(audit_events_info);

        status = LsaQueryInformationPolicy(handle, PolicyPrimaryDomainInformation, (void **)&primary_domain_info);
        ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy(PolicyPrimaryDomainInformation) failed, returned 0x%08x\n", status);
        if (status == STATUS_SUCCESS) {
            if (primary_domain_info->Sid) {
                LPSTR strsid;
                if (ConvertSidToStringSidA(primary_domain_info->Sid, &strsid))
                {
                    if (primary_domain_info->Name.Buffer) {
                        LPSTR name = NULL;
                        UINT len;
                        len = WideCharToMultiByte( CP_ACP, 0, primary_domain_info->Name.Buffer, -1, NULL, 0, NULL, NULL );
                        name = LocalAlloc( 0, len );
                        WideCharToMultiByte( CP_ACP, 0, primary_domain_info->Name.Buffer, -1, name, len, NULL, NULL );
                        trace("  name: %s sid: %s\n", name, strsid);
                        LocalFree( name );
                    } else
                        trace("  name: NULL sid: %s\n", strsid);
                    LocalFree( strsid );
                }
                else
                    trace("invalid sid\n");
            }
            else
                trace("Running on a standalone system.\n");
            LsaFreeMemory(primary_domain_info);
        }

        status = LsaQueryInformationPolicy(handle, PolicyAccountDomainInformation, (void **)&account_domain_info);
        ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy(PolicyAccountDomainInformation) failed, returned 0x%08x\n", status);
        if (status == STATUS_SUCCESS)
            LsaFreeMemory(account_domain_info);

        /* This isn't supported in NT4 */
        status = LsaQueryInformationPolicy(handle, PolicyDnsDomainInformation, (void **)&dns_domain_info);
        ok(status == STATUS_SUCCESS || status == STATUS_INVALID_PARAMETER,
           "LsaQueryInformationPolicy(PolicyDnsDomainInformation) failed, returned 0x%08x\n", status);
        if (status == STATUS_SUCCESS) {
            if (dns_domain_info->Sid || !IsEqualGUID(&dns_domain_info->DomainGuid, &GUID_NULL)) {
                LPSTR strsid = NULL;
                LPSTR name = NULL;
                LPSTR domain = NULL;
                LPSTR forest = NULL;
                LPSTR guidstr = NULL;
                WCHAR guidstrW[64];
                UINT len;
                guidstrW[0] = '\0';
                ConvertSidToStringSidA(dns_domain_info->Sid, &strsid);
                StringFromGUID2(&dns_domain_info->DomainGuid, guidstrW, ARRAY_SIZE(guidstrW));
                len = WideCharToMultiByte( CP_ACP, 0, guidstrW, -1, NULL, 0, NULL, NULL );
                guidstr = LocalAlloc( 0, len );
                WideCharToMultiByte( CP_ACP, 0, guidstrW, -1, guidstr, len, NULL, NULL );
                if (dns_domain_info->Name.Buffer) {
                    len = WideCharToMultiByte( CP_ACP, 0, dns_domain_info->Name.Buffer, -1, NULL, 0, NULL, NULL );
                    name = LocalAlloc( 0, len );
                    WideCharToMultiByte( CP_ACP, 0, dns_domain_info->Name.Buffer, -1, name, len, NULL, NULL );
                }
                if (dns_domain_info->DnsDomainName.Buffer) {
                    len = WideCharToMultiByte( CP_ACP, 0, dns_domain_info->DnsDomainName.Buffer, -1, NULL, 0, NULL, NULL );
                    domain = LocalAlloc( 0, len );
                    WideCharToMultiByte( CP_ACP, 0, dns_domain_info->DnsDomainName.Buffer, -1, domain, len, NULL, NULL );
                }
                if (dns_domain_info->DnsForestName.Buffer) {
                    len = WideCharToMultiByte( CP_ACP, 0, dns_domain_info->DnsForestName.Buffer, -1, NULL, 0, NULL, NULL );
                    forest = LocalAlloc( 0, len );
                    WideCharToMultiByte( CP_ACP, 0, dns_domain_info->DnsForestName.Buffer, -1, forest, len, NULL, NULL );
                }
                trace("  name: %s domain: %s forest: %s guid: %s sid: %s\n",
                      name ? name : "NULL", domain ? domain : "NULL",
                      forest ? forest : "NULL", guidstr, strsid ? strsid : "NULL");
                LocalFree( name );
                LocalFree( forest );
                LocalFree( domain );
                LocalFree( guidstr );
                LocalFree( strsid );
            }
            else
                trace("Running on a standalone system.\n");
            LsaFreeMemory(dns_domain_info);
        }

        /* We need a valid SID to pass to LsaEnumerateAccountRights */
        ret = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &token );
        ok(ret, "Unable to obtain process token, error %u\n", GetLastError( ));
        if (ret) {
            char buffer[64];
            DWORD len;
            TOKEN_USER *token_user = (TOKEN_USER *) buffer;
            ret = GetTokenInformation( token, TokenUser, (LPVOID) token_user, sizeof(buffer), &len );
            ok(ret || GetLastError( ) == ERROR_INSUFFICIENT_BUFFER, "Unable to obtain token information, error %u\n", GetLastError( ));
            if (! ret && GetLastError( ) == ERROR_INSUFFICIENT_BUFFER) {
                trace("Resizing buffer to %u.\n", len);
                token_user = LocalAlloc( 0, len );
                if (token_user != NULL)
                    ret = GetTokenInformation( token, TokenUser, (LPVOID) token_user, len, &len );
            }

            if (ret) {
                PLSA_UNICODE_STRING rights;
                ULONG rights_count;
                rights = (PLSA_UNICODE_STRING) 0xdeadbeaf;
                rights_count = 0xcafecafe;
                status = LsaEnumerateAccountRights(handle, token_user->User.Sid, &rights, &rights_count);
                ok(status == STATUS_SUCCESS || status == STATUS_OBJECT_NAME_NOT_FOUND, "Unexpected status 0x%x\n", status);
                if (status == STATUS_SUCCESS)
                    LsaFreeMemory( rights );
                else
                    ok(rights == NULL && rights_count == 0, "Expected rights and rights_count to be set to 0 on failure\n");
            }
            if (token_user != NULL && token_user != (TOKEN_USER *) buffer)
                LocalFree( token_user );
            CloseHandle( token );
        }

        status = LsaClose(handle);
        ok(status == STATUS_SUCCESS, "LsaClose() failed, returned 0x%08x\n", status);
    }
}
Пример #9
0
static int collect_access_rights(probe_ctx *ctx, WCHAR *security_principle, bool include_group, bool resolve_group)
{
	char *security_principle_str = oscap_windows_wstr_to_str(security_principle);

	LSA_OBJECT_ATTRIBUTES object_attributes;
	ZeroMemory(&object_attributes, sizeof(LSA_OBJECT_ATTRIBUTES));
	LSA_HANDLE lsa_policy_handle;

	NTSTATUS status = LsaOpenPolicy(NULL, &object_attributes, POLICY_LOOKUP_NAMES, &lsa_policy_handle);
	if (status != STATUS_SUCCESS) {
		DWORD err = LsaNtStatusToWinError(status);
		char *error_message = oscap_windows_error_message(err);
		dD("LsaOpenPolicy failed for principle '%s': %s", security_principle_str, error_message);
		free(error_message);
		free(security_principle_str);
		return 1;
	}

	/* Convert the value of the security_principle element to a SID. */
	DWORD sid_len = 0;
	DWORD domain_name_len = 0;
	SID_NAME_USE sid_type;
	LookupAccountNameW(NULL, security_principle, NULL, &sid_len, NULL, &domain_name_len, &sid_type);
	SID *sid = malloc(sid_len);
	WCHAR *domain_name = malloc(domain_name_len * sizeof(WCHAR));
	if (!LookupAccountNameW(NULL, security_principle, sid, &sid_len, domain_name, &domain_name_len, &sid_type)) {
		DWORD err = GetLastError();
		char *error_message = oscap_windows_error_message(err);
		dD("LookupAccountNameW failed for '%s': %s", security_principle_str, error_message);
		free(error_message);
		free(security_principle_str);
		free(sid);
		free(domain_name);
		return 1;
	}

	/* Is it a group? */
	if (sid_type == SidTypeGroup || sid_type == SidTypeWellKnownGroup || sid_type == SidTypeAlias) {
		if (resolve_group) {
			struct oscap_list *group_members_list = oscap_list_new();
			get_local_group_members(security_principle, group_members_list);
			get_global_group_members(security_principle, group_members_list);
			struct oscap_iterator *group_members_it = oscap_iterator_new(group_members_list);
			while (oscap_iterator_has_more(group_members_it)) {
				WCHAR *group_member = oscap_iterator_next(group_members_it);
				collect_access_rights(ctx, group_member, include_group, resolve_group);
			}
			oscap_iterator_free(group_members_it);
			oscap_list_free(group_members_list, free);
		}
		if (!include_group) {
			free(sid);
			free(domain_name);
			free(security_principle_str);
			return 0;
		}
	}

	/* Users and groups can inherit their privileges from their parents */
	struct oscap_list *every_rights_sources = oscap_list_new();
	oscap_list_add(every_rights_sources, wcsdup(security_principle));
	get_user_local_groups(security_principle, every_rights_sources);
	get_user_global_groups(security_principle, every_rights_sources);

	/* Iterate over the items */
	bool privileges_enabled[OVAL_PRIVILEGES_COUNT] = { false };
	struct oscap_iterator *it = oscap_iterator_new(every_rights_sources);
	while (oscap_iterator_has_more(it)) {
		WCHAR *account_name = oscap_iterator_next(it);

		DWORD account_sid_len = 0;
		DWORD account_domain_name_len = 0;
		SID_NAME_USE account_sid_type;
		LookupAccountNameW(NULL, account_name, NULL, &account_sid_len, NULL, &account_domain_name_len, &account_sid_type);
		SID *account_sid = malloc(account_sid_len);
		WCHAR *account_domain_name = malloc(account_domain_name_len * sizeof(WCHAR));
		if (!LookupAccountNameW(NULL, account_name, account_sid, &account_sid_len, account_domain_name, &account_domain_name_len, &account_sid_type)) {
			free(account_sid);
			free(account_domain_name);
			DWORD err = GetLastError();
			char *error_message = oscap_windows_error_message(err);
			dD("LookupAccountNameW failed for '%s': %s", security_principle_str, error_message);
			free(error_message);
			free(security_principle_str);
			return 1;
		}

		LSA_UNICODE_STRING *granted_rights = NULL;
		ULONG granted_rights_count = 0;
		status = LsaEnumerateAccountRights(lsa_policy_handle, account_sid, &granted_rights, &granted_rights_count);
		if (status != STATUS_SUCCESS) {
			free(account_sid);
			free(account_domain_name);
			DWORD err = LsaNtStatusToWinError(status);
			char *error_message = oscap_windows_error_message(err);
			dD("LsaEnumerateAccountRights failed for '%s': %s", security_principle_str, error_message);
			free(error_message);
			/* We should not exit here, because when LsaEnumerateAccountRights
			* failed it can mean that the entity simply doesn't have any specific
			* privileges, it only inhertis privileges form its parent group(s).
			*/
			continue;
		}

		for (int i = 0; i < OVAL_PRIVILEGES_COUNT; i++) {
			if (!privileges_enabled[i]) {
				for (ULONG j = 0; j < granted_rights_count; j++) {
					if (wcscmp(granted_rights[j].Buffer, privileges_texts[i]) == 0) {
						privileges_enabled[i] = true;
						break;
					}
				}
			}
		}
		LsaFreeMemory(granted_rights);
		free(account_sid);
		free(account_domain_name);

	}
	oscap_iterator_free(it);
	oscap_list_free(every_rights_sources, free);

	/* Collect the OVAL item */
	SEXP_t *item = probe_item_create(OVAL_WINDOWS_ACCESS_TOKEN, NULL,
		"security_principle", OVAL_DATATYPE_STRING, strdup(security_principle_str), NULL);
	for (int i = 0; i < OVAL_PRIVILEGES_COUNT; i++) {
		char *privilege_name = oscap_windows_wstr_to_str(privileges_texts[i]);
		/* Convert the element name to lowercase */
		for (char *p = privilege_name; *p; p++) {
			*p = tolower(*p);
		}
		SEXP_t *privilege_value = SEXP_number_newb(privileges_enabled[i]);
		probe_item_ent_add(item, privilege_name, NULL, privilege_value);
		free(privilege_name);
		SEXP_free(privilege_value);
	}
	probe_item_collect(ctx, item);
	free(security_principle_str);

	return 0;
}