// 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 <aclapi.h>
#include <sddl.h>
#include <vector>

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

#include "base/logging.h"
#include "base/win/scoped_handle.h"
#include "base/win/scoped_process_information.h"
#include "base/win/windows_version.h"
#include "sandbox/win/src/job.h"
#include "sandbox/win/src/restricted_token.h"
#include "sandbox/win/src/security_level.h"
#include "sandbox/win/src/sid.h"

namespace sandbox {

DWORD CreateRestrictedToken(HANDLE *token_handle,
                            TokenLevel security_level,
                            IntegrityLevel integrity_level,
                            TokenType token_type) {
  if (!token_handle)
    return ERROR_BAD_ARGUMENTS;

  RestrictedToken restricted_token;
  restricted_token.Init(NULL);  // Initialized with the current process token

  std::vector<base::string16> privilege_exceptions;
  std::vector<Sid> sid_exceptions;

  bool deny_sids = true;
  bool remove_privileges = true;

  switch (security_level) {
    case USER_UNPROTECTED: {
      deny_sids = false;
      remove_privileges = false;
      break;
    }
    case USER_RESTRICTED_SAME_ACCESS: {
      deny_sids = false;
      remove_privileges = false;

      unsigned err_code = restricted_token.AddRestrictingSidAllSids();
      if (ERROR_SUCCESS != err_code)
        return err_code;

      break;
    }
    case USER_NON_ADMIN: {
      sid_exceptions.push_back(WinBuiltinUsersSid);
      sid_exceptions.push_back(WinWorldSid);
      sid_exceptions.push_back(WinInteractiveSid);
      sid_exceptions.push_back(WinAuthenticatedUserSid);
      privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME);
      break;
    }
    case USER_INTERACTIVE: {
      sid_exceptions.push_back(WinBuiltinUsersSid);
      sid_exceptions.push_back(WinWorldSid);
      sid_exceptions.push_back(WinInteractiveSid);
      sid_exceptions.push_back(WinAuthenticatedUserSid);
      privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME);
      restricted_token.AddRestrictingSid(WinBuiltinUsersSid);
      restricted_token.AddRestrictingSid(WinWorldSid);
      restricted_token.AddRestrictingSid(WinRestrictedCodeSid);
      restricted_token.AddRestrictingSidCurrentUser();
      restricted_token.AddRestrictingSidLogonSession();
      break;
    }
    case USER_LIMITED: {
      sid_exceptions.push_back(WinBuiltinUsersSid);
      sid_exceptions.push_back(WinWorldSid);
      sid_exceptions.push_back(WinInteractiveSid);
      privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME);
      restricted_token.AddRestrictingSid(WinBuiltinUsersSid);
      restricted_token.AddRestrictingSid(WinWorldSid);
      restricted_token.AddRestrictingSid(WinRestrictedCodeSid);

      // This token has to be able to create objects in BNO.
      // Unfortunately, on vista, it needs the current logon sid
      // in the token to achieve this. You should also set the process to be
      // low integrity level so it can't access object created by other
      // processes.
      if (base::win::GetVersion() >= base::win::VERSION_VISTA)
        restricted_token.AddRestrictingSidLogonSession();
      break;
    }
    case USER_RESTRICTED: {
      privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME);
      restricted_token.AddUserSidForDenyOnly();
      restricted_token.AddRestrictingSid(WinRestrictedCodeSid);
      break;
    }
    case USER_LOCKDOWN: {
      restricted_token.AddUserSidForDenyOnly();
      restricted_token.AddRestrictingSid(WinNullSid);
      break;
    }
    default: {
      return ERROR_BAD_ARGUMENTS;
    }
  }

  DWORD err_code = ERROR_SUCCESS;
  if (deny_sids) {
    err_code = restricted_token.AddAllSidsForDenyOnly(&sid_exceptions);
    if (ERROR_SUCCESS != err_code)
      return err_code;
  }

  if (remove_privileges) {
    err_code = restricted_token.DeleteAllPrivileges(&privilege_exceptions);
    if (ERROR_SUCCESS != err_code)
      return err_code;
  }

  restricted_token.SetIntegrityLevel(integrity_level);

  switch (token_type) {
    case PRIMARY: {
      err_code = restricted_token.GetRestrictedTokenHandle(token_handle);
      break;
    }
    case IMPERSONATION: {
      err_code = restricted_token.GetRestrictedTokenHandleForImpersonation(
          token_handle);
      break;
    }
    default: {
      err_code = ERROR_BAD_ARGUMENTS;
      break;
    }
  }

  return err_code;
}

DWORD StartRestrictedProcessInJob(wchar_t *command_line,
                                  TokenLevel primary_level,
                                  TokenLevel impersonation_level,
                                  JobLevel job_level,
                                  HANDLE *const job_handle_ret) {
  Job job;
  DWORD err_code = job.Init(job_level, NULL, 0);
  if (ERROR_SUCCESS != err_code)
    return err_code;

  if (JOB_UNPROTECTED != job_level) {
    // Share the Desktop handle to be able to use MessageBox() in the sandboxed
    // application.
    err_code = job.UserHandleGrantAccess(GetDesktopWindow());
    if (ERROR_SUCCESS != err_code)
      return err_code;
  }

  // Create the primary (restricted) token for the process
  HANDLE primary_token_handle = NULL;
  err_code = CreateRestrictedToken(&primary_token_handle,
                                   primary_level,
                                   INTEGRITY_LEVEL_LAST,
                                   PRIMARY);
  if (ERROR_SUCCESS != err_code) {
    return err_code;
  }
  base::win::ScopedHandle primary_token(primary_token_handle);

  // Create the impersonation token (restricted) to be able to start the
  // process.
  HANDLE impersonation_token_handle;
  err_code = CreateRestrictedToken(&impersonation_token_handle,
                                   impersonation_level,
                                   INTEGRITY_LEVEL_LAST,
                                   IMPERSONATION);
  if (ERROR_SUCCESS != err_code) {
    return err_code;
  }
  base::win::ScopedHandle impersonation_token(impersonation_token_handle);

  // Start the process
  STARTUPINFO startup_info = {0};
  PROCESS_INFORMATION temp_process_info = {};
  DWORD flags = CREATE_SUSPENDED;

  if (base::win::GetVersion() < base::win::VERSION_WIN8) {
    // Windows 8 implements nested jobs, but for older systems we need to
    // break out of any job we're in to enforce our restrictions.
    flags |= CREATE_BREAKAWAY_FROM_JOB;
  }

  if (!::CreateProcessAsUser(primary_token.Get(),
                             NULL,   // No application name.
                             command_line,
                             NULL,   // No security attribute.
                             NULL,   // No thread attribute.
                             FALSE,  // Do not inherit handles.
                             flags,
                             NULL,   // Use the environment of the caller.
                             NULL,   // Use current directory of the caller.
                             &startup_info,
                             &temp_process_info)) {
    return ::GetLastError();
  }
  base::win::ScopedProcessInformation process_info(temp_process_info);

  // Change the token of the main thread of the new process for the
  // impersonation token with more rights.
  {
    HANDLE temp_thread = process_info.thread_handle();
    if (!::SetThreadToken(&temp_thread, impersonation_token.Get())) {
      ::TerminateProcess(process_info.process_handle(),
                         0);  // exit code
      return ::GetLastError();
    }
  }

  err_code = job.AssignProcessToJob(process_info.process_handle());
  if (ERROR_SUCCESS != err_code) {
    ::TerminateProcess(process_info.process_handle(),
                       0);  // exit code
    return ::GetLastError();
  }

  // Start the application
  ::ResumeThread(process_info.thread_handle());

  (*job_handle_ret) = job.Detach();

  return ERROR_SUCCESS;
}

DWORD SetObjectIntegrityLabel(HANDLE handle, SE_OBJECT_TYPE type,
                              const wchar_t* ace_access,
                              const wchar_t* integrity_level_sid) {
  // Build the SDDL string for the label.
  base::string16 sddl = L"S:(";   // SDDL for a SACL.
  sddl += SDDL_MANDATORY_LABEL;   // Ace Type is "Mandatory Label".
  sddl += L";;";                  // No Ace Flags.
  sddl += ace_access;             // Add the ACE access.
  sddl += L";;;";                 // No ObjectType and Inherited Object Type.
  sddl += integrity_level_sid;    // Trustee Sid.
  sddl += L")";

  DWORD error = ERROR_SUCCESS;
  PSECURITY_DESCRIPTOR sec_desc = NULL;

  PACL sacl = NULL;
  BOOL sacl_present = FALSE;
  BOOL sacl_defaulted = FALSE;

  if (::ConvertStringSecurityDescriptorToSecurityDescriptorW(sddl.c_str(),
                                                             SDDL_REVISION,
                                                             &sec_desc, NULL)) {
    if (::GetSecurityDescriptorSacl(sec_desc, &sacl_present, &sacl,
                                    &sacl_defaulted)) {
      error = ::SetSecurityInfo(handle, type,
                                LABEL_SECURITY_INFORMATION, NULL, NULL, NULL,
                                sacl);
    } else {
      error = ::GetLastError();
    }

    ::LocalFree(sec_desc);
  } else {
    return::GetLastError();
  }

  return error;
}

const wchar_t* GetIntegrityLevelString(IntegrityLevel integrity_level) {
  switch (integrity_level) {
    case INTEGRITY_LEVEL_SYSTEM:
      return L"S-1-16-16384";
    case INTEGRITY_LEVEL_HIGH:
      return L"S-1-16-12288";
    case INTEGRITY_LEVEL_MEDIUM:
      return L"S-1-16-8192";
    case INTEGRITY_LEVEL_MEDIUM_LOW:
      return L"S-1-16-6144";
    case INTEGRITY_LEVEL_LOW:
      return L"S-1-16-4096";
    case INTEGRITY_LEVEL_BELOW_LOW:
      return L"S-1-16-2048";
    case INTEGRITY_LEVEL_UNTRUSTED:
      return L"S-1-16-0";
    case INTEGRITY_LEVEL_LAST:
      return NULL;
  }

  NOTREACHED();
  return NULL;
}
DWORD SetTokenIntegrityLevel(HANDLE token, IntegrityLevel integrity_level) {
  if (base::win::GetVersion() < base::win::VERSION_VISTA)
    return ERROR_SUCCESS;

  const wchar_t* integrity_level_str = GetIntegrityLevelString(integrity_level);
  if (!integrity_level_str) {
    // No mandatory level specified, we don't change it.
    return ERROR_SUCCESS;
  }

  PSID integrity_sid = NULL;
  if (!::ConvertStringSidToSid(integrity_level_str, &integrity_sid))
    return ::GetLastError();

  TOKEN_MANDATORY_LABEL label = {0};
  label.Label.Attributes = SE_GROUP_INTEGRITY;
  label.Label.Sid = integrity_sid;

  DWORD size = sizeof(TOKEN_MANDATORY_LABEL) + ::GetLengthSid(integrity_sid);
  BOOL result = ::SetTokenInformation(token, TokenIntegrityLevel, &label,
                                      size);
  ::LocalFree(integrity_sid);

  return result ? ERROR_SUCCESS : ::GetLastError();
}

DWORD SetProcessIntegrityLevel(IntegrityLevel integrity_level) {
  if (base::win::GetVersion() < base::win::VERSION_VISTA)
    return ERROR_SUCCESS;

  // We don't check for an invalid level here because we'll just let it
  // fail on the SetTokenIntegrityLevel call later on.
  if (integrity_level == INTEGRITY_LEVEL_LAST) {
    // No mandatory level specified, we don't change it.
    return ERROR_SUCCESS;
  }

  HANDLE token_handle;
  if (!::OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT,
                          &token_handle))
    return ::GetLastError();

  base::win::ScopedHandle token(token_handle);

  return SetTokenIntegrityLevel(token.Get(), integrity_level);
}

}  // namespace sandbox
