// 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.

// Command line tool to parse data. Data is read from stdin as string or
// protobuf and returned through stdout in string or protobuf format. The tool
// is invoked by the authpolicy daemon in a secure sandbox. It is done this way
// since parsing the output is considered insecure.
//
// Usage:
//   authpolicy_parser <command> <serialized_debug_flags>
//   For a list of commands see constants.h.
//   Each command reads additional arguments from stdin. See code for details.
//
// Logs to syslog.

#include <time.h>

#include <string>
#include <vector>

#include <base/at_exit.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <brillo/syslog_logging.h>

#include "authpolicy/authpolicy_flags.h"
#include "authpolicy/constants.h"
#include "authpolicy/log_colors.h"
#include "authpolicy/platform_helper.h"
#include "authpolicy/policy/preg_policy_encoder.h"
#include "authpolicy/proto_bindings/active_directory_info.pb.h"
#include "authpolicy/samba_helper.h"
#include "bindings/authpolicy_containers.pb.h"
#include "bindings/chrome_device_policy.pb.h"
#include "bindings/cloud_policy.pb.h"

namespace em = enterprise_management;

namespace authpolicy {

namespace {

// 'net ads gpo list' tokens.
const char kGpoToken_Separator[] = "---------------------";
const char kGpoToken_Name[] = "name";
const char kGpoToken_Filesyspath[] = "filesyspath";
const char kGpoToken_VersionUser[] = "version_user";
const char kGpoToken_VersionMachine[] = "version_machine";
const char kGpoToken_Options[] = "options";

// 'net ads' tokens.
const char kToken_NoResults[] = "Got 0 replies";
const char kToken_KdcServer[] = "KDC server";
const char kToken_ServerTime[] = "Server time";
const char kToken_DomainController[] = "Domain Controller";
const char kToken_Workgroup[] = "Workgroup";

// Length of the klist date/time format (mm/dd/yy HH:MM:SS).
const int kDateTimeStringLength = 18;

// Various offsets from the beginning of a line of date/time strings in the
// klist output.
const size_t kValidFromOffset = 0;
const size_t kExpiresOffset = 19;
const size_t kRenewUntilOffset = 11;

// String in klist output that prefixes the renewal lifetime.
const char kRenewUntil[] = "renew until ";

// Grace time before printing warnings like "TGT not yet valid?" since it's
// generating a lot of false positives otherwise. The reason could be time
// discrepancies between client and server.
const int kTgtWarningGraceTimeSeconds = 300;

struct GpoEntry {
  GpoEntry() { Clear(); }

  void Clear() {
    name.clear();
    filesyspath.clear();
    version_user = 0;
    version_machine = 0;
    gp_flags = kGpFlagInvalid;
  }

  bool IsValid() const {
    return !name.empty() && !filesyspath.empty() &&
           !(version_user == 0 && version_machine == 0) &&
           gp_flags != kGpFlagInvalid;
  }

  bool IsEmpty() const {
    return name.empty() && filesyspath.empty() && version_user == 0 &&
           version_machine == 0 && gp_flags == kGpFlagInvalid;
  }

  void Log() const {
    LOG(INFO) << kColorGpo << "  Name:        " << name << kColorReset;
    LOG(INFO) << kColorGpo << "  Version:     " << version_user << " (user) "
              << version_machine << " (machine)" << kColorReset;
    LOG(INFO) << kColorGpo << "  GPFLags:     " << gp_flags << kColorReset;
  }

  std::string name;
  std::string filesyspath;
  unsigned int version_user;
  unsigned int version_machine;
  int gp_flags;
};

void PushGpo(const GpoEntry& gpo,
             PolicyScope scope,
             std::vector<GpoEntry>* gpo_list,
             const protos::DebugFlags& flags) {
  if (gpo.IsEmpty())
    return;

  if (!gpo.IsValid() && flags.log_gpo()) {
    LOG(INFO) << kColorGpo << "Ignoring invalid GPO" << kColorReset;
    gpo.Log();
    return;
  }

  // Filter out GPOs we don't need. If version_user == 0, there's no user
  // policy stored in that GPO. Similarly, if version_machine == 0, there's no
  // device policy.
  const char* filter_reason = nullptr;
  switch (scope) {
    case PolicyScope::USER:
      if (gpo.version_user == 0)
        filter_reason = "user version is 0";
      else if (gpo.gp_flags & kGpFlagUserDisabled)
        filter_reason = "user disabled flag is set";
      break;
    case PolicyScope::MACHINE:
      if (gpo.version_machine == 0)
        filter_reason = "machine version is 0";
      else if (gpo.gp_flags & kGpFlagMachineDisabled)
        filter_reason = "machine disabled flag is set";
      break;
  }
  if (!filter_reason) {
    gpo_list->push_back(gpo);
  } else if (flags.log_gpo()) {
    LOG(INFO) << kColorGpo << "Filtered out GPO (" << filter_reason << ")"
              << kColorReset;
    gpo.Log();
  }
}

// Prints |str| to stdout for the caller of this tool. Returns an exit code that
// indicates success or failure.
int OutputForCaller(const std::string& str) {
  if (!base::WriteFileDescriptor(STDOUT_FILENO, str)) {
    LOG(ERROR) << "Failed to write output for caller";
    return EXIT_CODE_WRITE_OUTPUT_FAILED;
  }
  return EXIT_CODE_OK;
}

// Parses the substring starting at offset |offset| of |str| for a date/time
// formatted mm/dd/yy HH:MM:SS. The time is interpreted as local time. Sets
// |time| to the number of seconds in the epoch or 0 on error. Returns true on
// success.
bool ParseTgtDateTime(const std::string& str, size_t offset, time_t* time) {
  *time = 0;
  if (offset >= str.size())
    return false;

  std::string datetime = str.substr(offset, kDateTimeStringLength);
  if (datetime.size() < kDateTimeStringLength)
    return false;

  struct tm tm = {};
  if (!strptime(datetime.c_str(), "%m/%d/%y %H:%M:%S", &tm))
    return false;

  // Figure out daylight saving time (strptime doesn't set this).
  tm.tm_isdst = -1;

  *time = mktime(&tm);
  return true;
}

// Parses the output of net ads info into a ServerInfo protobuf and prints
// it to stdout.
int ParseServerInfo(const std::string& net_out) {
  std::string kdc_ip, server_time_str;
  if (!FindToken(net_out, ':', kToken_KdcServer, &kdc_ip) ||
      !FindToken(net_out, ':', kToken_ServerTime, &server_time_str)) {
    LOG(ERROR) << "Failed to parse server info";
    return EXIT_CODE_FIND_TOKEN_FAILED;
  }

  // Parse time. The time format is "Thu, 15 Feb 2018 11:21:26 PST".
  base::Time server_time;
  if (!base::Time::FromString(server_time_str.c_str(), &server_time)) {
    LOG(ERROR) << "Failed to parse server time " << server_time_str;
    return EXIT_CODE_PARSE_INPUT_FAILED;
  }

  // Put data into proto.
  protos::ServerInfo server_info;
  server_info.set_kdc_ip(kdc_ip);
  server_info.set_server_time(server_time.ToInternalValue());

  std::string server_info_blob;
  if (!server_info.SerializeToString(&server_info_blob)) {
    LOG(ERROR) << "Failed to convert server info proto to string";
    return EXIT_CODE_WRITE_OUTPUT_FAILED;
  }
  return OutputForCaller(server_info_blob);
}

// Parses the output of net ads search to get the user's account info and prints
// it to stdout. Prints an empty string in case of no search results.
int ParseAccountInfo(const std::string& net_out) {
  // Return an empty string, but no error, if no results have been found.
  if (base::StartsWith(net_out, kToken_NoResults, base::CompareCase::SENSITIVE))
    return OutputForCaller("");

  // Parse required attributes.
  std::string object_guid;
  std::string sam_account_name;
  std::string common_name;
  if (!FindToken(net_out, ':', kSearchObjectGUID, &object_guid) ||
      !FindToken(net_out, ':', kSearchSAMAccountName, &sam_account_name) ||
      !FindToken(net_out, ':', kSearchCommonName, &common_name)) {
    LOG(ERROR) << "Failed to parse account info";
    return EXIT_CODE_FIND_TOKEN_FAILED;
  }

  // Put data into proto.
  ActiveDirectoryAccountInfo account_info;
  account_info.set_account_id(object_guid);
  account_info.set_sam_account_name(sam_account_name);
  account_info.set_common_name(common_name);

  // pwdLastSet might be missing, see crbug.com/795758. Handle it gracefully.
  std::string pwd_last_set_str;
  if (FindToken(net_out, ':', kSearchPwdLastSet, &pwd_last_set_str)) {
    uint64_t pwd_last_set;
    if (!base::StringToUint64(pwd_last_set_str, &pwd_last_set)) {
      LOG(WARNING) << "Failed to convert pwdLastSet string '"
                   << pwd_last_set_str << "' to integer";
    } else {
      account_info.set_pwd_last_set(pwd_last_set);
    }
  }

  // Likewise, handle missing userAccountControl just in case.
  std::string user_account_control_str;
  if (FindToken(net_out, ':', kSearchUserAccountControl,
                &user_account_control_str)) {
    uint32_t user_account_control;
    if (!base::StringToUint(user_account_control_str, &user_account_control)) {
      LOG(WARNING) << "Failed to convert userAccountControl string '"
                   << user_account_control_str << "' to integer";
    } else {
      account_info.set_user_account_control(user_account_control);
    }
  }

  // Attributes 'displayName' and 'givenName' are optional. May be missing for
  // accounts like 'Administrator' or for partially set up accounts.
  std::string display_name, given_name;
  if (FindToken(net_out, ':', kSearchDisplayName, &display_name))
    account_info.set_display_name(display_name);
  if (FindToken(net_out, ':', kSearchGivenName, &given_name))
    account_info.set_given_name(given_name);

  std::string account_info_blob;
  if (!account_info.SerializeToString(&account_info_blob)) {
    LOG(ERROR) << "Failed to convert account info proto to string";
    return EXIT_CODE_WRITE_OUTPUT_FAILED;
  }
  return OutputForCaller(account_info_blob);
}

// Parses the output of a net ads command for '|token| : value'. Prints value to
// stdout.
int ParseSingleToken(const std::string& net_out, const std::string& token) {
  std::string value;
  if (!FindToken(net_out, ':', token, &value))
    return EXIT_CODE_FIND_TOKEN_FAILED;

  return OutputForCaller(value);
}

// Parses the output of net ads gpo list to get the list of GPOs. Prints out a
// serialized GpoList blob to stdout.
int ParseGpoList(const std::string& net_out,
                 PolicyScope scope,
                 const protos::DebugFlags& flags) {
  // Parse net output.
  GpoEntry current_gpo;
  std::vector<GpoEntry> gpo_list;
  const std::vector<std::string> lines = base::SplitString(
      net_out, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  LOG_IF(INFO, flags.log_gpo()) << kColorGpo << "Parsing GPO list ("
                                << lines.size() << " lines)" << kColorReset;
  bool found_separator = false;
  for (const std::string& line : lines) {
    if (line.find(kGpoToken_Separator) == 0) {
      // Separator between entries. Process last gpo if any.
      PushGpo(current_gpo, scope, &gpo_list, flags);
      current_gpo.Clear();
      found_separator = true;
      continue;
    }

    // Collect data
    const size_t colon_pos = line.find(":");
    if (colon_pos == std::string::npos || colon_pos + 1 >= line.size())
      continue;
    const std::string key = line.substr(0, colon_pos);
    std::string value = line.substr(colon_pos + 1);
    base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value);

    bool already_set = false;
    bool version_error = false;
    bool flags_error = false;
    if (key == kGpoToken_Name) {
      already_set = !current_gpo.name.empty();
      current_gpo.name = value;
    } else if (key == kGpoToken_Filesyspath) {
      already_set = !current_gpo.filesyspath.empty();
      current_gpo.filesyspath = value;
    } else if (key == kGpoToken_VersionUser) {
      already_set = current_gpo.version_user != 0;
      version_error = !ParseGpoVersion(value, &current_gpo.version_user);
    } else if (key == kGpoToken_VersionMachine) {
      already_set = current_gpo.version_machine != 0;
      version_error = !ParseGpoVersion(value, &current_gpo.version_machine);
    } else if (key == kGpoToken_Options) {
      already_set = current_gpo.gp_flags != kGpFlagInvalid;
      flags_error = !ParseGpFlags(value, &current_gpo.gp_flags);
    }

    // Sanity check that we don't miss separators between GPOs.
    if (already_set) {
      LOG(ERROR) << "Failed to parse GPO data (bad format)";
      return EXIT_CODE_PARSE_INPUT_FAILED;
    }

    if (version_error) {
      LOG(ERROR) << "Failed to parse GPO version '" << value << "'";
      return EXIT_CODE_PARSE_INPUT_FAILED;
    }

    if (flags_error) {
      LOG(ERROR) << "Failed to parse GP flags '" << value << "'";
      return EXIT_CODE_PARSE_INPUT_FAILED;
    }
  }

  // Just in case there's no separator in the end.
  PushGpo(current_gpo, scope, &gpo_list, flags);

  if (!found_separator) {
    // This usually happens when something went wrong, e.g. connection error.
    LOG(ERROR) << "Failed to parse GPO data (no separator, did net fail?)";
    return EXIT_CODE_PARSE_INPUT_FAILED;
  }

  if (flags.log_gpo() && LOG_IS_ON(INFO)) {
    LOG(INFO) << kColorGpo << "Found " << gpo_list.size() << " GPOs."
              << kColorReset;
    for (size_t n = 0; n < gpo_list.size(); ++n) {
      LOG(INFO) << kColorGpo << n + 1 << ")" << kColorReset;
      gpo_list[n].Log();
    }
  }

  // Convert to proto.
  protos::GpoList gpo_list_proto;
  for (const GpoEntry& gpo : gpo_list) {
    // Split the filesyspath, e.g.
    //   \\chrome.lan\SysVol\chrome.lan\Policies\{3507856D-...-CF144DC5CC3A}
    // into
    // - the share (SysVol) and
    // - the directory (chrome.lan\Policies\...).
    // The first part (chrome.lan) is dropped and replaced by the domain
    // controller name when the GPOs are downloaded via smbclient.
    const std::vector<std::string> file_parts = base::SplitString(
        gpo.filesyspath, "\\/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
    if (file_parts.size() < 4 || !file_parts[0].empty() ||
        !file_parts[1].empty()) {
      LOG(ERROR) << "Failed to split filesyspath '" << gpo.filesyspath
                 << "' into service and directory parts";
      return EXIT_CODE_PARSE_INPUT_FAILED;
    }
    const std::string& share = file_parts[3];
    const std::string directory = base::JoinString(
        std::vector<std::string>(file_parts.begin() + 4, file_parts.end()),
        "\\");
    uint32_t version =
        scope == PolicyScope::USER ? gpo.version_user : gpo.version_machine;

    protos::GpoEntry* gpo_proto = gpo_list_proto.add_entries();
    gpo_proto->set_name(gpo.name);
    gpo_proto->set_share(share);
    gpo_proto->set_directory(directory);
    gpo_proto->set_version(version);
  }

  // Output data as proto blob.
  std::string gpo_list_blob;
  if (!gpo_list_proto.SerializeToString(&gpo_list_blob)) {
    LOG(ERROR) << "Failed to convert GPO list proto to string";
    return EXIT_CODE_WRITE_OUTPUT_FAILED;
  }
  return OutputForCaller(gpo_list_blob);
}

// Parses a set of GPO files and assembles a user or device policy proto. Writes
// the serialized policy blob to stdout. |gpo_file_paths_blob| is expected to be
// a serialized |protos::FilePathList| proto blob.
int ParsePreg(const std::string& gpo_file_paths_blob,
              PolicyScope scope,
              const protos::DebugFlags& flags) {
  // Parse FilePathList proto blob.
  protos::FilePathList gpo_file_paths_proto;
  if (!gpo_file_paths_proto.ParseFromString(gpo_file_paths_blob)) {
    LOG(ERROR) << "Failed to parse file paths blob";
    return EXIT_CODE_READ_INPUT_FAILED;
  }

  // Convert to list of base::FilePaths.
  std::vector<base::FilePath> gpo_file_paths;
  for (int n = 0; n < gpo_file_paths_proto.entries_size(); ++n)
    gpo_file_paths.push_back(base::FilePath(gpo_file_paths_proto.entries(n)));

  protos::GpoPolicyData data;
  switch (scope) {
    case PolicyScope::USER: {
      // Parse files into a user policy proto.
      em::CloudPolicySettings policy;
      if (!policy::ParsePRegFilesIntoUserPolicy(gpo_file_paths, &policy,
                                                flags.log_policy_values())) {
        return EXIT_CODE_PARSE_INPUT_FAILED;
      }

      // Serialize user policy proto to string.
      if (!policy.SerializeToString(data.mutable_user_or_device_policy()))
        return EXIT_CODE_WRITE_OUTPUT_FAILED;
      break;
    }
    case PolicyScope::MACHINE: {
      // Parse files into a device policy proto.
      em::ChromeDeviceSettingsProto policy;
      if (!policy::ParsePRegFilesIntoDevicePolicy(gpo_file_paths, &policy,
                                                  flags.log_policy_values())) {
        return EXIT_CODE_PARSE_INPUT_FAILED;
      }

      // Serialize policy proto to string.
      if (!policy.SerializeToString(data.mutable_user_or_device_policy()))
        return EXIT_CODE_WRITE_OUTPUT_FAILED;
      break;
    }
    default: {
      LOG(FATAL) << "invalid scope";
    }
  }

  // Parse GPOs again for extension policy. Note that it might be contained in
  // both scopes (USER and MACHINE). Note that this is slightly inefficient as
  // it loads and parses each GPO file a second time. It would be better if
  // preg_parser accepted multiple keys.
  policy::ExtensionPolicies extension_policies;
  if (!policy::ParsePRegFilesIntoExtensionPolicy(
          gpo_file_paths, &extension_policies, flags.log_policy_values())) {
    return EXIT_CODE_PARSE_INPUT_FAILED;
  }
  for (protos::ExtensionPolicy& proto : extension_policies)
    *data.add_extension_policies() = std::move(proto);

  // Output |data| as serialized string to stdout.
  std::string data_blob;
  if (!data.SerializeToString(&data_blob))
    return EXIT_CODE_WRITE_OUTPUT_FAILED;
  return OutputForCaller(data_blob);
}

// Parses the validity and renewal lifetimes of a TGT from the output of klist.
// Writes the serialized lifetime protobuf blob to stdout. For sample klist
// output see stub_klist_main.cc.
int ParseTgtLifetime(const std::string& klist_out) {
  std::vector<std::string> lines = base::SplitString(
      klist_out, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);

  time_t valid_from, expires, renew_until = 0;
  for (size_t n = 0; n < lines.size(); ++n) {
    if (Contains(lines[n], "krbtgt/") &&
        ParseTgtDateTime(lines[n], kValidFromOffset, &valid_from) &&
        ParseTgtDateTime(lines[n], kExpiresOffset, &expires)) {
      if (n + 1 < lines.size() &&
          base::StartsWith(lines[n + 1], kRenewUntil,
                           base::CompareCase::SENSITIVE) &&
          ParseTgtDateTime(lines[n + 1], kRenewUntilOffset, &renew_until)) {
        ++n;
      }

      // If the caller checked klist -s beforehand, the TGT should be valid and
      // these warnings should never be printed.
      time_t now = time(NULL);
      if (now + kTgtWarningGraceTimeSeconds < valid_from) {
        LOG(WARNING) << "TGT not yet valid? (now=" << now
                     << ", valid_from=" << valid_from << ")";
      }
      if (now + kTgtWarningGraceTimeSeconds > expires) {
        LOG(WARNING) << "TGT already expired? (now=" << now
                     << ", expires=" << expires << ")";
      }

      // Output lifetime as protobuf blob.
      protos::TgtLifetime lifetime;
      lifetime.set_validity_seconds(std::max<int64_t>(expires - now, 0));
      lifetime.set_renewal_seconds(std::max<int64_t>(renew_until - now, 0));

      std::string lifetime_blob;
      if (!lifetime.SerializeToString(&lifetime_blob)) {
        LOG(ERROR) << "Failed to convert lifetime proto to string";
        return EXIT_CODE_WRITE_OUTPUT_FAILED;
      }
      return OutputForCaller(lifetime_blob);
    }
  }

  LOG(ERROR) << "Failed to find krbtgt in klist output";
  return EXIT_CODE_PARSE_INPUT_FAILED;
}

int HandleCommand(const std::string& cmd,
                  const std::string& arg,
                  const protos::DebugFlags& flags) {
  if (cmd == kCmdParseServerInfo)
    return ParseServerInfo(arg);
  if (cmd == kCmdParseDcName)
    return ParseSingleToken(arg, kToken_DomainController);
  if (cmd == kCmdParseWorkgroup)
    return ParseSingleToken(arg, kToken_Workgroup);
  if (cmd == kCmdParseAccountInfo)
    return ParseAccountInfo(arg);
  if (cmd == kCmdParseUserGpoList)
    return ParseGpoList(arg, PolicyScope::USER, flags);
  if (cmd == kCmdParseDeviceGpoList)
    return ParseGpoList(arg, PolicyScope::MACHINE, flags);
  if (cmd == kCmdParseUserPreg)
    return ParsePreg(arg, PolicyScope::USER, flags);
  if (cmd == kCmdParseDevicePreg)
    return ParsePreg(arg, PolicyScope::MACHINE, flags);
  if (cmd == kCmdParseTgtLifetime)
    return ParseTgtLifetime(arg);

  LOG(ERROR) << "Bad command";
  return EXIT_CODE_BAD_COMMAND;
}

}  // namespace

}  // namespace authpolicy

int main(int argc, char* argv[]) {
  brillo::OpenLog("authpolicy_parser", true);
  brillo::InitLog(brillo::kLogToSyslog);

  // Required for base::SysInfo.
  base::AtExitManager at_exit_manager;

  // Require one argument, one of the kCmdParse* strings.
  if (argc <= 1) {
    LOG(ERROR) << "No command";
    return authpolicy::EXIT_CODE_BAD_COMMAND;
  }
  const char* cmd = argv[1];

  // Load debug flags from argv[2] if present.
  authpolicy::protos::DebugFlags flags;
  if (argc > 2 && !authpolicy::DeserializeFlags(argv[2], &flags)) {
    LOG(ERROR) << "Failed to deserialize flags";
    return authpolicy::EXIT_CODE_BAD_COMMAND;
  }

  // All commands take additional arguments via stdin.
  std::string stdin;
  if (!authpolicy::ReadPipeToString(STDIN_FILENO, &stdin)) {
    LOG(ERROR) << "Failed to read stdin";
    return authpolicy::EXIT_CODE_READ_INPUT_FAILED;
  }

  return authpolicy::HandleCommand(cmd, stdin, flags);
}
