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