// 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/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/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 search' tokens.
const char kNoResults[] = "Got 0 replies";

// 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 ";

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) << "  Name:        " << name;
    LOG(INFO) << "  Version:     " << version_user << " (user) "
              << version_machine << " (machine)";
    LOG(INFO) << "  GPFLags:     " << gp_flags;
  }

  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) << "Ignoring invalid GPO";
    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) << "Filtered out GPO (" << filter_reason << ")";
    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.c_str(), str.size())) {
    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 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, kNoResults, base::CompareCase::SENSITIVE))
    return OutputForCaller("");

  std::string object_guid;
  std::string sam_account_name;
  std::string common_name;
  std::string pwd_last_set_str;
  std::string user_account_control_str;
  if (!FindToken(net_out, ':', kSearchObjectGUID, &object_guid) ||
      !FindToken(net_out, ':', kSearchSAMAccountName, &sam_account_name) ||
      !FindToken(net_out, ':', kSearchCommonName, &common_name) ||
      !FindToken(net_out, ':', kSearchPwdLastSet, &pwd_last_set_str) ||
      !FindToken(net_out, ':', kSearchUserAccountControl,
                 &user_account_control_str)) {
    LOG(ERROR) << "Failed to parse account info";
    return EXIT_CODE_FIND_TOKEN_FAILED;
  }

  uint64_t pwd_last_set = 0;
  uint32_t user_account_control = 0;
  if (!base::StringToUint64(pwd_last_set_str, &pwd_last_set) ||
      !base::StringToUint(user_account_control_str, &user_account_control)) {
    LOG(ERROR) << "Failed to parse account info";
    return EXIT_CODE_PARSE_INPUT_FAILED;
  }

  // Output data as proto blob.
  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);
  account_info.set_pwd_last_set(pwd_last_set);
  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 net ads info to get the domain controller name and KDC
// IP address. Prints it to stdout.
int ParseRealmInfo(const std::string& net_out) {
  // Parse output for dc_name in 'LDAP server name: dc_name.some.domain'.
  std::string dc_name, kdc_ip;
  if (!FindToken(net_out, ':', "LDAP server name", &dc_name) ||
      !FindToken(net_out, ':', "KDC server", &kdc_ip)) {
    return EXIT_CODE_FIND_TOKEN_FAILED;
  }

  // We're only interested in the part before the dot.
  size_t dot_pos = dc_name.find('.');
  dc_name = dc_name.substr(0, dot_pos);

  protos::RealmInfo realm_info;
  realm_info.set_dc_name(dc_name);
  realm_info.set_kdc_ip(kdc_ip);
  std::string realm_info_blob;
  if (!realm_info.SerializeToString(&realm_info_blob)) {
    LOG(ERROR) << "Failed to convert realm info proto to string";
    return EXIT_CODE_WRITE_OUTPUT_FAILED;
  }

  return OutputForCaller(realm_info_blob);
}

// Parses the output of net ads workgroup to get the workgroup and prints it to
// stdout.
int ParseWorkgroup(const std::string& net_out) {
  std::string workgroup;
  if (!FindToken(net_out, ':', "Workgroup", &workgroup))
    return EXIT_CODE_FIND_TOKEN_FAILED;

  return OutputForCaller(workgroup);
}

// 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;
  std::vector<std::string> lines = base::SplitString(
      net_out, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  LOG_IF(INFO, flags.log_gpo())
      << "Parsing GPO list (" << lines.size() << " lines)";
  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?)";
    LOG(ERROR) << "Net response: " << net_out;
    return EXIT_CODE_PARSE_INPUT_FAILED;
  }

  if (flags.log_gpo() && LOG_IS_ON(INFO)) {
    LOG(INFO) << "Found " << gpo_list.size() << " GPOs.";
    for (size_t n = 0; n < gpo_list.size(); ++n) {
      LOG(INFO) << n + 1 << ")";
      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 base path (chrome.lan/SysVol) and
    // - the directory (chrome.lan\Policies\...).
    // Note the change from \ to / in base path.
    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;
    }
    std::string basepath = file_parts[2] + "/" + file_parts[3];
    file_parts =
        std::vector<std::string>(file_parts.begin() + 4, file_parts.end());
    std::string directory = base::JoinString(file_parts, "\\");

    protos::GpoEntry* gpo_proto = gpo_list_proto.add_entries();
    gpo_proto->set_name(gpo.name);
    gpo_proto->set_basepath(basepath);
    gpo_proto->set_directory(directory);
  }

  // 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)));

  std::string policy_blob;
  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(&policy_blob))
        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(&policy_blob))
        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;
  }

  // Store policy blob and extension policy in a GpoPolicyData struct.
  protos::GpoPolicyData data;
  data.set_user_or_device_policy(policy_blob);
  for (protos::ExtensionPolicy& proto : extension_policies)
    *data.add_extension_policies() = std::move(proto);

  std::string data_blob;
  if (!data.SerializeToString(&data_blob))
    return EXIT_CODE_WRITE_OUTPUT_FAILED;

  // Print the serialized policy data to stdout.
  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 < valid_from) {
        LOG(WARNING) << "TGT not yet valid? (now=" << now
                     << ", valid_from=" << valid_from << ")";
      }
      if (now > 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 == kCmdParseRealmInfo)
    return ParseRealmInfo(arg);
  if (cmd == kCmdParseWorkgroup)
    return ParseWorkgroup(arg);
  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);
}
