// Copyright 2016 The Chromium OS 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 "authpolicy/samba_interface.h"

#include <algorithm>
#include <map>
#include <string>
#include <utility>
#include <vector>

#include <base/files/file.h>
#include <base/files/file_util.h>
#include <base/files/important_file_writer.h>
#include <base/memory/ptr_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/threading/platform_thread.h>
#include <base/time/default_clock.h>
#include <base/time/time.h>
#include <policy/device_policy_impl.h>

#include "authpolicy/anonymizer.h"
#include "authpolicy/cryptohome_client.h"
#include "authpolicy/log_colors.h"
#include "authpolicy/platform_helper.h"
#include "authpolicy/process_executor.h"

namespace em = enterprise_management;

namespace authpolicy {
namespace {

// Samba configuration file data.
constexpr char kSmbConfData[] =
    "[global]\n"
    "\tnetbios name = %s\n"
    "\tsecurity = ADS\n"
    "\tworkgroup = %s\n"
    "\trealm = %s\n"
    "\tlock directory = %s\n"
    "\tinclude system krb5 conf = false\n"
    "\tcache directory = %s\n"
    "\tstate directory = %s\n"
    "\tprivate directory = %s\n"
    "\tkerberos encryption types = %s\n"
    "\tclient signing = mandatory\n"
    "\tclient min protocol = SMB2\n"
    // TODO(crbug.com/662440): Remove this line if it is no longer necessary.
    // (Make sure that Samba doesn't default to some older version)
    "\tclient max protocol = SMB3\n"
    "\tclient ipc min protocol = SMB2\n"
    "\tclient ldap sasl wrapping = sign\n";

// Fake domain SID to work around issue in Samba-4.8.6+, see
// `MaybeSetFakeDomainSid()`.
constexpr char kFakeDomainSid[] = "S-1-5-21-0000000000-0000000000-00000000";

constexpr int kFileMode_rwr = base::FILE_PERMISSION_READ_BY_USER |
                              base::FILE_PERMISSION_WRITE_BY_USER |
                              base::FILE_PERMISSION_READ_BY_GROUP;

constexpr int kFileMode_rwxrx = kFileMode_rwr |
                                base::FILE_PERMISSION_EXECUTE_BY_USER |
                                base::FILE_PERMISSION_EXECUTE_BY_GROUP;

constexpr int kFileMode_rwxrwx =
    kFileMode_rwxrx | base::FILE_PERMISSION_WRITE_BY_GROUP;

// Directories with permissions to be created. AUTHPOLICY_TMP_DIR needs group rx
// access to read smb.conf and krb5.conf and to access SAMBA_DIR, but no write
// access. The Samba directories need full group rwx access since Samba reads
// and writes files there.
constexpr struct CreateDirectories {
  Path path;
  int mode;
  bool owned_by_authpolicyd_exec;
} kDirsToCreate[] = {{Path::TEMP_DIR, kFileMode_rwxrx, false},
                     {Path::SAMBA_DIR, kFileMode_rwxrwx, false},
                     {Path::SAMBA_LOCK_DIR, kFileMode_rwxrwx, true},
                     {Path::SAMBA_CACHE_DIR, kFileMode_rwxrwx, true},
                     {Path::SAMBA_STATE_DIR, kFileMode_rwxrwx, true},
                     {Path::SAMBA_PRIVATE_DIR, kFileMode_rwxrwx, true}};

// Directory / filenames for user and device policy.
constexpr char kPRegUserDir[] = "User";
constexpr char kPRegDeviceDir[] = "Machine";
constexpr char kPRegFileName[] = "registry.pol";

// Size limit when loading the config file (256 kb).
constexpr size_t kConfigSizeLimit = 256 * 1024;

// SessionStateChanged signal payload we care about.
constexpr char kSessionStarted[] = "started";

// Maximum smbclient tries.
constexpr int kSmbClientMaxTries = 5;
// Wait interval between two smbclient tries.
constexpr base::TimeDelta kSmbClientRetryDelay =
    base::TimeDelta::FromSeconds(1);

// Check every 120 minutes whether the machine password has to be changed.
constexpr base::TimeDelta kPasswordChangeCheckRate =
    base::TimeDelta::FromMinutes(120);

// Default GPO version cache TTL. Can be overridden with the
// DeviceGpoCacheLifetime policy. Make sure the value matches the policy
// description in policy_templates.json!
constexpr base::TimeDelta kDefaultGpoVersionCacheTTL =
    base::TimeDelta::FromHours(25);

// Default auth data cache TTL. Can be overridden with the
// DeviceAuthDataCacheLifetime policy. Make sure the value matches the policy
// description in policy_templates.json!
constexpr base::TimeDelta kDefaultAuthDataCacheTTL =
    base::TimeDelta::FromHours(73);

constexpr base::TimeDelta kZeroDelta = base::TimeDelta::FromHours(0);

// Keys for interpreting net output.
constexpr char kKeyJoinAccessDenied[] = "NT_STATUS_ACCESS_DENIED";
constexpr char kKeyJoinAccessDenied2[] =
    "Failed to join domain: failed to set machine os attributes: Insufficient "
    "access";
constexpr char kKeyInvalidMachineName[] = "Improperly formed account name";
constexpr char kKeyInvalidMachineName2[] =
    "The name provided is not a properly formed account name";
constexpr char kKeyMachineNameTooLong[] = "Our netbios name can be at most";
constexpr char kKeyUserHitJoinQuota[] =
    "Insufficient quota exists to complete the operation";
constexpr char kKeyJoinFailedToFindDC[] = "failed to find DC";
constexpr char kKeyNoLogonServers[] = "No logon servers";
constexpr char kKeyJoinLogonFailure[] = "Logon failure";
constexpr char kKeyJoinLogonFailure2[] = "The attempted logon is invalid";
constexpr char kKeyJoinMustChangePassword[] = "Must change password";
constexpr char kKeyJoinMustChangePassword2[] = "password must be changed";
// Setting OU during domain join failed. More specific errors below.
constexpr char kKeyBadOuCommon[] = "failed to precreate account in ou";
// The domain join createcomputer argument specified a non-existent OU.
constexpr char kKeyBadOuNoSuchObject[] = "No such object";
// The domain join createcomputer argument syntax was invalid. Caused by some
// special characters in OU names, e.g. 'ou=123!' or 'a"b'. Seems like a Samba
// issue since OUs allow all characters and we do escape names properly.
constexpr char kKeyBadOuInvalidDnSyntax[] = "Invalid DN syntax";
// Domain join operation would have violated an attribute constraint.
constexpr char kKeyBadOuConstrainViolation[] = "Constraint violation";
// Domain join required access permissions that the user does not possess.
constexpr char kKeyBadOuInsufficientAccess[] = "Insufficient access";
// All other OU errors result in a generic ERROR_SETTING_OU_FAILED, e.g.
//  - "Referral": dc=... specification resulted in a referral to another server.
//  - "Operations error": Unspecific error.
// Keys for interpreting smbclient output.
constexpr char kKeyConnectionReset[] = "NT_STATUS_CONNECTION_RESET";
constexpr char kKeyNetworkTimeout[] = "NT_STATUS_IO_TIMEOUT";
constexpr char kKeyObjectNameNotFound[] =
    "NT_STATUS_OBJECT_NAME_NOT_FOUND opening remote file ";
constexpr char kKeyEncTypeNotSupported[] =
    "KDC has no support for encryption type";
constexpr char kKeyEncTypeNotSupported2[] =
    "The encryption type requested is not supported by the KDC";

// Replacement strings for anonymization.
constexpr char kMachineNamePlaceholder[] = "<MACHINE_NAME>";
constexpr char kLogonNamePlaceholder[] = "<USER_LOGON_NAME>";
constexpr char kGivenNamePlaceholder[] = "<USER_GIVEN_NAME>";
constexpr char kDisplayNamePlaceholder[] = "<USER_DISPLAY_NAME>";
constexpr char kSAMAccountNamePlaceholder[] = "<USER_SAM_ACCOUNT_NAME>";
constexpr char kCommonNamePlaceholder[] = "<USER_COMMON_NAME>";
constexpr char kAccountIdPlaceholder[] = "<USER_ACCOUNT_ID>";
constexpr char kWorkgroupPlaceholder[] = "<WORKGROUP>";
constexpr char kDeviceRealmPlaceholder[] = "<DEVICE_REALM>";
constexpr char kUserRealmPlaceholder[] = "<USER_REALM>";
constexpr char kForestPlaceholder[] = "<FOREST>";
constexpr char kDomainPlaceholder[] = "<DOMAIN>";
constexpr char kServerNamePlaceholder[] = "<SERVER_NAME>";
constexpr char kSiteNamePlaceholder[] = "<SITE_NAME>";
constexpr char kIpAddressPlaceholder[] = "<IP_ADDRESS>";
constexpr char kPasswordPlaceholder[] = "<PASSWORD>";

// Keys for net ads searches.
constexpr char kKeyWorkgroup[] = "Workgroup";
constexpr char kKeyAdsDnsParseRrSrv[] = "ads_dns_parse_rr_srv";
constexpr char kKeyPdcDnsName[] = "pdc_dns_name";
constexpr char kKeyAdsDcName[] = "ads_dc_name";
constexpr char kKeyPdcName[] = "pdc_name";
constexpr char kKeyServerSite[] = "server_site";
constexpr char kKeyClientSite[] = "client_site";
constexpr char kKeyForest[] = "Forest";
constexpr char kKeyDomain[] = "Domain";
constexpr char kKeyDomainController[] = "Domain Controller";
constexpr char kKeyPreWin2kDomain[] = "Pre-Win2k Domain";
constexpr char kKeyPreWin2kHostname[] = "Pre-Win2k Hostname";
constexpr char kKeyServerSiteName[] = "Server Site Name";
constexpr char kKeyClientSiteName[] = "Client Site Name";
constexpr char kKeyKdcServer[] = "KDC server";
constexpr char kKeyLdapServer[] = "LDAP server";
constexpr char kKeyLdapServerName[] = "LDAP server name";

// Kerberos encryption types strings for smb.conf.
constexpr char kEncTypesAll[] = "all";
constexpr char kEncTypesStrong[] = "strong";
constexpr char kEncTypesLegacy[] = "legacy";

// Maximum time that logging through SetDefaultLogLevel() should stay enabled.
// The method is called through the authpolicy_debug crosh command. The time is
// limited so users don't have to remember to turn logging off.
// Keep in sync with description in crosh!
constexpr int kMaxDefaultLogLevelUptimeMinutes = 30;

// Auth state backup filename in user daemon store.
constexpr char kBackupFileName[] = "user_backup_data";
constexpr int kMaxBackupSizeBytes = 4 * 1024 * 1024;

WARN_UNUSED_RESULT ErrorType GetNetError(const ProcessExecutor& executor,
                                         const std::string& net_command) {
  const std::string& net_out = executor.GetStdout();
  const std::string& net_err = executor.GetStderr();
  const std::string error_msg("net ads " + net_command + " failed: ");

  if (Contains(net_out, kKeyJoinFailedToFindDC) ||
      Contains(net_err, kKeyNoLogonServers)) {
    LOG(ERROR) << error_msg << "network problem";
    return ERROR_NETWORK_PROBLEM;
  }
  if (Contains(net_out, kKeyJoinLogonFailure) ||
      Contains(net_out, kKeyJoinLogonFailure2)) {
    LOG(ERROR) << error_msg << "logon failure";
    return ERROR_BAD_PASSWORD;
  }
  if (Contains(net_out, kKeyJoinMustChangePassword) ||
      Contains(net_out, kKeyJoinMustChangePassword2)) {
    LOG(ERROR) << error_msg << "must change password";
    return ERROR_PASSWORD_EXPIRED;
  }
  if (Contains(net_out, kKeyJoinAccessDenied) ||
      Contains(net_out, kKeyJoinAccessDenied2)) {
    LOG(ERROR) << error_msg << "user is not permitted to join the domain";
    return ERROR_JOIN_ACCESS_DENIED;
  }
  if (Contains(net_out, kKeyInvalidMachineName) ||
      Contains(net_out, kKeyInvalidMachineName2)) {
    LOG(ERROR) << error_msg << "invalid machine name";
    return ERROR_INVALID_MACHINE_NAME;
  }
  if (Contains(net_out, kKeyMachineNameTooLong)) {
    LOG(ERROR) << error_msg << "machine name is too long";
    return ERROR_MACHINE_NAME_TOO_LONG;
  }
  if (Contains(net_out, kKeyUserHitJoinQuota)) {
    LOG(ERROR) << error_msg << "user joined max number of machines";
    return ERROR_USER_HIT_JOIN_QUOTA;
  }
  if (Contains(net_out, kKeyBadOuCommon)) {
    if (Contains(net_out, kKeyBadOuNoSuchObject)) {
      LOG(ERROR) << error_msg << "computer OU does not exist";
      return ERROR_OU_DOES_NOT_EXIST;
    }
    if (Contains(net_out, kKeyBadOuInvalidDnSyntax)) {
      LOG(ERROR) << error_msg << "computer OU invalid";
      return ERROR_INVALID_OU;
    }
    if (Contains(net_out, kKeyBadOuConstrainViolation)) {
      LOG(ERROR) << error_msg << "constraint violation setting computer OU";
      return ERROR_OU_CONSTRAINT_VIOLATION;
    }
    if (Contains(net_out, kKeyBadOuInsufficientAccess)) {
      LOG(ERROR) << error_msg << "access denied setting computer OU";
      return ERROR_OU_ACCESS_DENIED;
    }
    // Fall back to generic OU error.
    LOG(ERROR) << error_msg << "setting computer OU failed, unspecified error";
    return ERROR_SETTING_OU_FAILED;
  }
  if (Contains(net_out, kKeyEncTypeNotSupported) ||
      Contains(net_out, kKeyEncTypeNotSupported2)) {
    LOG(ERROR) << error_msg << "KDC does not support encryption type";
    return ERROR_KDC_DOES_NOT_SUPPORT_ENCRYPTION_TYPE;
  }
  LOG(ERROR) << error_msg << "exit code " << executor.GetExitCode();
  return ERROR_NET_FAILED;
}

WARN_UNUSED_RESULT ErrorType
GetSmbclientError(const ProcessExecutor& smb_client_cmd) {
  const std::string& smb_client_out = smb_client_cmd.GetStdout();
  if (Contains(smb_client_out, kKeyNetworkTimeout) ||
      Contains(smb_client_out, kKeyConnectionReset)) {
    LOG(ERROR) << "smbclient failed - network problem";
    return ERROR_NETWORK_PROBLEM;
  }
  LOG(ERROR) << "smbclient failed with exit code "
             << smb_client_cmd.GetExitCode();
  return ERROR_SMBCLIENT_FAILED;
}

// Creates the given directory recursively and sets error message on failure.
WARN_UNUSED_RESULT ErrorType CreateDirectory(const base::FilePath& dir) {
  base::File::Error ferror;
  if (!base::CreateDirectoryAndGetError(dir, &ferror)) {
    LOG(ERROR) << "Failed to create directory '" << dir.value()
               << "': " << base::File::ErrorToString(ferror);
    return ERROR_LOCAL_IO;
  }
  return ERROR_NONE;
}

// Sets file permissions for a given filepath and sets error message on failure.
WARN_UNUSED_RESULT ErrorType SetFilePermissions(const base::FilePath& fp,
                                                int mode) {
  if (!base::SetPosixFilePermissions(fp, mode)) {
    LOG(ERROR) << "Failed to set permissions on '" << fp.value() << "'";
    return ERROR_LOCAL_IO;
  }
  return ERROR_NONE;
}

// Similar to |SetFilePermissions|, but sets permissions recursively up the path
// to |base_fp| (not including |base_fp|). Returns false if |base_fp| is not a
// parent of |fp|.
WARN_UNUSED_RESULT ErrorType SetFilePermissionsRecursive(
    const base::FilePath& fp, const base::FilePath& base_fp, int mode) {
  if (!base_fp.IsParent(fp)) {
    LOG(ERROR) << "Base path '" << base_fp.value() << "' is not a parent of '"
               << fp.value() << "'";
    return ERROR_LOCAL_IO;
  }
  ErrorType error = ERROR_NONE;
  for (base::FilePath curr_fp = fp; curr_fp != base_fp && error == ERROR_NONE;
       curr_fp = curr_fp.DirName()) {
    error = SetFilePermissions(curr_fp, mode);
  }
  return error;
}

// Checks whether the file at |default_level_path| exists and was last modified
// in a certain time range. If not, it is deleted to prevent that a user forgets
// to disable logging.
bool CheckFlagsDefaultLevelValid(const base::FilePath& default_level_path) {
  // Having no file is the out-of-box state with no level set, so exit quietly.
  if (!base::PathExists(default_level_path))
    return false;

  base::File::Info info;
  if (!GetFileInfo(default_level_path, &info)) {
    PLOG(ERROR) << "Failed to get file info from '"
                << default_level_path.value() << "'";
    return false;
  }

  // Check < -1 to prevent issues with clocks running backwards for a bit.
  int uptime_min = (base::Time::Now() - info.last_modified).InMinutes();
  if (uptime_min < -1 || uptime_min > kMaxDefaultLogLevelUptimeMinutes) {
    LOG(INFO) << "Removing flags default level file and resetting (uptime: "
              << uptime_min << " minutes).";
    PCHECK(base::DeleteFile(default_level_path))
        << "Failed to delete flags default level file '"
        << default_level_path.value() << "'";
    return false;
  }

  return true;
}

// Parses |gpo_policy_data| from |gpo_policy_data_blob|. Returns ERROR_NONE on
// success. Returns ERROR_PARSE_FAILED and prints an error on failure.
WARN_UNUSED_RESULT ErrorType
ParsePolicyData(const std::string& gpo_policy_data_blob,
                protos::GpoPolicyData* gpo_policy_data) {
  if (!gpo_policy_data->ParseFromString(gpo_policy_data_blob)) {
    LOG(ERROR) << "Failed to parse policy data from string";
    return ERROR_PARSE_FAILED;
  }
  return ERROR_NONE;
}

// Returns the string representation of |encryption_types| for smb.conf.
const char* GetEncryptionTypesString(KerberosEncryptionTypes encryption_types) {
  switch (encryption_types) {
    case ENC_TYPES_ALL:
      return kEncTypesAll;
    case ENC_TYPES_STRONG:
      return kEncTypesStrong;
    case ENC_TYPES_LEGACY:
      return kEncTypesLegacy;
    case ENC_TYPES_COUNT:
      NOTREACHED() << "Not a valid encryption type and will default to strong.";
      return kEncTypesStrong;
  }
  CHECK(false);
}

// Returns the value of the DeviceKerberosEncryptionTypes policy or
// ENC_TYPES_STRONG if the policy is not set or invalid.
KerberosEncryptionTypes GetEncryptionTypes(
    const em::ChromeDeviceSettingsProto& device_policy) {
  if (!device_policy.has_device_kerberos_encryption_types() ||
      !device_policy.device_kerberos_encryption_types().has_types()) {
    return ENC_TYPES_STRONG;
  }

  em::DeviceKerberosEncryptionTypesProto::Types policy_encryption_types =
      device_policy.device_kerberos_encryption_types().types();

  switch (policy_encryption_types) {
    case em::DeviceKerberosEncryptionTypesProto::ENC_TYPES_ALL:
      return ENC_TYPES_ALL;
    case em::DeviceKerberosEncryptionTypesProto::ENC_TYPES_STRONG:
      return ENC_TYPES_STRONG;
    case em::DeviceKerberosEncryptionTypesProto::ENC_TYPES_LEGACY:
      return ENC_TYPES_LEGACY;
  }

  CHECK(false);
}

// Returns the value of the DeviceUserPolicyLoopbackProcessingMode policy or
// |USER_POLICY_MODE_DEFAULT| if the policy is not.
em::DeviceUserPolicyLoopbackProcessingModeProto::Mode GetUserPolicyMode(
    const em::ChromeDeviceSettingsProto& device_policy) {
  if (!device_policy.has_device_user_policy_loopback_processing_mode() ||
      !device_policy.device_user_policy_loopback_processing_mode().has_mode()) {
    return em::DeviceUserPolicyLoopbackProcessingModeProto::
        USER_POLICY_MODE_DEFAULT;
  }
  return device_policy.device_user_policy_loopback_processing_mode().mode();
}

// Returns the value of the DeviceMachinePasswordChangeRate policy or
// |kDefaultMachinePasswordChange| if the policy is not set.
base::TimeDelta GetMachinePasswordChangeRate(
    const em::ChromeDeviceSettingsProto& device_policy) {
  if (!device_policy.has_device_machine_password_change_rate() ||
      !device_policy.device_machine_password_change_rate().has_rate_days()) {
    return kDefaultMachinePasswordChangeRate;
  }
  return base::TimeDelta::FromDays(
      device_policy.device_machine_password_change_rate().rate_days());
}

// Returns the value of the DeviceGpoCacheLifetime policy or
// |kDefaultGpoVersionCacheTTL| if the policy is not set.
base::TimeDelta GetGpoVersionCacheTTL(
    const em::ChromeDeviceSettingsProto& device_policy) {
  if (!device_policy.has_device_gpo_cache_lifetime() ||
      !device_policy.device_gpo_cache_lifetime().has_lifetime_hours()) {
    return kDefaultGpoVersionCacheTTL;
  }
  return base::TimeDelta::FromHours(
      device_policy.device_gpo_cache_lifetime().lifetime_hours());
}

// Returns the value of the DeviceAuthDataCacheLifetime policy or
// |kDefaultAuthDataCacheTTL| if the policy is not set.
base::TimeDelta GetAuthDataCacheTTL(
    const em::ChromeDeviceSettingsProto& device_policy) {
  if (!device_policy.has_device_auth_data_cache_lifetime() ||
      !device_policy.device_auth_data_cache_lifetime().has_lifetime_hours()) {
    return kDefaultAuthDataCacheTTL;
  }
  return base::TimeDelta::FromHours(
      device_policy.device_auth_data_cache_lifetime().lifetime_hours());
}

std::ostream& operator<<(std::ostream& os,
                         const ActiveDirectoryUserStatus::TgtStatus& status) {
  switch (status) {
    case ActiveDirectoryUserStatus::TGT_VALID:
      return os << "valid";
    case ActiveDirectoryUserStatus::TGT_EXPIRED:
      return os << "expired";
    case ActiveDirectoryUserStatus::TGT_NOT_FOUND:
      return os << "not found";
  }
  NOTREACHED();
  return os << "unknown";
}

std::ostream& operator<<(
    std::ostream& os, const ActiveDirectoryUserStatus::PasswordStatus& status) {
  switch (status) {
    case ActiveDirectoryUserStatus::PASSWORD_VALID:
      return os << "valid";
    case ActiveDirectoryUserStatus::PASSWORD_EXPIRED:
      return os << "expired";
    case ActiveDirectoryUserStatus::PASSWORD_CHANGED:
      return os << "changed";
  }
  NOTREACHED();
  return os << "unknown";
}

// Helper to log |status| if the |log_status| debug flag is enabled.
void LogUserStatus(const ActiveDirectoryUserStatus& status,
                   const protos::DebugFlags& flags) {
  if (!flags.log_status())
    return;

  LOG(INFO) << kColorStatus << "User Status:" << kColorReset;
  LOG(INFO) << kColorStatus << "  TGT:                  " << status.tgt_status()
            << kColorReset;
  LOG(INFO) << kColorStatus
            << "  Password:             " << status.password_status()
            << kColorReset;
  LOG(INFO) << kColorStatus << "  Password Last Set:    "
            << status.account_info().pwd_last_set() << kColorReset;
  LOG(INFO) << kColorStatus << "  User Account Control: "
            << status.account_info().user_account_control() << kColorReset;
  // Note: Don't log the other account info data, it's all PII.
}

// Logs an error in case of failure. Returns true on success.
bool ReadMachinePasswordToString(const base::FilePath& password_path,
                                 std::string* password) {
  if (!base::ReadFileToString(password_path, password)) {
    PLOG(ERROR) << "Could not read machine password file '"
                << password_path.value() << "'";
    return false;
  }
  return true;
}

}  // namespace

SambaInterface::SambaInterface(AuthPolicyMetrics* metrics,
                               const PathService* path_service,
                               const base::Closure& user_kerberos_files_changed)
    : user_account_(Path::USER_SMB_CONF),
      device_account_(Path::DEVICE_SMB_CONF),
      metrics_(metrics),
      paths_(path_service),
      anonymizer_(std::make_unique<Anonymizer>()),
      jail_helper_(paths_, &flags_, anonymizer_.get()),
      user_tgt_manager_(paths_,
                        metrics_,
                        &flags_,
                        &jail_helper_,
                        anonymizer_.get(),
                        this /* TgtManager::Delegate */,
                        Path::USER_KRB5_CONF,
                        Path::USER_CREDENTIAL_CACHE),
      device_tgt_manager_(paths_,
                          metrics_,
                          &flags_,
                          &jail_helper_,
                          anonymizer_.get(),
                          this /* TgtManager::Delegate */,
                          Path::DEVICE_KRB5_CONF,
                          Path::DEVICE_CREDENTIAL_CACHE),
      gpo_version_cache_(&flags_),
      gpo_version_cache_ttl_(kDefaultGpoVersionCacheTTL),
      auth_data_cache_(&flags_),
      auth_data_cache_ttl_(kDefaultAuthDataCacheTTL) {
  DCHECK(paths_);
  LoadFlagsDefaultLevel();
  user_tgt_manager_.SetKerberosFilesChangedCallback(
      user_kerberos_files_changed);
}

SambaInterface::~SambaInterface() = default;

ErrorType SambaInterface::Initialize(bool expect_config) {
  ReloadDebugFlags();

  ErrorType error = ERROR_NONE;
  {
    // Note: From 4.8.0 on Samba performs a strict ownership check on some
    // directories, so they have to be owned by authpolicyd-exec.
    for (const auto& dir : kDirsToCreate) {
      std::unique_ptr<ScopedSwitchToSavedUid> switch_scope;
      if (dir.owned_by_authpolicyd_exec)
        switch_scope = std::make_unique<ScopedSwitchToSavedUid>();
      const base::FilePath path(paths_->Get(dir.path));
      error = ::authpolicy::CreateDirectory(path);
      if (error != ERROR_NONE)
        return error;
      error = SetFilePermissions(path, dir.mode);
      if (error != ERROR_NONE)
        return error;
    }
  }

  if (expect_config) {
    error = ReadConfiguration();
    if (error != ERROR_NONE)
      return error;

    // Load cached auth data. It's OK if that fails, just start with an empty
    // cache.
    // NOTE: Load cache before UpdateDevicePolicyDependencies() as that may
    // modify the cache!
    base::FilePath cache_path(paths_->Get(Path::AUTH_DATA_CACHE));
    if (base::PathExists(cache_path))
      auth_data_cache_.Load(cache_path);

    // Load device policy and update stuff that depends on device policy. If
    // there's a config, it means the device is locked and there should also be
    // device policy at this point.
    std::unique_ptr<policy::DevicePolicyImpl> policy_impl =
        std::move(device_policy_impl_for_testing);
    if (!policy_impl)
      policy_impl = std::make_unique<policy::DevicePolicyImpl>();
    if (!policy_impl->LoadPolicy()) {
      LOG(ERROR) << "Failed to load device policy. Authentication and policy "
                    "fetch might behave unexpectedly until the next device "
                    "policy fetch.";
    }

    // Call this even when loading failed to get the defaults right (e.g.
    // turn on machine password auto renewal).
    UpdateDevicePolicyDependencies(policy_impl->get_device_policy());
  }

  return ERROR_NONE;
}

void SambaInterface::SetCryptohomeClient(
    std::unique_ptr<CryptohomeClient> cryptohome_client) {
  cryptohome_client_ = std::move(cryptohome_client);
}

// static
bool SambaInterface::CleanState(const PathService* path_service) {
  // Note: We're not permitted to delete the folder and DeleteFile apparently
  // doesn't support wildcards, so DeleteFile returns false.
  DCHECK(path_service);
  const base::FilePath state_dir(path_service->Get(Path::STATE_DIR));
  base::DeletePathRecursively(state_dir);
  if (!base::IsDirectoryEmpty(state_dir)) {
    LOG(ERROR) << "Failed to clean state dir '" << state_dir.value() << "'";
    return false;
  }
  return true;
}

ErrorType SambaInterface::AuthenticateUser(
    const std::string& user_principal_name,
    const std::string& account_id,
    int password_fd,
    ActiveDirectoryAccountInfo* account_info) {
  ReloadDebugFlags();

  ErrorType error = AuthenticateUserInternal(user_principal_name, account_id,
                                             password_fd, account_info);

  last_auth_error_ = error;
  return error;
}

ErrorType SambaInterface::AuthenticateUserInternal(
    const std::string& user_principal_name,
    const std::string& account_id,
    int password_fd,
    ActiveDirectoryAccountInfo* account_info) {
  if (!account_id.empty())
    SetUserAccountId(account_id);

  // We technically don't have to be in joined state, but check it anyway,
  // because the device should always be joined during auth.
  if (!IsDeviceJoined())
    return ERROR_NOT_JOINED;

  // Split user_principal_name into parts and normalize.
  std::string user_name, user_realm, normalized_upn;
  if (!ParseUserPrincipalName(user_principal_name, &user_name, &user_realm,
                              &normalized_upn)) {
    return ERROR_PARSE_UPN_FAILED;
  }
  SetUserRealm(user_realm);
  user_tgt_manager_.SetPrincipal(normalized_upn);

  // Clean up auth data cache.
  auth_data_cache_.RemoveEntriesOlderThan(auth_data_cache_ttl_);

  // Acquire Kerberos ticket-granting-ticket for the user account.
  ErrorType error = AcquireUserTgt(password_fd);
  if (error != ERROR_NONE)
    return error;

  // Get account info for the user.
  error = GetAccountInfo(user_name, normalized_upn, account_id, account_info);
  if (error != ERROR_NONE)
    return error;

  // Renew TGT periodically. The usual validity lifetime is 1 day, so this won't
  // happen too often. There's a corner-case if pwdLastSet or userAccountControl
  // are missing, see crbug.com/795758. In that case, GetUserStatus cannot
  // determine the password validity and just *assumes* it's valid. However, the
  // AD admin might have requested the user to change their password. To limit
  // the impact, don't renew the TGT automatically, so that the user will be
  // prompted to relog after 1 day instead of the renewal lifetime of usually 1
  // week.
  bool should_auto_renew = account_info->has_pwd_last_set() &&
                           account_info->has_user_account_control();
  LOG_IF(WARNING, !should_auto_renew)
      << "pwdLastSet or userAccountControl fields missing. Will not "
         "be able to determine password validity. Turning off TGT "
         "renewal to limit lifetime.";
  user_tgt_manager_.EnableTgtAutoRenewal(should_auto_renew);

  if (account_id.empty())
    SetUserAccountId(account_info->account_id());

  // Store sAMAccountName for policy fetch. Note that net ads gpo list always
  // wants the sAMAccountName. Also note that pwd_last_set is zero and stale
  // at this point if AcquireTgtWithPassword() set a new password, but that's
  // fine, the timestamp is updated in the next GetUserStatus() call.
  user_account_.user_name = account_info->sam_account_name();
  if (account_info->has_pwd_last_set())
    user_pwd_last_set_ = account_info->pwd_last_set();
  user_logged_in_ = true;

  // Backup state on user's Cryptohome.
  MaybeBackupUserAuthState();

  // Collecting metrics with the encryption types used during this successful
  // login. This value has been set through the DeviceKerberosEncryptionTypes
  // policy.
  metrics_->ReportEncryptionType(ENC_TYPES_OF_AUTHENTICATE_USER,
                                 encryption_types_);

  return ERROR_NONE;
}

ErrorType SambaInterface::GetUserStatus(
    const std::string& user_principal_name,
    const std::string& account_id,
    ActiveDirectoryUserStatus* user_status) {
  ReloadDebugFlags();
  SetUserAccountId(account_id);
  user_status->Clear();

  // Try to restore TGT if it doesn't exist. The TGT is required for reading the
  // account info below.
  MaybeRestoreUserAuthState();

  // We technically don't have to be in joined state, but check it anyway,
  // because the device should always be joined during getting status.
  if (!IsDeviceJoined())
    return ERROR_NOT_JOINED;

  // Split user_principal_name into parts and normalize.
  std::string user_name, user_realm, normalized_upn;
  if (!ParseUserPrincipalName(user_principal_name, &user_name, &user_realm,
                              &normalized_upn)) {
    return ERROR_PARSE_UPN_FAILED;
  }
  SetUserRealm(user_realm);

  // Tell Chrome that the password expired in case the TGT is not valid and the
  // GetUserPasswordStatus() call below doesn't happen. See crbug.com/849318.
  if (last_auth_error_ == ERROR_PASSWORD_EXPIRED) {
    user_status->set_password_status(
        ActiveDirectoryUserStatus::PASSWORD_EXPIRED);
  }

  // If authentication failed with bad password, but the session was still
  // started and Cryptohome could be unmounted, it means that the logon password
  // must have been a valid, old password and the password must have changed on
  // the server.
  if (last_auth_error_ == ERROR_BAD_PASSWORD) {
    user_status->set_password_status(
        ActiveDirectoryUserStatus::PASSWORD_CHANGED);
  }

  // Determine the status of the TGT.
  ActiveDirectoryUserStatus::TgtStatus tgt_status =
      ActiveDirectoryUserStatus::TGT_VALID;
  ErrorType error = GetUserTgtStatus(&tgt_status);
  if (error != ERROR_NONE) {
    LogUserStatus(*user_status, flags_);
    return error;
  }
  user_status->set_tgt_status(tgt_status);

  // If we don't have a valid TGT, we can't GetAccountInfo() because that uses
  // the TGT to authenticate. Thus, just return the TGT status and the last auth
  // error.
  if (tgt_status != ActiveDirectoryUserStatus::TGT_VALID) {
    // Just try to ping the server here. Otherwise, Chrome shows a popup that
    // the user has to relog in order to get a new TGT, but AuthenticateUser()
    // fails if the server is unavailable and the popup is shown again.
    // See crbug.com/844662.
    LogUserStatus(*user_status, flags_);
    return PingServer(&user_account_);
  }

  // Update smb.conf, IPs, server names etc. for the user account.
  error = UpdateAccountData(&user_account_);
  if (error != ERROR_NONE) {
    LogUserStatus(*user_status, flags_);
    return error;
  }

  // Get account info for the user.
  ActiveDirectoryAccountInfo account_info;
  error =
      GetAccountInfo("" /* user_name unused */, "" /* normalized_upn unused */,
                     account_id, &account_info);
  if (error != ERROR_NONE) {
    LogUserStatus(*user_status, flags_);
    return error;
  }
  *user_status->mutable_account_info() = account_info;

  // Determine the status of the password.
  ActiveDirectoryUserStatus::PasswordStatus password_status =
      GetUserPasswordStatus(account_info);
  user_status->set_password_status(password_status);

  LogUserStatus(*user_status, flags_);
  return ERROR_NONE;
}

ErrorType SambaInterface::GetUserKerberosFiles(const std::string& account_id,
                                               KerberosFiles* files) {
  ReloadDebugFlags();
  SetUserAccountId(account_id);

  // Try to restore TGT, user_account_id_ etc. if it doesn't exist.
  MaybeRestoreUserAuthState();

  return user_tgt_manager_.GetKerberosFiles(files);
}

ErrorType SambaInterface::JoinMachine(
    const std::string& machine_name,
    const std::string& machine_domain,
    const std::vector<std::string>& machine_ou,
    const std::string& user_principal_name,
    KerberosEncryptionTypes encryption_types,
    int password_fd,
    std::string* joined_domain) {
  ReloadDebugFlags();

  // Prevent joining a second time for security reasons (a hacked Chrome might
  // call this).
  if (IsDeviceJoined())
    return ERROR_ALREADY_JOINED;

  // Split user_principal_name into parts and normalize.
  std::string user_name, user_realm, normalized_upn;
  if (!ParseUserPrincipalName(user_principal_name, &user_name, &user_realm,
                              &normalized_upn)) {
    return ERROR_PARSE_UPN_FAILED;
  }
  AnonymizeRealm(user_realm, kUserRealmPlaceholder);
  anonymizer_->SetReplacement(user_name, kSAMAccountNamePlaceholder);

  std::string join_realm;
  if (!machine_domain.empty()) {
    // Join machine to the given domain (note: realm and domain is the same).
    join_realm = base::ToUpperASCII(machine_domain);
    AnonymizeRealm(join_realm, kDeviceRealmPlaceholder);
  } else {
    // By default, join machine to the user's realm.
    join_realm = user_realm;
  }

  // The netbios name in smb.conf needs to be upper-case, but there is also
  // Samba code that logs the machine name lower-case, so add both here.
  anonymizer_->SetReplacementAllCases(machine_name, kMachineNamePlaceholder);

  // Wipe and (re-)create config. Note that all session data is wiped to make
  // testing easier.
  Reset();
  InitDeviceAccount(base::ToUpperASCII(machine_name), join_realm);

  // Note: Encryption types stay valid through the initial device policy fetch,
  // which, if it succeeds, resets or updates the value.
  SetKerberosEncryptionTypes(encryption_types);

  // Update smb.conf, IPs, server names etc. for the device account.
  ErrorType error = UpdateAccountData(&device_account_);
  if (error != ERROR_NONE) {
    Reset();
    return error;
  }

  // Call net ads join to join the machine to the Active Directory domain.
  ProcessExecutor net_cmd({paths_->Get(Path::NET), "ads", "join", kUserParam,
                           normalized_upn, kKerberosParam, kConfigParam,
                           paths_->Get(Path::DEVICE_SMB_CONF), kDebugParam,
                           flags_.net_log_level(), kMachinepassStdinParam});
  if (!machine_ou.empty()) {
    net_cmd.PushArg(kCreatecomputerParam +
                    BuildDistinguishedName(machine_ou, join_realm));
  }
  const std::string os_name = GetOsName();
  const std::string os_version = GetOsVersion();
  if (!os_name.empty() && !os_version.empty()) {
    // Both must be specified for the params to take effect.
    net_cmd.PushArg(kOsNameParam + os_name);
    net_cmd.PushArg(kOsVersionParam + os_version);
    // Prevent Samba from setting "Samba x.x.x" here.
    net_cmd.PushArg(kOsServicePackParam);
  }

  // The machine password and the user password are read from stdin.
  const std::string machine_pass = GenerateRandomMachinePassword();
  anonymizer_->SetReplacement(machine_pass, kPasswordPlaceholder);
  base::ScopedFD passwords_pipe =
      WriteStringAndPipeToPipe(machine_pass + "\n", password_fd);
  net_cmd.SetInputFile(passwords_pipe.get());
  if (!jail_helper_.SetupJailAndRun(&net_cmd, Path::NET_ADS_SECCOMP,
                                    TIMER_NET_ADS_JOIN)) {
    Reset();
    return GetNetError(net_cmd, "join");
  }

  // Store the machine password.
  error = WriteMachinePassword(Path::MACHINE_PASS, machine_pass);
  if (error != ERROR_NONE) {
    Reset();
    return error;
  }

  // Store configuration for subsequent runs of the daemon.
  error = WriteConfiguration();
  if (error != ERROR_NONE) {
    Reset();
    return error;
  }

  // Cache auth data. Note that users in the device realm are always affiliated.
  UpdateAuthDataCache(device_account_, true /* is_affiliated */);

  // Since we just created the account, set propagation retry to give the
  // password time to propagate through Active Directory.
  device_tgt_manager_.SetPropagationRetry(true);

  // Only if everything worked out, keep the config.
  if (joined_domain)
    *joined_domain = join_realm;

  // Collecting metrics with the encryption types used during this successful
  // enrollment. This value has been set through the advanced settings of the
  // domain join screen.
  metrics_->ReportEncryptionType(ENC_TYPES_OF_JOIN_AD_DOMAIN,
                                 encryption_types_);

  return ERROR_NONE;
}

ErrorType SambaInterface::FetchUserGpos(
    const std::string& account_id, protos::GpoPolicyData* gpo_policy_data) {
  ReloadDebugFlags();
  SetUserAccountId(account_id);

  // Try to restore TGT, user_account_id_ etc. if it doesn't exist.
  MaybeRestoreUserAuthState();

  if (!user_logged_in_) {
    LOG(ERROR) << "User not logged in. Did AuthenticateUser() fail?";
    return ERROR_NOT_LOGGED_IN;
  }
  DCHECK(!user_account_.user_name.empty());
  DCHECK(!user_account_.realm.empty());

  // We need user_policy_mode_ to properly fetch user policy, which is read from
  // device policy.
  if (!has_device_policy_) {
    LOG(ERROR) << "Unknown user policy mode. Did FetchDeviceGpos() fail?";
    return ERROR_NO_DEVICE_POLICY;
  }

  // Download GPOs for the given user, taking the loopback processing |mode|
  // into account:
  //   USER_POLICY_MODE_DEFAULT: Process user GPOs as usual.
  //   USER_POLICY_MODE_MERGE:   Apply user policy from device GPOs on top of
  //                             user policy from user GPOs.
  //   USER_POLICY_MODE_REPLACE: Only apply user policy from device GPOs.
  ErrorType error;
  std::vector<base::FilePath> gpo_file_paths;
  if (user_policy_mode_ != em::DeviceUserPolicyLoopbackProcessingModeProto::
                               USER_POLICY_MODE_REPLACE) {
    // Update smb.conf, IPs, server names etc for the user account.
    error = UpdateAccountData(&user_account_);
    if (error != ERROR_NONE)
      return error;

    // Download user GPOs with user policy data.
    error = GetGpos(GpoSource::USER, PolicyScope::USER, &gpo_file_paths);
    if (error != ERROR_NONE)
      return error;
  }
  if (user_policy_mode_ != em::DeviceUserPolicyLoopbackProcessingModeProto::
                               USER_POLICY_MODE_DEFAULT) {
    // Acquire Kerberos ticket-granting-ticket for the device account.
    error = AcquireDeviceTgt();
    if (error != ERROR_NONE)
      return error;

    // Download device GPOs with user policy data.
    // Note that device account data was updated by calling `AcquireDeviceTgt()`
    // above.
    error = GetGpos(GpoSource::MACHINE, PolicyScope::USER, &gpo_file_paths);
    if (error != ERROR_NONE)
      return error;
  }

  // Parse GPOs and store them in a user+extension policy protobuf.
  std::string gpo_policy_data_blob;
  error = ParseGposIntoProtobuf(gpo_file_paths, kCmdParseUserPreg,
                                &gpo_policy_data_blob);
  if (error != ERROR_NONE)
    return error;

  error = ParsePolicyData(gpo_policy_data_blob, gpo_policy_data);
  if (error != ERROR_NONE)
    return error;

  return ERROR_NONE;
}

ErrorType SambaInterface::FetchDeviceGpos(
    protos::GpoPolicyData* gpo_policy_data) {
  ReloadDebugFlags();

  // Check if the device is domain joined.
  if (!IsDeviceJoined())
    return ERROR_NOT_JOINED;

  // Acquire Kerberos ticket-granting-ticket for the device account.
  ErrorType error = AcquireDeviceTgt();
  if (error != ERROR_NONE)
    return error;

  // Download device GPOs with device policy data.
  // Note that account data was updated by calling `AcquireDeviceTgt()` above.
  std::vector<base::FilePath> gpo_file_paths;
  error = GetGpos(GpoSource::MACHINE, PolicyScope::MACHINE, &gpo_file_paths);
  if (error != ERROR_NONE)
    return error;

  // Parse GPOs and store them in a device+extension policy protobuf.
  std::string gpo_policy_data_blob;
  error = ParseGposIntoProtobuf(gpo_file_paths, kCmdParseDevicePreg,
                                &gpo_policy_data_blob);
  if (error != ERROR_NONE)
    return error;

  error = ParsePolicyData(gpo_policy_data_blob, gpo_policy_data);
  if (error != ERROR_NONE)
    return error;

  // Update stuff that depends on device policy.
  em::ChromeDeviceSettingsProto device_policy;
  if (!device_policy.ParseFromString(
          gpo_policy_data->user_or_device_policy())) {
    LOG(ERROR) << "Failed to parse device policy";
    return ERROR_PARSE_FAILED;
  }
  UpdateDevicePolicyDependencies(device_policy);

  return ERROR_NONE;
}

void SambaInterface::OnSessionStateChanged(const std::string& state) {
  LOG(INFO) << "Session state changed to '" << state << "'";
  in_user_session_ = state == kSessionStarted;
  MaybeBackupUserAuthState();
}

void SambaInterface::SetDefaultLogLevel(AuthPolicyFlags::DefaultLevel level) {
  flags_default_level_ = level;
  LOG(INFO) << "Flags default level = " << flags_default_level_;
  SaveFlagsDefaultLevel();
}

std::string SambaInterface::GetUserPrincipal() const {
  return user_account_.GetPrincipal();
}

void SambaInterface::OnTgtRenewed() {
  MaybeBackupUserAuthState();
}

void SambaInterface::DisableRetrySleepForTesting() {
  retry_sleep_disabled_for_testing_ = true;
  device_tgt_manager_.DisableRetrySleepForTesting();
}

ErrorType SambaInterface::RenewUserTgtForTesting() {
  return user_tgt_manager_.RenewTgt();
}

void SambaInterface::SetDevicePolicyImplForTesting(
    std::unique_ptr<policy::DevicePolicyImpl> policy_impl) {
  device_policy_impl_for_testing = std::move(policy_impl);
}

void SambaInterface::ResetForTesting() {
  Reset();
}

ErrorType SambaInterface::ChangeMachinePasswordForTesting() {
  const base::FilePath password_path(paths_->Get(Path::MACHINE_PASS));
  std::string old_password;
  if (!ReadMachinePasswordToString(password_path, &old_password))
    return ERROR_LOCAL_IO;

  auto stored_password_change_rate_ = password_change_rate_;
  password_change_rate_ = base::TimeDelta::FromMilliseconds(1);
  ErrorType error = CheckMachinePasswordChange();
  password_change_rate_ = stored_password_change_rate_;
  if (error != ERROR_NONE)
    return error;

  std::string new_password;
  if (!ReadMachinePasswordToString(password_path, &new_password))
    return ERROR_LOCAL_IO;

  if (new_password == old_password)
    return ERROR_KPASSWD_FAILED;

  return ERROR_NONE;
}

ErrorType SambaInterface::UpdateKdcIpAndServerTime(AccountData* account) const {
  // Look up KDC IP from cache.
  if (account->kdc_ip.empty()) {
    base::Optional<std::string> kdc_ip =
        auth_data_cache_.GetKdcIp(account->realm);
    if (kdc_ip) {
      account->kdc_ip = std::move(*kdc_ip);
      anonymizer_->SetReplacementAllCases(account->kdc_ip,
                                          kIpAddressPlaceholder);
    }
  }

  // Use cached KDC IP and server time. Caching server time seems weird since it
  // changes constantly, but most code doesn't need server time. If an
  // up-to-date server time is needed, just reset it to base::Time() before
  // calling UpdateAccountData();
  if (!account->kdc_ip.empty() && !account->server_time.is_null())
    return ERROR_NONE;

  // Call net ads info to get the KDC IP.
  const std::string& smb_conf_path = paths_->Get(account->smb_conf_path);
  authpolicy::ProcessExecutor net_cmd({paths_->Get(Path::NET), "ads", "info",
                                       kConfigParam, smb_conf_path, kDebugParam,
                                       flags_.net_log_level()});
  // Replace a few values immediately in the net_cmd output, see
  // SearchAccountInfo for an explanation.
  anonymizer_->ReplaceSearchArg(kKeyKdcServer, kIpAddressPlaceholder);
  anonymizer_->ReplaceSearchArg(kKeyLdapServer, kIpAddressPlaceholder);
  anonymizer_->ReplaceSearchArg(kKeyLdapServerName, kServerNamePlaceholder);
  const bool net_result = jail_helper_.SetupJailAndRun(
      &net_cmd, Path::NET_ADS_SECCOMP, TIMER_NET_ADS_INFO);
  anonymizer_->ResetSearchArgReplacements();
  if (!net_result)
    return GetNetError(net_cmd, "info");
  const std::string& net_out = net_cmd.GetStdout();

  // Parse the output to find the KDC IP. Enclose in a sandbox for security
  // considerations.
  ProcessExecutor parse_cmd(
      {paths_->Get(Path::PARSER), kCmdParseServerInfo, SerializeFlags(flags_)});
  parse_cmd.SetInputString(net_out);
  if (!jail_helper_.SetupJailAndRun(&parse_cmd, Path::PARSER_SECCOMP,
                                    TIMER_NONE)) {
    // Log net output if it hasn't been done yet.
    net_cmd.LogOutputOnce();
    LOG(ERROR) << "authpolicy_parser parse_server_info failed with exit code "
               << parse_cmd.GetExitCode();
    return ERROR_PARSE_FAILED;
  }

  protos::ServerInfo server_info;
  if (!server_info.ParseFromString(parse_cmd.GetStdout())) {
    // Log net output if it hasn't been done yet.
    net_cmd.LogOutputOnce();
    LOG(ERROR) << "Failed to parse server info protobuf";
    return ERROR_PARSE_FAILED;
  }

  account->kdc_ip = server_info.kdc_ip();
  account->server_time =
      base::Time::FromInternalValue(server_info.server_time());

  // Explicitly set replacements again, see SearchAccountInfo for an
  // explanation.
  anonymizer_->SetReplacementAllCases(account->kdc_ip, kIpAddressPlaceholder);

  return ERROR_NONE;
}

ErrorType SambaInterface::UpdateDcName(AccountData* account) const {
  // Look up DC name from cache.
  if (account->dc_name.empty()) {
    base::Optional<std::string> dc_name =
        auth_data_cache_.GetDcName(account->realm);
    if (dc_name) {
      account->dc_name = std::move(*dc_name);
      anonymizer_->SetReplacementAllCases(account->dc_name,
                                          kServerNamePlaceholder);
    }
  }

  // Use cached DC name.
  if (!account->dc_name.empty())
    return ERROR_NONE;

  // Call net ads lookup to get the domain controller name.
  const std::string& smb_conf_path = paths_->Get(account->smb_conf_path);
  authpolicy::ProcessExecutor net_cmd({paths_->Get(Path::NET), "ads", "lookup",
                                       kConfigParam, smb_conf_path, kDebugParam,
                                       flags_.net_log_level()});
  // Replace a few values immediately in the net_cmd output, see
  // SearchAccountInfo for an explanation.
  anonymizer_->ReplaceSearchArg(kKeyForest, kForestPlaceholder);
  anonymizer_->ReplaceSearchArg(kKeyDomain, kDomainPlaceholder);
  anonymizer_->ReplaceSearchArg(kKeyDomainController, kServerNamePlaceholder);
  anonymizer_->ReplaceSearchArg(kKeyPreWin2kDomain, kDomainPlaceholder);
  anonymizer_->ReplaceSearchArg(kKeyPreWin2kHostname, kServerNamePlaceholder);
  anonymizer_->ReplaceSearchArg(kKeyServerSiteName, kSiteNamePlaceholder);
  anonymizer_->ReplaceSearchArg(kKeyClientSiteName, kSiteNamePlaceholder);
  const bool net_result = jail_helper_.SetupJailAndRun(
      &net_cmd, Path::NET_ADS_SECCOMP, TIMER_NET_ADS_INFO);
  anonymizer_->ResetSearchArgReplacements();
  if (!net_result)
    return GetNetError(net_cmd, "lookup");
  const std::string& net_out = net_cmd.GetStdout();

  // Parse the output to find the domain controller name. Enclose in a sandbox
  // for security considerations.
  ProcessExecutor parse_cmd(
      {paths_->Get(Path::PARSER), kCmdParseDcName, SerializeFlags(flags_)});
  parse_cmd.SetInputString(net_out);
  if (!jail_helper_.SetupJailAndRun(&parse_cmd, Path::PARSER_SECCOMP,
                                    TIMER_NONE)) {
    // Log net output if it hasn't been done yet.
    net_cmd.LogOutputOnce();
    LOG(ERROR) << "authpolicy_parser parse_dc_name failed with exit code "
               << parse_cmd.GetExitCode();
    return ERROR_PARSE_FAILED;
  }
  account->dc_name = parse_cmd.GetStdout();

  // Explicitly set replacements again, see SearchAccountInfo for an
  // explanation.
  anonymizer_->SetReplacementAllCases(account->dc_name, kServerNamePlaceholder);

  return ERROR_NONE;
}

ErrorType SambaInterface::GetUserTgtStatus(
    ActiveDirectoryUserStatus::TgtStatus* tgt_status) {
  protos::TgtLifetime lifetime;
  ErrorType error = user_tgt_manager_.GetTgtLifetime(&lifetime);
  switch (error) {
    case ERROR_NONE:
      *tgt_status = lifetime.validity_seconds() > 0
                        ? ActiveDirectoryUserStatus::TGT_VALID
                        : ActiveDirectoryUserStatus::TGT_EXPIRED;
      return ERROR_NONE;
    // Eat two errors and convert them to TgtStatus values instead.
    case ERROR_NO_CREDENTIALS_CACHE_FOUND:
      *tgt_status = ActiveDirectoryUserStatus::TGT_NOT_FOUND;
      return ERROR_NONE;
    case ERROR_KERBEROS_TICKET_EXPIRED:
      *tgt_status = ActiveDirectoryUserStatus::TGT_EXPIRED;
      return ERROR_NONE;
    default:
      return error;
  }
}

ActiveDirectoryUserStatus::PasswordStatus SambaInterface::GetUserPasswordStatus(
    const ActiveDirectoryAccountInfo& account_info) {
  // See https://msdn.microsoft.com/en-us/library/ms679430(v=vs.85).aspx.

  // Gracefully handle missing fields, see crbug.com/795758.
  if (!account_info.has_pwd_last_set() ||
      !account_info.has_user_account_control()) {
    return ActiveDirectoryUserStatus::PASSWORD_VALID;
  }

  // Password is always valid if it never expires.
  if ((account_info.user_account_control() & UF_DONT_EXPIRE_PASSWD) != 0)
    return ActiveDirectoryUserStatus::PASSWORD_VALID;

  // Password expired, user will have to enter a new password.
  if (account_info.pwd_last_set() == 0)
    return ActiveDirectoryUserStatus::PASSWORD_EXPIRED;

  // Memorize pwd_last_set if it wasn't set yet. This happens after the password
  // expired and was reset by AuthenticateUser().
  if (user_pwd_last_set_ == 0) {
    user_pwd_last_set_ = account_info.pwd_last_set();
    return ActiveDirectoryUserStatus::PASSWORD_VALID;
  }

  // Password changed on the server. Note: Don't update pwd_last_set_ here,
  // update it in AuthenticateUser() when we know that Chrome sent the right
  // password.
  if (user_pwd_last_set_ != account_info.pwd_last_set())
    return ActiveDirectoryUserStatus::PASSWORD_CHANGED;

  // pwd_last_set did not change, password is still valid.
  return ActiveDirectoryUserStatus::PASSWORD_VALID;
}

ErrorType SambaInterface::UpdateWorkgroup(AccountData* account) const {
  // Look up workgroup from cache.
  if (account->workgroup.empty()) {
    base::Optional<std::string> workgroup =
        auth_data_cache_.GetWorkgroup(account->realm);
    if (workgroup) {
      account->workgroup = std::move(*workgroup);
      anonymizer_->SetReplacement(account->workgroup, kWorkgroupPlaceholder);
    }
  }

  // Use cached workgroup.
  if (!account->workgroup.empty())
    return ERROR_NONE;

  const std::string& smb_conf_path = paths_->Get(account->smb_conf_path);
  ProcessExecutor net_cmd({paths_->Get(Path::NET), "ads", "workgroup",
                           kConfigParam, smb_conf_path, kDebugParam,
                           flags_.net_log_level()});
  // Parse workgroup from the net_cmd output immediately, see SearchAccountInfo
  // for an explanation. Also replace a bunch of other server names.
  anonymizer_->ReplaceSearchArg(kKeyWorkgroup, kWorkgroupPlaceholder);
  anonymizer_->ReplaceSearchArg(kKeyAdsDnsParseRrSrv, kServerNamePlaceholder,
                                "Parsed (.+?)\\.");
  anonymizer_->ReplaceSearchArg(kKeyPdcDnsName, kServerNamePlaceholder,
                                "'(.+)'");
  anonymizer_->ReplaceSearchArg(kKeyAdsDcName, kServerNamePlaceholder,
                                "using server='(.+?)\\.");
  anonymizer_->ReplaceSearchArg(kKeyPdcName, kServerNamePlaceholder, "'(.+)'");
  anonymizer_->ReplaceSearchArg(kKeyServerSite, kSiteNamePlaceholder, "'(.+)'");
  anonymizer_->ReplaceSearchArg(kKeyClientSite, kSiteNamePlaceholder, "'(.+)'");
  const bool net_result = jail_helper_.SetupJailAndRun(
      &net_cmd, Path::NET_ADS_SECCOMP, TIMER_NET_ADS_WORKGROUP);
  anonymizer_->ResetSearchArgReplacements();
  if (!net_result)
    return GetNetError(net_cmd, "workgroup");
  const std::string& net_out = net_cmd.GetStdout();

  // Parse the output to find the workgroup. Enclose in a sandbox for security
  // considerations.
  ProcessExecutor parse_cmd(
      {paths_->Get(Path::PARSER), kCmdParseWorkgroup, SerializeFlags(flags_)});
  parse_cmd.SetInputString(net_out);
  if (!jail_helper_.SetupJailAndRun(&parse_cmd, Path::PARSER_SECCOMP,
                                    TIMER_NONE)) {
    LOG(ERROR) << "authpolicy_parser parse_workgroup failed with exit code "
               << parse_cmd.GetExitCode();
    return ERROR_PARSE_FAILED;
  }
  account->workgroup = parse_cmd.GetStdout();

  // Explicitly set replacements again, see SearchAccountInfo for an
  // explanation.
  anonymizer_->SetReplacement(account->workgroup, kWorkgroupPlaceholder);
  return ERROR_NONE;
}

ErrorType SambaInterface::WriteSmbConf(const AccountData& account) const {
  // account.netbios_name and account.workgroup may be empty at this point.
  DCHECK(!account.realm.empty());

  std::string data = base::StringPrintf(
      kSmbConfData, account.netbios_name.c_str(), account.workgroup.c_str(),
      account.realm.c_str(), paths_->Get(Path::SAMBA_LOCK_DIR).c_str(),
      paths_->Get(Path::SAMBA_CACHE_DIR).c_str(),
      paths_->Get(Path::SAMBA_STATE_DIR).c_str(),
      paths_->Get(Path::SAMBA_PRIVATE_DIR).c_str(),
      GetEncryptionTypesString(encryption_types_));

  const base::FilePath smbconf_path(paths_->Get(account.smb_conf_path));
  const int data_size = static_cast<int>(data.size());
  if (base::WriteFile(smbconf_path, data.data(), data_size) != data_size) {
    LOG(ERROR) << "Failed to write Samba conf file '" << smbconf_path.value()
               << "'";
    return ERROR_LOCAL_IO;
  }

  return ERROR_NONE;
}

ErrorType SambaInterface::UpdateAccountData(AccountData* account) {
  // Write smb.conf for UpdateWorkgroup().
  ErrorType error = WriteSmbConf(*account);
  if (error != ERROR_NONE)
    return error;

  // Update |account|->workgroup.
  const std::string prev_workgroup = account->workgroup;
  error = UpdateWorkgroup(account);
  if (error != ERROR_NONE)
    return error;

  // Write smb.conf again for the rest in case the workgroup changed.
  if (account->workgroup != prev_workgroup) {
    error = WriteSmbConf(*account);
    if (error != ERROR_NONE)
      return error;
  }

  // Set fake domain SID if it was not set for this account workgroup yet.
  // This is workaround for Samba 4.8.6+, see `MaybeSetFakeDomainSid()`
  // description.
  error = MaybeSetFakeDomainSid(*account);
  if (error != ERROR_NONE)
    return error;

  // Query the key distribution center IP and server time and store them in
  // |account|->kdc_ip and |account|->server_time, respectively.
  error = UpdateKdcIpAndServerTime(account);
  if (error != ERROR_NONE)
    return error;

  // Query the domain controller name and store it in |account|->dc_name.
  error = UpdateDcName(account);
  if (error != ERROR_NONE)
    return error;

  return ERROR_NONE;
}

ErrorType SambaInterface::PingServer(AccountData* account) {
  // Write smb.conf for UpdateWorkgroup().
  ErrorType error = WriteSmbConf(*account);
  if (error != ERROR_NONE)
    return error;

  // Update |account|->workgroup. Make sure to invalidate the workgroup and
  // disable the cache, so that the server is actually hit.
  std::string prev_workgroup;
  prev_workgroup.swap(account->workgroup);
  bool prev_enabled = auth_data_cache_.IsEnabled();
  auth_data_cache_.SetEnabled(false);

  error = UpdateWorkgroup(account);

  auth_data_cache_.SetEnabled(prev_enabled);
  prev_workgroup.swap(account->workgroup);
  return error;
}

bool SambaInterface::IsUserAffiliated() {
  // Check cache first.
  base::Optional<bool> cached_is_affiliated =
      auth_data_cache_.GetIsAffiliated(user_account_.realm);
  if (cached_is_affiliated) {
    // Right now, only affiliated realms should be cached (but we'll keep it
    // generic, anyway, in case that changes in the future).
    CHECK(*cached_is_affiliated)
        << "Caching for unaffiliated realms not supported";
    return *cached_is_affiliated;
  }

  // Users on device realm are always affiliated.
  if (user_account_.realm == device_account_.realm)
    return true;

  // Call net ads search using
  //   - the device smb.conf, but
  //   - the user's credentials!
  // This enforces a trust check, which tells us about affiliation.
  const std::string& smb_conf_path = paths_->Get(device_account_.smb_conf_path);
  std::string search_string = base::StringPrintf(
      "(sAMAccountName=%s)", device_account_.user_name.c_str());
  ProcessExecutor net_cmd({paths_->Get(Path::NET), "ads", "search",
                           search_string, kSearchSAMAccountName, kConfigParam,
                           smb_conf_path, kDebugParam, flags_.net_log_level(),
                           kKerberosParam});
  net_cmd.SetEnv(kKrb5CCEnvKey,
                 paths_->Get(user_tgt_manager_.GetCredentialCachePath()));
  const bool net_result = jail_helper_.SetupJailAndRun(
      &net_cmd, Path::NET_ADS_SECCOMP, TIMER_NET_ADS_SEARCH);

  // net is expected to fail if the user is not affiliated. In my test setup
  // with different KDCs, net failed with exit code 255 and no error message,
  // resulting in ERROR_NET_FAILED (there was a "Cannot read password" error in
  // debug logs). It's unclear, though, if that's always the case, so just print
  // out the error otherwise and assume the user is not affiliated. By no means
  // bail on error here.
  if (!net_result) {
    ErrorType error = GetNetError(net_cmd, "search");
    if (error != ERROR_NET_FAILED)
      LOG(ERROR) << "Affiliation check failed with error " << error;
    return false;
  }

  // Expected output in case of success:
  // Got 1 replies
  //
  // sAMAccountName: <MACHINE_NAME>
  return Contains(net_cmd.GetStdout(), kSearchSAMAccountName);
}

ErrorType SambaInterface::AcquireUserTgt(int password_fd) {
  // Update smb.conf, IPs, server names etc. for the user account.
  ErrorType error = UpdateAccountData(&user_account_);
  if (error != ERROR_NONE)
    return error;
  user_tgt_manager_.SetKdcIp(user_account_.kdc_ip);

  // Call kinit to get the Kerberos ticket-granting-ticket.
  return user_tgt_manager_.AcquireTgtWithPassword(password_fd);
}

ErrorType SambaInterface::AcquireDeviceTgt() {
  // Update smb.conf, IPs, server names etc for the device account.
  ErrorType error = UpdateAccountData(&device_account_);
  if (error != ERROR_NONE)
    return error;
  device_tgt_manager_.SetKdcIp(device_account_.kdc_ip);

  // Acquire the Kerberos ticket-granting-ticket.
  const base::FilePath password_path(paths_->Get(Path::MACHINE_PASS));
  if (!base::PathExists(password_path)) {
    // This is expected to happen on devices that had been domain joined before
    // authpolicyd managed the machine password. They stored the machine keytab
    // instead of the password, so use that for authentication.
    return device_tgt_manager_.AcquireTgtWithKeytab(Path::MACHINE_KEYTAB);
  }

  // Authenticate using password. Note: There is no keytab file here.
  base::ScopedFD password_fd = ReadFileToPipe(password_path);
  if (!password_fd.is_valid()) {
    LOG(ERROR) << "Failed to open machine password file '"
               << password_path.value() << "'";
    return ERROR_LOCAL_IO;
  }
  const base::FilePath prev_password_path(paths_->Get(Path::PREV_MACHINE_PASS));
  error = device_tgt_manager_.AcquireTgtWithPassword(password_fd.get());
  if (error != ERROR_BAD_PASSWORD || !base::PathExists(prev_password_path))
    return error;

  // Try again with the previous password. After a password change the password
  // might not have propagated through a large AD deployment yet.
  password_fd = ReadFileToPipe(prev_password_path);
  if (!password_fd.is_valid()) {
    LOG(ERROR) << "Failed to open machine password file '"
               << prev_password_path.value() << "'";
    return ERROR_LOCAL_IO;
  }
  return device_tgt_manager_.AcquireTgtWithPassword(password_fd.get());
}

ErrorType SambaInterface::WriteMachinePassword(
    Path path, const std::string& machine_pass) const {
  const base::FilePath password_path(paths_->Get(path));
  if (!base::ImportantFileWriter::WriteFileAtomically(password_path,
                                                      machine_pass)) {
    LOG(ERROR) << "Failed to write machine password file '"
               << password_path.value() << "'";
    return ERROR_LOCAL_IO;
  }

  // This file is only authpolicyd's business.
  int mode =
      base::FILE_PERMISSION_READ_BY_USER | base::FILE_PERMISSION_WRITE_BY_USER;
  ErrorType error = SetFilePermissions(password_path, mode);
  if (error != ERROR_NONE)
    return error;

  // Set file time to match server time, so that we can determine the password
  // age and renew the machine password without relying on local time.
  if (!base::TouchFile(password_path, device_account_.server_time,
                       device_account_.server_time)) {
    LOG(ERROR) << "Failed to set file time on machine password file '"
               << password_path.value() << "'";
    return ERROR_LOCAL_IO;
  }

  LOG(INFO) << "Wrote machine password file '" << password_path.value() << "'";
  return ERROR_NONE;
}

ErrorType SambaInterface::RollMachinePassword() {
  const base::FilePath password_path(paths_->Get(Path::MACHINE_PASS));
  const base::FilePath prev_password_path(paths_->Get(Path::PREV_MACHINE_PASS));
  const base::FilePath new_password_path(paths_->Get(Path::NEW_MACHINE_PASS));

  base::File::Error file_error;
  if (!base::ReplaceFile(password_path, prev_password_path, &file_error) ||
      !base::ReplaceFile(new_password_path, password_path, &file_error)) {
    LOG(ERROR) << "Machine password roll failed: "
               << base::File::ErrorToString(file_error);
    return ERROR_LOCAL_IO;
  }

  return ERROR_NONE;
}

ErrorType SambaInterface::WriteConfiguration() const {
  DCHECK(!device_account_.realm.empty());
  DCHECK(!device_account_.netbios_name.empty());

  protos::ActiveDirectoryConfig config;
  config.set_realm(device_account_.realm);
  config.set_machine_name(device_account_.netbios_name);

  std::string config_blob;
  if (!config.SerializeToString(&config_blob)) {
    LOG(ERROR) << "Failed to serialize configuration to string";
    return ERROR_LOCAL_IO;
  }

  const base::FilePath config_path(paths_->Get(Path::CONFIG_DAT));
  if (!base::ImportantFileWriter::WriteFileAtomically(config_path,
                                                      config_blob)) {
    LOG(ERROR) << "Failed to write configuration file '" << config_path.value()
               << "'";
    return ERROR_LOCAL_IO;
  }

  // This file is only authpolicyd's business.
  ErrorType error =
      SetFilePermissions(config_path, base::FILE_PERMISSION_READ_BY_USER);
  if (error != ERROR_NONE)
    return error;

  LOG(INFO) << "Wrote configuration file '" << config_path.value() << "'";
  return ERROR_NONE;
}

ErrorType SambaInterface::ReadConfiguration() {
  const base::FilePath config_path(paths_->Get(Path::CONFIG_DAT));
  if (!base::PathExists(config_path)) {
    LOG(ERROR) << "Configuration file '" << config_path.value()
               << "' does not exist";
    return ERROR_LOCAL_IO;
  }

  std::string config_blob;
  if (!base::ReadFileToStringWithMaxSize(config_path, &config_blob,
                                         kConfigSizeLimit)) {
    PLOG(ERROR) << "Failed to read configuration file '" << config_path.value()
                << "'";
    return ERROR_LOCAL_IO;
  }

  auto config = std::make_unique<protos::ActiveDirectoryConfig>();
  if (!config->ParseFromString(config_blob)) {
    LOG(ERROR) << "Failed to parse configuration from string";
    return ERROR_LOCAL_IO;
  }

  // Check if the config is valid.
  if (config->machine_name().empty() || config->realm().empty()) {
    LOG(ERROR) << "Configuration is invalid";
    return ERROR_LOCAL_IO;
  }

  InitDeviceAccount(config->machine_name(), config->realm());

  LOG(INFO) << "Read configuration file '" << config_path.value() << "'";

  AnonymizeRealm(device_account_.realm, kDeviceRealmPlaceholder);
  anonymizer_->SetReplacementAllCases(device_account_.netbios_name,
                                      kMachineNamePlaceholder);
  return ERROR_NONE;
}

ErrorType SambaInterface::GetAccountInfo(
    const std::string& user_name,
    const std::string& normalized_upn,
    const std::string& account_id,
    ActiveDirectoryAccountInfo* account_info) {
  // If |account_id| is provided, search by objectGUID only.
  if (!account_id.empty()) {
    // Searching by objectGUID has to use the octet string representation!
    // Note: If |account_id| is malformed, the search yields no results.
    const std::string account_id_octet = GuidToOctetString(account_id);
    anonymizer_->SetReplacement(account_id_octet, kAccountIdPlaceholder);
    std::string search_string =
        base::StringPrintf("(objectGUID=%s)", account_id_octet.c_str());
    return SearchAccountInfo(search_string, account_info);
  }

  // Otherwise, search by sAMAccountName, then by userPrincipalName.
  anonymizer_->SetReplacement(user_name, kSAMAccountNamePlaceholder);
  std::string search_string =
      base::StringPrintf("(sAMAccountName=%s)", user_name.c_str());
  ErrorType error = SearchAccountInfo(search_string, account_info);
  if (error != ERROR_BAD_USER_NAME)  // ERROR_BAD_USER_NAME means there were
    return error;                    // no search results.

  LOG(WARNING) << "Account info not found by sAMAccountName. "
               << "Trying userPrincipalName.";
  anonymizer_->SetReplacement(user_name, kLogonNamePlaceholder);
  search_string =
      base::StringPrintf("(userPrincipalName=%s)", normalized_upn.c_str());
  return SearchAccountInfo(search_string, account_info);
}

ErrorType SambaInterface::SearchAccountInfo(
    const std::string& search_string,
    ActiveDirectoryAccountInfo* account_info) {
  // Set up net ads search to find the user's account info.
  const std::string& smb_conf_path = paths_->Get(user_account_.smb_conf_path);
  ProcessExecutor net_cmd(
      {paths_->Get(Path::NET), "ads", "search", search_string,
       kSearchObjectGUID, kSearchSAMAccountName, kSearchCommonName,
       kSearchDisplayName, kSearchGivenName, kSearchPwdLastSet,
       kSearchUserAccountControl, kConfigParam, smb_conf_path, kDebugParam,
       flags_.net_log_level(), kKerberosParam});

  // Parse the search args from the net_cmd output immediately. This resolves
  // the chicken-egg-problem that replacement strings cannot be set before the
  // strings-to-replace are known, so the output of net_cmd would still contain
  // sensitive strings.
  anonymizer_->ReplaceSearchArg(kSearchObjectGUID, kAccountIdPlaceholder);
  anonymizer_->ReplaceSearchArg(kSearchDisplayName, kDisplayNamePlaceholder);
  anonymizer_->ReplaceSearchArg(kSearchGivenName, kGivenNamePlaceholder);
  anonymizer_->ReplaceSearchArg(kSearchSAMAccountName,
                                kSAMAccountNamePlaceholder);
  anonymizer_->ReplaceSearchArg(kSearchCommonName, kCommonNamePlaceholder);

  // Use the user's TGT to query the account info.
  net_cmd.SetEnv(kKrb5CCEnvKey,
                 paths_->Get(user_tgt_manager_.GetCredentialCachePath()));
  const bool net_result = jail_helper_.SetupJailAndRun(
      &net_cmd, Path::NET_ADS_SECCOMP, TIMER_NET_ADS_SEARCH);
  anonymizer_->ResetSearchArgReplacements();
  if (!net_result) {
    return GetNetError(net_cmd, "search");
  }
  const std::string& net_out = net_cmd.GetStdout();

  // Parse the output to find the account info proto blob. Enclose in a sandbox
  // for security considerations.
  ProcessExecutor parse_cmd({paths_->Get(Path::PARSER), kCmdParseAccountInfo,
                             SerializeFlags(flags_)});
  parse_cmd.SetInputString(net_out);
  if (!jail_helper_.SetupJailAndRun(&parse_cmd, Path::PARSER_SECCOMP,
                                    TIMER_NONE)) {
    // Log net output if it hasn't been done yet.
    net_cmd.LogOutputOnce();
    LOG(ERROR) << "Failed to parse account info. Net response: " << net_out;
    return ERROR_PARSE_FAILED;
  }
  const std::string& account_info_blob = parse_cmd.GetStdout();

  // Parse account info protobuf.
  if (account_info_blob.empty()) {
    // No search results. Return ERROR_BAD_USER_NAME since it usually means that
    // the user mistyped their user name.
    LOG(WARNING) << "Search yielded no results";
    return ERROR_BAD_USER_NAME;
  } else if (!account_info->ParseFromString(account_info_blob)) {
    // Log net output if it hasn't been done yet.
    net_cmd.LogOutputOnce();
    LOG(ERROR) << "Failed to parse account info protobuf";
    return ERROR_PARSE_FAILED;
  }

  // Explicitly set replacements again in case logging is currently disabled
  // and the anonymizer has not parsed the search values above. If we didn't do
  // it here and logging would be enabled later, logs would contain sensitive
  // data.
  anonymizer_->SetReplacement(account_info->account_id(),
                              kAccountIdPlaceholder);
  anonymizer_->SetReplacement(account_info->display_name(),
                              kDisplayNamePlaceholder);
  anonymizer_->SetReplacement(account_info->given_name(),
                              kGivenNamePlaceholder);
  anonymizer_->SetReplacement(account_info->sam_account_name(),
                              kSAMAccountNamePlaceholder);
  anonymizer_->SetReplacement(account_info->common_name(),
                              kCommonNamePlaceholder);

  return ERROR_NONE;
}

ErrorType SambaInterface::GetGpos(GpoSource source,
                                  PolicyScope scope,
                                  std::vector<base::FilePath>* gpo_file_paths) {
  // There's no use case for machine policy from user GPOs right now.
  DCHECK(!(source == GpoSource::USER && scope == PolicyScope::MACHINE));

  // Query list of GPOs from Active Directory server.
  protos::GpoList gpo_list;
  ErrorType error = GetGpoList(source, scope, &gpo_list);
  if (error != ERROR_NONE)
    return error;

  // Download GPOs from Active Directory server.
  return DownloadGpos(gpo_list, source, scope, gpo_file_paths);
}

ErrorType SambaInterface::GetGpoList(GpoSource source,
                                     PolicyScope scope,
                                     protos::GpoList* gpo_list) {
  DCHECK(gpo_list);
  LOG(INFO) << "Getting " << (scope == PolicyScope::USER ? "user" : "device")
            << " GPO list for "
            << (source == GpoSource::USER ? "user" : "device") << " account";

  const AccountData& account = GetAccount(source);
  const TgtManager& tgt_manager = GetTgtManager(source);
  authpolicy::ProcessExecutor net_cmd(
      {paths_->Get(Path::NET), "ads", "gpo", "list", account.user_name,
       kConfigParam, paths_->Get(account.smb_conf_path), kDebugParam,
       flags_.net_log_level(), kKerberosParam});
  net_cmd.SetEnv(kKrb5CCEnvKey,
                 paths_->Get(tgt_manager.GetCredentialCachePath()));
  if (!jail_helper_.SetupJailAndRun(&net_cmd, Path::NET_ADS_SECCOMP,
                                    TIMER_NET_ADS_GPO_LIST)) {
    return GetNetError(net_cmd, "gpo list");
  }

  // GPO data is written to stderr, not stdin!
  const std::string& net_out = net_cmd.GetStderr();

  // Parse the GPO list. Enclose in a sandbox for security considerations. Note
  // that |cmd| depends on |scope| since the parse command is concerned with the
  // type of policy, not which account a GPO came from.
  const char* cmd = scope == PolicyScope::USER ? kCmdParseUserGpoList
                                               : kCmdParseDeviceGpoList;
  ProcessExecutor parse_cmd(
      {paths_->Get(Path::PARSER), cmd, SerializeFlags(flags_)});
  parse_cmd.SetInputString(net_out);
  if (!jail_helper_.SetupJailAndRun(&parse_cmd, Path::PARSER_SECCOMP,
                                    TIMER_NONE)) {
    // Log net output if it hasn't been done yet.
    net_cmd.LogOutputOnce();
    LOG(ERROR) << "Failed to parse GPO list";
    return ERROR_PARSE_FAILED;
  }
  std::string gpo_list_blob = parse_cmd.GetStdout();

  // Parse GPO list protobuf.
  if (!gpo_list->ParseFromString(gpo_list_blob)) {
    LOG(ERROR) << "Failed to read GPO list protobuf";
    return ERROR_PARSE_FAILED;
  }

  return ERROR_NONE;
}

struct GpoPaths {
  std::string server_;     // GPO file path on server (not a local file path!).
  base::FilePath local_;   // Local GPO file path.
  std::string cache_key_;  // Key into the gpo version cache; gpo giud + "-U/M".
  uint32_t version_;       // User or machine version of the GPO.
  bool use_cache_;  // Whether to use cached version. False to redownload.
  GpoPaths(const std::string& server,
           const base::FilePath& local,
           const std::string& cache_key,
           uint32_t version,
           bool use_cache)
      : server_(server),
        local_(local),
        cache_key_(cache_key),
        version_(version),
        use_cache_(use_cache) {}
};

ErrorType SambaInterface::DownloadGpos(
    const protos::GpoList& gpo_list,
    GpoSource source,
    PolicyScope scope,
    std::vector<base::FilePath>* gpo_file_paths) {
  metrics_->Report(METRIC_DOWNLOAD_GPO_COUNT, gpo_list.entries_size());
  if (gpo_list.entries_size() == 0) {
    LOG(INFO) << "No GPOs to download";
    return ERROR_NONE;
  }

  // Clean up GPO cache.
  gpo_version_cache_.RemoveEntriesOlderThan(gpo_version_cache_ttl_);

  // Generate all smb source and linux target directories and create targets.
  ErrorType error;
  std::string smb_command = "prompt OFF;lowercase ON;";
  std::string gpo_share;
  std::vector<GpoPaths> gpo_paths;
  bool anything_to_download = false;
  for (int entry_idx = 0; entry_idx < gpo_list.entries_size(); ++entry_idx) {
    const protos::GpoEntry& gpo = gpo_list.entries(entry_idx);

    // Security check, make sure nobody sneaks in smbclient commands.
    if (gpo.share().find(';') != std::string::npos ||
        gpo.directory().find(';') != std::string::npos) {
      LOG(ERROR) << "GPO paths may not contain a ';'";
      return ERROR_BAD_GPOS;
    }

    // All GPOs should have the same share, i.e. come from the same SysVol.
    if (gpo_share.empty()) {
      gpo_share = gpo.share();
    } else if (!base::EqualsCaseInsensitiveASCII(gpo_share, gpo.share())) {
      LOG(ERROR) << "Inconsistent share '" << gpo_share << "' != '"
                 << gpo.share() << "'";
      return ERROR_BAD_GPOS;
    }

    // Figure out local (Linux) and remote (smb) directories.
    const char* preg_dir =
        scope == PolicyScope::USER ? kPRegUserDir : kPRegDeviceDir;
    std::string smb_dir =
        base::StringPrintf("\\%s\\%s", gpo.directory().c_str(), preg_dir);
    std::string linux_dir = paths_->Get(Path::GPO_LOCAL_DIR) + smb_dir;
    std::replace(linux_dir.begin(), linux_dir.end(), '\\', '/');

    // Make local directory.
    const base::FilePath linux_dir_fp(linux_dir);
    error = ::authpolicy::CreateDirectory(linux_dir_fp);
    if (error != ERROR_NONE)
      return error;

    // Set group rwx permissions recursively, so that smbclient can write GPOs
    // there and the parser tool can read the GPOs later.
    error = SetFilePermissionsRecursive(
        linux_dir_fp, base::FilePath(paths_->Get(Path::SAMBA_CACHE_DIR)),
        kFileMode_rwxrwx);
    if (error != ERROR_NONE)
      return error;

    // Figure out whether we can use cached GPO to skip download. As cache key
    // use {GPO-GUID}-U for user policy and {GPO-GUID}-M for machine policy.
    // (User and machine policy are two separate files, even though it's the
    // same GPO). Note that the GPO file may not exist, but that's fine.
    const char* scope_extension = (scope == PolicyScope::USER ? "-U" : "-M");
    const std::string cache_key = gpo.name() + scope_extension;
    const bool use_cache =
        gpo_version_cache_.MayUseCachedGpo(cache_key, gpo.version());

    // Record output file paths.
    const std::string server_path = smb_dir + "\\" + kPRegFileName;
    const auto local_path = base::FilePath(linux_dir).Append(kPRegFileName);
    gpo_paths.push_back(
        GpoPaths(server_path, local_path, cache_key, gpo.version(), use_cache));

    if (!use_cache) {
      // Delete the stale GPO file if it exists.
      if (!base::DeleteFile(local_path)) {
        LOG(ERROR) << "Failed to delete old GPO file '"
                   << anonymizer_->Process(local_path.value()) << "'";
        return ERROR_LOCAL_IO;
      }

      // Build command to download the GPO file via smbclient.
      smb_command += base::StringPrintf("cd %s;lcd %s;get %s;", smb_dir.c_str(),
                                        linux_dir.c_str(), kPRegFileName);
      anything_to_download = true;
    }
  }

  // Skip smbclient call if there's nothing to download.
  if (anything_to_download) {
    const AccountData& account = GetAccount(source);
    DCHECK(!account.dc_name.empty());
    const std::string service = base::StringPrintf(
        "//%s/%s", account.dc_name.c_str(), gpo_share.c_str());

    // The exit code of smbclient corresponds to the LAST command issued. Some
    // files might be missing and fail to download, which is fine and handled
    // below. Appending 'exit' makes sure the exit code is not 1 if the last
    // file happens to be missing.
    smb_command += "exit;";

    // Download GPO into local directory. Retry a couple of times in case of
    // network errors, Kerberos authentication may be flaky in some deployments,
    // see crbug.com/684733.
    ProcessExecutor smb_client_cmd(
        {paths_->Get(Path::SMBCLIENT), service, kConfigParam,
         paths_->Get(account.smb_conf_path), kKerberosParam, kDebugParam,
         flags_.net_log_level(), kCommandParam, smb_command});
    const TgtManager& tgt_manager = GetTgtManager(source);
    smb_client_cmd.SetEnv(kKrb5CCEnvKey,
                          paths_->Get(tgt_manager.GetCredentialCachePath()));
    smb_client_cmd.SetEnv(
        kKrb5ConfEnvKey,  // Kerberos configuration file path.
        kFilePrefix + paths_->Get(tgt_manager.GetConfigPath()));
    int tries, failed_tries = 0;
    for (tries = 1; tries <= kSmbClientMaxTries; ++tries) {
      if (tries > 1 && !retry_sleep_disabled_for_testing_)
        base::PlatformThread::Sleep(kSmbClientRetryDelay);
      if (jail_helper_.SetupJailAndRun(&smb_client_cmd, Path::SMBCLIENT_SECCOMP,
                                       TIMER_SMBCLIENT)) {
        error = ERROR_NONE;
        break;
      }
      failed_tries++;
      error = GetSmbclientError(smb_client_cmd);
      if (error != ERROR_NETWORK_PROBLEM)
        break;
    }
    metrics_->Report(METRIC_SMBCLIENT_FAILED_TRY_COUNT, failed_tries);
    if (error != ERROR_NONE)
      return error;

    // Note that the errors are in stdout and the output is in stderr :-/
    const std::string& smbclient_out_lower =
        base::ToLowerASCII(smb_client_cmd.GetStdout());

    // Gracefully handle non-existing GPOs. Testing revealed these cases do
    // exist, see crbug.com/680921.
    for (const GpoPaths& gpo_path : gpo_paths) {
      if (gpo_path.use_cache_)
        continue;
      if (base::PathExists(gpo_path.local_))
        continue;

      const std::string no_file_error_key(
          base::ToLowerASCII(kKeyObjectNameNotFound + gpo_path.server_));
      if (Contains(smbclient_out_lower, no_file_error_key)) {
        LOG_IF(WARNING, flags_.log_gpo())
            << "Ignoring missing preg file '"
            << anonymizer_->Process(gpo_path.local_.value()) << "'";
      } else {
        // Log smbclient output if it hasn't been done yet.
        smb_client_cmd.LogOutputOnce();
        LOG(ERROR) << "Failed to download preg file '"
                   << anonymizer_->Process(gpo_path.local_.value()) << "'";
        gpo_version_cache_.Remove(gpo_path.cache_key_);
        return ERROR_SMBCLIENT_FAILED;
      }
    }
  }

  // Gather a list of existing GPO files and update cache.
  DCHECK(gpo_file_paths);
  for (const GpoPaths& gpo_path : gpo_paths) {
    if (base::PathExists(gpo_path.local_))
      gpo_file_paths->push_back(gpo_path.local_);

    // Add GPO to the cache even if the file didn't actually download.
    if (!gpo_path.use_cache_)
      gpo_version_cache_.Add(gpo_path.cache_key_, gpo_path.version_);
  }

  return ERROR_NONE;
}

ErrorType SambaInterface::ParseGposIntoProtobuf(
    const std::vector<base::FilePath>& gpo_file_paths,
    const char* parser_cmd_string,
    std::string* policy_blob) const {
  // Convert file paths to proto blob.
  std::string gpo_file_paths_blob;
  protos::FilePathList fp_proto;
  for (const auto& fp : gpo_file_paths)
    *fp_proto.add_entries() = fp.value();
  if (!fp_proto.SerializeToString(&gpo_file_paths_blob)) {
    LOG(ERROR) << "Failed to serialize policy file paths to protobuf";
    return ERROR_PARSE_PREG_FAILED;
  }

  // Load GPOs into protobuf. Enclose in a sandbox for security considerations.
  ProcessExecutor parse_cmd(
      {paths_->Get(Path::PARSER), parser_cmd_string, SerializeFlags(flags_)});
  parse_cmd.SetInputString(gpo_file_paths_blob);
  if (!jail_helper_.SetupJailAndRun(&parse_cmd, Path::PARSER_SECCOMP,
                                    TIMER_NONE)) {
    LOG(ERROR) << "Failed to parse preg files";
    return ERROR_PARSE_PREG_FAILED;
  }
  *policy_blob = parse_cmd.GetStdout();
  return ERROR_NONE;
}

void SambaInterface::UpdateDevicePolicyDependencies(
    const em::ChromeDeviceSettingsProto& device_policy) {
  has_device_policy_ = true;

  // Get Kerberos encryption types policy. Note that we fall back to strong
  // encryption if the policy is not set.
  KerberosEncryptionTypes enc_types = GetEncryptionTypes(device_policy);
  SetKerberosEncryptionTypes(enc_types);

  // Get loopback processing mode.
  user_policy_mode_ = GetUserPolicyMode(device_policy);

  // Update machine password change rate. Use the default 30 days for now until
  // the DeviceMachinePasswordChangeRate arrives in Chrome OS.
  base::TimeDelta password_change_rate =
      GetMachinePasswordChangeRate(device_policy);
  UpdateMachinePasswordAutoChange(password_change_rate);

  // Update GPO version cache. The cache is disabled if the TTL is 0.
  gpo_version_cache_ttl_ = GetGpoVersionCacheTTL(device_policy);
  gpo_version_cache_.SetEnabled(gpo_version_cache_ttl_ > kZeroDelta);
  if (!gpo_version_cache_.IsEnabled())
    gpo_version_cache_.Clear();

  // Update auth data cache. The cache is disabled if the TTL is 0.
  auth_data_cache_ttl_ = GetAuthDataCacheTTL(device_policy);
  auth_data_cache_.SetEnabled(auth_data_cache_ttl_ > kZeroDelta);
  if (!auth_data_cache_.IsEnabled()) {
    auth_data_cache_.Clear();
    const base::FilePath cache_path(paths_->Get(Path::AUTH_DATA_CACHE));
    if (!base::DeleteFile(cache_path)) {
      LOG(ERROR) << "Failed delete auth data cache file '" << cache_path.value()
                 << "'";
    }
  }
}

void SambaInterface::UpdateUserAffiliation() {
  // Must be called after successful login.
  DCHECK(user_logged_in_);

  // Figure out if the user is affiliated.
  is_user_affiliated_ = IsUserAffiliated();
  LOG(INFO) << "User is " << (is_user_affiliated_ ? "" : "not ")
            << "affiliated";

  // Cache auth data, but ONLY if the user is affiliated (for privacy reasons).
  if (is_user_affiliated_)
    UpdateAuthDataCache(user_account_, is_user_affiliated_);
}

void SambaInterface::UpdateAuthDataCache(const AccountData& account,
                                         bool is_affiliated) {
  // Update cache.
  auth_data_cache_.SetWorkgroup(account.realm, account.workgroup);
  auth_data_cache_.SetKdcIp(account.realm, account.kdc_ip);
  auth_data_cache_.SetDcName(account.realm, account.dc_name);
  auth_data_cache_.SetIsAffiliated(account.realm, is_affiliated);

  // Flush cache to file. Do a best effort, don't bother if it fails.
  const base::FilePath cache_path(paths_->Get(Path::AUTH_DATA_CACHE));
  auth_data_cache_.Save(cache_path);
}

void SambaInterface::UpdateMachinePasswordAutoChange(
    const base::TimeDelta& rate) {
  password_change_rate_ = rate;

  // Disable password auto change if the rate is non-positive.
  if (password_change_rate_ <= base::TimeDelta::FromDays(0)) {
    password_change_timer_.Stop();
    return;
  }

  // Are we using a machine password at all? Devices joined before the switch
  // from keytab to password still use keytabs, so changing the machine password
  // isn't possible.
  if (!base::PathExists(base::FilePath(paths_->Get(Path::MACHINE_PASS)))) {
    LOG(WARNING)
        << "Cannot change the machine password since this devices still uses "
           "the keytab file. Re-enrolling the device will fix this.";
    return;
  }

  // Start timer for the password change checker.
  if (!password_change_timer_.IsRunning()) {
    password_change_timer_.Start(
        FROM_HERE, kPasswordChangeCheckRate, this,
        &SambaInterface::AutoCheckMachinePasswordChange);

    // Perform a check immediately. This usually happens on startup and makes
    // sure we do at least one check during a session.
    AutoCheckMachinePasswordChange();
  }
}

void SambaInterface::AutoCheckMachinePasswordChange() {
  LOG(INFO) << "Running scheduled machine password age check";
  ErrorType error = CheckMachinePasswordChange();
  if (error != ERROR_NONE)
    LOG(ERROR) << "Machine password check failed with error " << error;
  did_password_change_check_run_for_testing_ = true;
  metrics_->ReportError(ERROR_OF_AUTO_MACHINE_PASSWORD_CHANGE, error);
}

ErrorType SambaInterface::CheckMachinePasswordChange() {
  // Get the latest server time and KDC IP. Reset |server_time| to enforce an
  // update (otherwise, the cached values are kept).
  device_account_.server_time = base::Time();
  ErrorType error = UpdateAccountData(&device_account_);
  if (error != ERROR_NONE)
    return error;
  device_tgt_manager_.SetKdcIp(device_account_.kdc_ip);

  const base::FilePath password_path(paths_->Get(Path::MACHINE_PASS));
  base::File::Info file_info;
  if (!GetFileInfo(password_path, &file_info)) {
    LOG(ERROR)
        << "Machine password check failed. Could not get info for machine "
        << "password file '" << password_path.value() << "'";
    return ERROR_LOCAL_IO;
  }

  // Check if the password is older than the change rate (=max age).
  base::TimeDelta password_age =
      device_account_.server_time - file_info.last_modified;
  if (password_age < password_change_rate_) {
    int total_hours_left = (password_change_rate_ - password_age).InHours();
    int days_left = total_hours_left / base::Time::kHoursPerDay;
    int hours_left = total_hours_left % base::Time::kHoursPerDay;

    LOG(INFO) << "No need to change machine password (" << days_left << "d "
              << hours_left << "h left)";
    return ERROR_NONE;
  }

  LOG(INFO) << "Machine password is older than "
            << password_change_rate_.InDays() << " days. Changing.";

  // Read the old password.
  std::string old_password;
  if (!ReadMachinePasswordToString(password_path, &old_password))
    return ERROR_LOCAL_IO;

  // Generate and write a new password.
  const std::string new_password = GenerateRandomMachinePassword();
  error = WriteMachinePassword(Path::NEW_MACHINE_PASS, new_password);
  if (error != ERROR_NONE)
    return error;

  // Change the machine password on the server.
  error = device_tgt_manager_.ChangePassword(old_password, new_password);
  if (error != ERROR_NONE)
    return error;

  // Roll password files.
  error = RollMachinePassword();

  if (error != ERROR_NONE) {
    // Try writing the new password directly, ignoring the previous one.
    error = WriteMachinePassword(Path::MACHINE_PASS, new_password);
  }

  if (error != ERROR_NONE) {
    // Do a best effort recovering the old password. If that doesn't work, we
    // won't be able to access the machine account anymore!
    ErrorType change_back_error =
        device_tgt_manager_.ChangePassword(new_password, old_password);
    ErrorType write_error =
        WriteMachinePassword(Path::MACHINE_PASS, old_password);
    if (change_back_error != ERROR_NONE || write_error != ERROR_NONE) {
      LOG(ERROR) << "Recovering the old machine password failed. Your device "
                    "is in an invalid state and needs to be re-enrolled.";
    }
    return error;
  }

  LOG(INFO) << "Successfully changed machine password";
  return ERROR_NONE;
}

void SambaInterface::SetUserAccountId(const std::string& account_id) {
  // Don't allow authenticating multiple users. Chrome should prevent that.
  CHECK(!account_id.empty());
  if (user_account_id_ == account_id)
    return;
  CHECK(user_account_id_.empty()) << "Multi-user not supported";
  user_account_id_ = account_id;

  // Get the user daemon store path to back up auth data.
  DCHECK(cryptohome_client_);
  std::string sanitized_username =
      cryptohome_client_->GetSanitizedUsername(GetAccountIdKey(account_id));
  if (sanitized_username.empty()) {
    LOG(ERROR) << "Failed to get sanitized username. "
                  "Auth state backups won't work.";
    return;
  }
  user_daemon_store_path_ = base::FilePath(paths_->Get(Path::DAEMON_STORE_DIR))
                                .Append(sanitized_username);
}

void SambaInterface::SetUserRealm(const std::string& user_realm) {
  // Allow setting the realm only once. This makes sure that nobody calls
  // AuthenticateUser() with a different realm, the call fails and we're stuck
  // with a wrong realm.
  CHECK(!user_realm.empty());
  CHECK(user_account_.realm.empty() || user_account_.realm == user_realm)
      << "Multi-user not supported";
  user_account_.realm = user_realm;
  user_tgt_manager_.SetRealm(user_account_.realm);
  AnonymizeRealm(user_realm, kUserRealmPlaceholder);
}

ErrorType SambaInterface::MaybeSetFakeDomainSid(const AccountData& account) {
  // Don't set twice for the same workgroup.
  if (fake_domain_sid_was_set_for_workgroup_.find(account.workgroup) !=
      fake_domain_sid_was_set_for_workgroup_.end())
    return ERROR_NONE;

  // Reuse the NET_ADS_SECCOMP filter for simplicity, even though it's not a net
  // ads command.
  ProcessExecutor net_cmd({paths_->Get(Path::NET), "setdomainsid",
                           kFakeDomainSid, kConfigParam,
                           paths_->Get(account.smb_conf_path), kDebugParam,
                           flags_.net_log_level()});
  if (!jail_helper_.SetupJailAndRun(&net_cmd, Path::NET_ADS_SECCOMP,
                                    TIMER_NONE)) {
    // This is actually a local operation.
    LOG(ERROR) << "Failed to set fake domain SID";
    return ERROR_LOCAL_IO;
  }

  // Mark as set for this workgroup.
  fake_domain_sid_was_set_for_workgroup_.insert(account.workgroup);
  return ERROR_NONE;
}

void SambaInterface::InitDeviceAccount(const std::string& netbios_name,
                                       const std::string& realm) {
  device_account_.netbios_name = netbios_name;
  device_account_.user_name = device_account_.netbios_name + "$";
  device_account_.realm = realm;
  device_tgt_manager_.SetRealm(device_account_.realm);
  device_tgt_manager_.SetPrincipal(device_account_.GetPrincipal());
}

void SambaInterface::SetKerberosEncryptionTypes(
    KerberosEncryptionTypes encryption_types) {
  if (encryption_types_ != encryption_types) {
    LOG(INFO) << "Kerberos encryption types changed to "
              << GetEncryptionTypesString(encryption_types);
  }
  encryption_types_ = encryption_types;
  user_tgt_manager_.SetKerberosEncryptionTypes(encryption_types_);
  device_tgt_manager_.SetKerberosEncryptionTypes(encryption_types_);
}

void SambaInterface::MaybeBackupUserAuthState() {
  if (!user_logged_in_ || !in_user_session_ || user_daemon_store_path_.empty())
    return;
  DCHECK(!user_account_id_.empty());

  // Since we're in the session, Cryptohome should be mounted.
  DCHECK(base::PathExists(user_daemon_store_path_));

  // Back up TGT state.
  protos::UserBackupData data;
  if (!user_tgt_manager_.Backup(data.mutable_tgt_state()))
    return;

  // Put all other data we want to serialize into the proto.
  data.set_pwd_last_set(user_pwd_last_set_);
  data.set_user_name(user_account_.user_name);
  data.set_is_user_affiliated(is_user_affiliated_);
  data.set_user_realm(user_account_.realm);

  // Convert proto to string.
  std::string data_blob;
  if (!data.SerializeToString(&data_blob)) {
    LOG(WARNING) << "Backup failed to serialize backup data to string";
    return;
  }

  // Save string to disk.
  const int size = static_cast<int>(data_blob.size());
  const base::FilePath backup_path =
      user_daemon_store_path_.Append(kBackupFileName);
  if (base::WriteFile(backup_path, data_blob.data(), size) != size) {
    LOG(WARNING) << "Backup failed to write data to " << backup_path.value();
    return;
  }

  LOG(INFO) << "Backup successfully written to " << backup_path.value();
}

void SambaInterface::MaybeRestoreUserAuthState() {
  if (user_logged_in_ || !in_user_session_ || user_daemon_store_path_.empty())
    return;
  DCHECK(!user_account_id_.empty());

  // Exit quietly if the backup path doesn't exist (yet).
  const base::FilePath backup_path =
      user_daemon_store_path_.Append(kBackupFileName);
  if (!base::PathExists(backup_path))
    return;

  // Read string from disk.
  std::string data_blob;
  if (!base::ReadFileToStringWithMaxSize(backup_path, &data_blob,
                                         kMaxBackupSizeBytes)) {
    PLOG(ERROR) << "Backup failed to read data from " << backup_path.value();
    return;
  }

  // Convert string to proto.
  protos::UserBackupData data;
  if (!data.ParseFromString(data_blob)) {
    LOG(WARNING) << "Backup failed to parse backup data from string";
    return;
  }

  // Check proto.
  if (!data.has_tgt_state() || !data.has_pwd_last_set() ||
      !data.has_user_name() || data.user_name().empty() ||
      !data.has_is_user_affiliated()) {
    LOG(WARNING) << "Backup data is bad";
    return;
  }

  // Restore TGT state.
  if (!user_tgt_manager_.Restore(data.tgt_state()))
    return;

  // Restore all other data from the proto.
  user_pwd_last_set_ = data.pwd_last_set();
  user_account_.user_name = data.user_name();
  is_user_affiliated_ = data.is_user_affiliated();
  // User realm might be missing in old backup data. New data should have it.
  if (data.has_user_realm())
    SetUserRealm(data.user_realm());
  user_logged_in_ = true;

  LOG(INFO) << "Backup successfully restored from " << backup_path.value();
}

void SambaInterface::AnonymizeRealm(const std::string& realm,
                                    const char* placeholder) {
  anonymizer_->SetReplacementAllCases(realm, placeholder);

  std::vector<std::string> parts = base::SplitString(
      realm, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  for (const auto& part : parts)
    anonymizer_->SetReplacementAllCases(part, placeholder);
}

bool SambaInterface::IsDeviceJoined() const {
  DCHECK(device_account_.realm.empty() ^ !device_account_.netbios_name.empty());
  return !device_account_.realm.empty() &&
         !device_account_.netbios_name.empty();
}

void SambaInterface::Reset() {
  user_account_id_.clear();
  user_pwd_last_set_ = 0;
  user_logged_in_ = false;
  is_user_affiliated_ = false;
  user_account_ = AccountData(Path::USER_SMB_CONF);
  device_account_ = AccountData(Path::DEVICE_SMB_CONF);
  user_tgt_manager_.Reset();
  device_tgt_manager_.Reset();
  gpo_version_cache_.Clear();
  gpo_version_cache_.SetEnabled(true);
  gpo_version_cache_ttl_ = kDefaultGpoVersionCacheTTL;
  auth_data_cache_.Clear();
  auth_data_cache_.SetEnabled(true);
  auth_data_cache_ttl_ = kDefaultAuthDataCacheTTL;
  SetKerberosEncryptionTypes(ENC_TYPES_STRONG);
  user_policy_mode_ =
      em::DeviceUserPolicyLoopbackProcessingModeProto::USER_POLICY_MODE_DEFAULT;
  password_change_timer_.Stop();
  password_change_rate_ = base::TimeDelta();
  has_device_policy_ = false;
  device_policy_impl_for_testing.reset();
  did_password_change_check_run_for_testing_ = false;
}

void SambaInterface::LoadFlagsDefaultLevel() {
  const base::FilePath default_level_path(
      paths_->Get(Path::FLAGS_DEFAULT_LEVEL));
  if (!CheckFlagsDefaultLevelValid(default_level_path))
    return;
  std::string level_str;
  if (!base::ReadFileToStringWithMaxSize(default_level_path, &level_str, 16)) {
    PLOG(ERROR) << "Failed to read flags default level from '"
                << default_level_path.value() << "'";
    return;
  }
  int level_int;
  if (!base::StringToInt(level_str, &level_int) ||
      level_int < AuthPolicyFlags::kMinLevel ||
      level_int > AuthPolicyFlags::kMaxLevel) {
    LOG(ERROR) << "Bad flags default level '" << level_str << "'";
    return;
  }
  flags_default_level_ = static_cast<AuthPolicyFlags::DefaultLevel>(level_int);
  LOG(INFO) << "Flags default level = " << flags_default_level_;
}

void SambaInterface::SaveFlagsDefaultLevel() {
  const base::FilePath default_level_path(
      paths_->Get(Path::FLAGS_DEFAULT_LEVEL));
  const std::string level_str = std::to_string(flags_default_level_);
  const int size = static_cast<int>(level_str.size());
  if (flags_default_level_ == AuthPolicyFlags::kQuiet) {
    // Remove the file, kQuiet is the default, anyway.
    if (!base::DeleteFile(default_level_path)) {
      PLOG(ERROR) << "Failed to delete flags default level file '"
                  << default_level_path.value() << "'";
    }
  } else {
    // Write the file.
    if (base::WriteFile(default_level_path, level_str.data(), size) != size) {
      PLOG(ERROR) << "Failed to write flags default level to '"
                  << default_level_path.value() << "'";
    }
  }
}

void SambaInterface::ReloadDebugFlags() {
  const base::FilePath default_level_path(
      paths_->Get(Path::FLAGS_DEFAULT_LEVEL));
  if (flags_default_level_ != AuthPolicyFlags::kQuiet &&
      !CheckFlagsDefaultLevelValid(default_level_path)) {
    // Default flags file expired, reset default level.
    flags_default_level_ = AuthPolicyFlags::kQuiet;
  }

  // First set defaults, then load file on top.
  AuthPolicyFlags flags_container;
  flags_container.SetDefaults(flags_default_level_);
  const base::FilePath path(paths_->Get(Path::DEBUG_FLAGS));
  if (flags_container.LoadFromJsonFile(path) ||
      flags_default_level_ != AuthPolicyFlags::kQuiet) {
    flags_container.Dump();
  }
  flags_ = flags_container.Get();
  if (disable_seccomp_for_testing_)
    flags_.set_disable_seccomp(true);

  // Toggle anonymizer.
  anonymizer_->set_disabled(flags_.disable_anonymizer());
}

}  // namespace authpolicy
