// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sandbox/win/src/acl.h"

#include <aclapi.h>
#include <sddl.h>

#include "base/logging.h"
#include "base/memory/free_deleter.h"

namespace sandbox {

bool GetDefaultDacl(
    HANDLE token,
    std::unique_ptr<TOKEN_DEFAULT_DACL, base::FreeDeleter>* default_dacl) {
  if (!token)
    return false;

  DCHECK(default_dacl);

  unsigned long length = 0;
  ::GetTokenInformation(token, TokenDefaultDacl, nullptr, 0, &length);
  if (length == 0) {
    NOTREACHED();
    return false;
  }

  TOKEN_DEFAULT_DACL* acl =
      reinterpret_cast<TOKEN_DEFAULT_DACL*>(malloc(length));
  default_dacl->reset(acl);

  if (!::GetTokenInformation(token, TokenDefaultDacl, default_dacl->get(),
                             length, &length))
    return false;

  return true;
}

bool AddSidToDacl(const Sid& sid,
                  ACL* old_dacl,
                  ACCESS_MODE access_mode,
                  ACCESS_MASK access,
                  ACL** new_dacl) {
  EXPLICIT_ACCESS new_access = {0};
  new_access.grfAccessMode = access_mode;
  new_access.grfAccessPermissions = access;
  new_access.grfInheritance = NO_INHERITANCE;

  new_access.Trustee.pMultipleTrustee = nullptr;
  new_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  new_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
  new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>(sid.GetPSID());

  if (ERROR_SUCCESS != ::SetEntriesInAcl(1, &new_access, old_dacl, new_dacl))
    return false;

  return true;
}

bool AddSidToDefaultDacl(HANDLE token,
                         const Sid& sid,
                         ACCESS_MODE access_mode,
                         ACCESS_MASK access) {
  if (!token)
    return false;

  std::unique_ptr<TOKEN_DEFAULT_DACL, base::FreeDeleter> default_dacl;
  if (!GetDefaultDacl(token, &default_dacl))
    return false;

  ACL* new_dacl = nullptr;
  if (!AddSidToDacl(sid, default_dacl->DefaultDacl, access_mode, access,
                    &new_dacl))
    return false;

  TOKEN_DEFAULT_DACL new_token_dacl = {0};
  new_token_dacl.DefaultDacl = new_dacl;

  bool ret = ::SetTokenInformation(token, TokenDefaultDacl, &new_token_dacl,
                                   sizeof(new_token_dacl));
  ::LocalFree(new_dacl);
  return ret;
}

bool RevokeLogonSidFromDefaultDacl(HANDLE token) {
  DWORD size = sizeof(TOKEN_GROUPS) + SECURITY_MAX_SID_SIZE;
  TOKEN_GROUPS* logon_sid = reinterpret_cast<TOKEN_GROUPS*>(malloc(size));

  std::unique_ptr<TOKEN_GROUPS, base::FreeDeleter> logon_sid_ptr(logon_sid);

  if (!::GetTokenInformation(token, TokenLogonSid, logon_sid, size, &size)) {
    // If no logon sid, there's nothing to revoke.
    if (::GetLastError() == ERROR_NOT_FOUND)
      return true;
    return false;
  }
  if (logon_sid->GroupCount < 1) {
    ::SetLastError(ERROR_INVALID_TOKEN);
    return false;
  }
  return AddSidToDefaultDacl(token,
                             reinterpret_cast<SID*>(logon_sid->Groups[0].Sid),
                             REVOKE_ACCESS, 0);
}

bool AddUserSidToDefaultDacl(HANDLE token, ACCESS_MASK access) {
  DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE;
  TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(malloc(size));

  std::unique_ptr<TOKEN_USER, base::FreeDeleter> token_user_ptr(token_user);

  if (!::GetTokenInformation(token, TokenUser, token_user, size, &size))
    return false;

  return AddSidToDefaultDacl(token,
                             reinterpret_cast<SID*>(token_user->User.Sid),
                             GRANT_ACCESS, access);
}

bool AddKnownSidToObject(HANDLE object,
                         SE_OBJECT_TYPE object_type,
                         const Sid& sid,
                         ACCESS_MODE access_mode,
                         ACCESS_MASK access) {
  PSECURITY_DESCRIPTOR descriptor = nullptr;
  PACL old_dacl = nullptr;
  PACL new_dacl = nullptr;

  if (ERROR_SUCCESS !=
      ::GetSecurityInfo(object, object_type, DACL_SECURITY_INFORMATION, nullptr,
                        nullptr, &old_dacl, nullptr, &descriptor))
    return false;

  if (!AddSidToDacl(sid, old_dacl, access_mode, access, &new_dacl)) {
    ::LocalFree(descriptor);
    return false;
  }

  DWORD result =
      ::SetSecurityInfo(object, object_type, DACL_SECURITY_INFORMATION, nullptr,
                        nullptr, new_dacl, nullptr);

  ::LocalFree(new_dacl);
  ::LocalFree(descriptor);

  if (ERROR_SUCCESS != result)
    return false;

  return true;
}

}  // namespace sandbox
