// Copyright (c) 2012 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.

// This is the Chaps client. It sends calls to the Chaps daemon via D-Bus.

#include <stdio.h>
#include <stdlib.h>

#include <string>
#include <vector>

#include <base/command_line.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/time/time.h>
#include <chromeos/syslog_logging.h>

#include "chaps/chaps_proxy.h"
#include "chaps/chaps_utility.h"
#include "chaps/isolate.h"
#include "chaps/token_manager_client.h"

using base::FilePath;
using chaps::IsolateCredentialManager;
using chromeos::SecureBlob;
using std::string;
using std::vector;

namespace {

void PrintHelp() {
  printf("Usage: chaps_client COMMAND [ARGUMENTS]\n");
  printf("Commands:\n");
  printf("  --ping : Checks that the Chaps daemon is available.\n");
  printf("  --load --path=<path> --auth=<auth> [--label=<label>]"
         " : Loads the token at the given path.\n");
  printf("  --unload --path=<path> : Unloads the token at the given path.\n");
  printf("  --change_auth --path=<path> --auth=<old_auth> --new_auth=<new_auth>"
         " : Changes authorization data for the token at the given path.\n");
  printf("  --set_log_level=<level> : Sets the chapsd logging level.\n"
         "    Levels: \n      2 - Errors Only\n      1 - Warnings and Errors\n"
         "      0 - Normal\n     -1 - Verbose (Logs PKCS #11 calls.)\n"
         "     -2 - More Verbose (Logs PKCS #11 calls and arguments.)\n");
  printf("  --list : Lists all loaded token paths.\n");
}

void Ping() {
  chaps::ChapsProxyImpl proxy;
  if (!proxy.Init())
    exit(-1);
  vector<uint64_t> slot_list;
  uint32_t result = proxy.GetSlotList(
      IsolateCredentialManager::GetDefaultIsolateCredential(),
      true,
      &slot_list);
  if (result != 0) {
    LOG(ERROR) << "Chaps is available but failed to provide a token list.";
    exit(-1);
  }
  LOG(INFO) << "Chaps is available with " << slot_list.size() << " token(s).";
}

// Loads a token given a path and auth data.
void LoadToken(const string& path, const string& auth, const string& label) {
  chaps::TokenManagerClient client;
  int slot_id = -1;
  client.LoadToken(IsolateCredentialManager::GetDefaultIsolateCredential(),
                   FilePath(path),
                   SecureBlob(auth.begin(), auth.end()),
                   label,
                   &slot_id);
  LOG(INFO) << "LoadToken: " << path << " - slot = " << slot_id;
}

// Unloads a token given a path.
void UnloadToken(const string& path) {
  chaps::TokenManagerClient client;
  client.UnloadToken(IsolateCredentialManager::GetDefaultIsolateCredential(),
                     FilePath(path));
  LOG(INFO) << "Sent Event: Logout: " << path;
}

// Changes authorization data for a token at the given path.
void ChangeAuthData(const string& path,
                    const string& auth_old,
                    const string& auth_new) {
  chaps::TokenManagerClient client;
  client.ChangeTokenAuthData(
      FilePath(path),
      SecureBlob(auth_old.begin(), auth_old.end()),
      SecureBlob(auth_new.begin(), auth_new.end()));
  LOG(INFO) << "Sent Event: Change Authorization Data: " << path;
}

// Sets the logging level.
void SetLogLevel(int level) {
  chaps::ChapsProxyImpl proxy;
  if (!proxy.Init())
    exit(-1);
  proxy.SetLogLevel(level);
}

void ListTokens() {
  chaps::ChapsProxyImpl proxy;
  if (!proxy.Init())
    exit(-1);
  vector<uint64_t> slot_list;
  uint32_t result = proxy.GetSlotList(
      IsolateCredentialManager::GetDefaultIsolateCredential(),
      true,
      &slot_list);
  if (result != 0)
    exit(-1);
  chaps::TokenManagerClient client;
  for (size_t i = 0; i < slot_list.size(); ++i) {
    int slot = slot_list[i];
    FilePath path;
    if (client.GetTokenPath(
        IsolateCredentialManager::GetDefaultIsolateCredential(),
        slot,
        &path)) {
      LOG(INFO) << "Slot " << slot << ": " << path.value();
    } else {
      LOG(INFO) << "Slot " << slot << ": Empty";
    }
  }
}

}  // namespace

int main(int argc, char** argv) {
  base::CommandLine::Init(argc, argv);
  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
  chromeos::InitLog(chromeos::kLogToSyslog | chromeos::kLogToStderr);

  bool ping = cl->HasSwitch("ping");
  bool load = (cl->HasSwitch("load") &&
               cl->HasSwitch("path") &&
               cl->HasSwitch("auth"));
  bool unload = cl->HasSwitch("unload") && cl->HasSwitch("path");
  bool change_auth = (cl->HasSwitch("change_auth") &&
                      cl->HasSwitch("path") &&
                      cl->HasSwitch("auth") &&
                      cl->HasSwitch("new_auth"));
  bool set_log_level = cl->HasSwitch("set_log_level");
  bool list = cl->HasSwitch("list");
  if (ping + load + unload + change_auth + set_log_level + list != 1) {
    PrintHelp();
    exit(-1);
  }
  if (ping) {
    Ping();
  } else if (load) {
    string label = "Default Token";
    if (cl->HasSwitch("label"))
      label = cl->GetSwitchValueASCII("label");
    LoadToken(cl->GetSwitchValueASCII("path"),
              cl->GetSwitchValueASCII("auth"),
              label);
  } else if (change_auth) {
    ChangeAuthData(cl->GetSwitchValueASCII("path"),
                   cl->GetSwitchValueASCII("auth"),
                   cl->GetSwitchValueASCII("new_auth"));
  } else if (unload) {
    UnloadToken(cl->GetSwitchValueASCII("path"));
  } else if (set_log_level) {
    int level = 0;
    if (!base::StringToInt(cl->GetSwitchValueASCII("set_log_level"), &level)) {
      LOG(ERROR) << "Invalid argument.";
      exit(-1);
    }
    SetLogLevel(level);
  } else if (list) {
    ListTokens();
  }
  return 0;
}
