Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(856)

Unified Diff: src/platform/cryptohome/cryptohome.cc

Issue 2051003: Initial patch from Will. (Closed) Base URL: ssh://git@chromiumos-git/chromiumos
Patch Set: Address style nits. Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/platform/cryptohome/cryptohome.cc
diff --git a/src/platform/cryptohome/cryptohome.cc b/src/platform/cryptohome/cryptohome.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cdc9c5b768a41849716e4e1c2afd4f6c73a3bc36
--- /dev/null
+++ b/src/platform/cryptohome/cryptohome.cc
@@ -0,0 +1,337 @@
+// Copyright (c) 2009 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.
+//
+// Cryptohome client that uses the dbus client interface
+
+#include <base/basictypes.h>
+#include <base/command_line.h>
+#include <base/logging.h>
+#include <base/string_util.h>
+#include <chromeos/dbus/dbus.h>
+#include <chromeos/dbus/service_constants.h>
+#include <chromeos/utility.h>
+
+#include <iostream>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "cryptohome/username_passkey.h"
+#include "cryptohome/bindings/client.h"
+
+namespace switches {
+ static const char kActionSwitch[] = "action";
+ static const char *kActions[] = {
+ "mount",
+ "unmount",
+ "is_mounted",
+ "test_auth",
+ "migrate_key",
+ "remove",
+ NULL };
+ enum ActionEnum {
+ ACTION_MOUNT,
+ ACTION_UNMOUNT,
+ ACTION_MOUNTED,
+ ACTION_TEST_AUTH,
+ ACTION_MIGRATE_KEY,
+ ACTION_REMOVE };
+ static const char kUserSwitch[] = "user";
+ static const char kPasswordSwitch[] = "password";
+ static const char kOldPasswordSwitch[] = "old_password";
+} // namespace switches
+
+chromeos::Blob GetSystemSalt(const chromeos::dbus::Proxy& proxy) {
+ chromeos::glib::ScopedError error;
+ GArray* salt;
+ GError **errptr = &chromeos::Resetter(&error).lvalue();
+ if (!org_chromium_CryptohomeInterface_get_system_salt(proxy.gproxy(),
+ &salt,
+ errptr)) {
+ LOG(ERROR) << "GetSystemSalt failed: " << error->message;
+ return chromeos::Blob();
+ }
+
+ chromeos::Blob system_salt;
+ system_salt.resize(salt->len);
+ if(system_salt.size() == salt->len) {
+ memcpy(&system_salt[0], static_cast<const void*>(salt->data), salt->len);
+ } else {
+ system_salt.clear();
+ }
+ g_array_free(salt, false);
+ return system_salt;
+}
+
+bool GetUsername(const CommandLine* cl, std::string* user_out) {
+ *user_out = cl->GetSwitchValueASCII(switches::kUserSwitch);
+
+ if(user_out->length() == 0) {
+ LOG(ERROR) << "No user specified (--user=<user>)";
+ return false;
+ }
+ return true;
+}
+
+bool GetUsernamePassword(const chromeos::dbus::Proxy& proxy,
+ const CommandLine* cl,
+ std::string* user_out,
+ std::string* password_out,
+ std::string* old_password_out = NULL) {
+ if(!GetUsername(cl, user_out)) {
+ return false;
+ }
+
+ std::string password = cl->GetSwitchValueASCII(switches::kPasswordSwitch);
+ std::string old_password = cl->GetSwitchValueASCII(
+ switches::kOldPasswordSwitch);
+
+ if(old_password_out != NULL && old_password.length() == 0) {
+ struct termios original_attr;
+ struct termios new_attr;
+ tcgetattr(0, &original_attr);
+ memcpy(&new_attr, &original_attr, sizeof(new_attr));
+ new_attr.c_lflag &= ~(ECHO);
+ tcsetattr(0, TCSANOW, &new_attr);
+ std::cout << "Enter old password for <" << (*user_out) << ">: ";
+ std::cin >> old_password;
+ std::cout << std::endl;
+ tcsetattr(0, TCSANOW, &original_attr);
+ }
+ if(password.length() == 0) {
+ struct termios original_attr;
+ struct termios new_attr;
+ tcgetattr(0, &original_attr);
+ memcpy(&new_attr, &original_attr, sizeof(new_attr));
+ new_attr.c_lflag &= ~(ECHO);
+ tcsetattr(0, TCSANOW, &new_attr);
+ std::cout << "Enter password for <" << (*user_out) << ">: ";
+ std::cin >> password;
+ std::cout << std::endl
+ << "Re-enter password for <" << (*user_out) << ">: ";
+ std::string verification;
+ std::cin >> verification;
+ std::cout << std::endl;
+ tcsetattr(0, TCSANOW, &original_attr);
+ if(verification != password) {
+ LOG(ERROR) << "Passwords do not match.";
+ return false;
+ }
+ }
+
+ std::string trimmed_password;
+ TrimString(password, "\r\n", &trimmed_password);
+ cryptohome::UsernamePasskey up(
+ cryptohome::UsernamePasskey::FromUsernamePassword((*user_out).c_str(),
+ trimmed_password.c_str(), GetSystemSalt(proxy)));
+ cryptohome::SecureBlob passkey = up.GetPasskey();
+ *password_out = std::string(reinterpret_cast<char*>(&passkey[0]),
+ passkey.size());
+ if(old_password_out != NULL) {
+ TrimString(old_password, "\r\n", &trimmed_password);
+ cryptohome::UsernamePasskey old_up(
+ cryptohome::UsernamePasskey::FromUsernamePassword((*user_out).c_str(),
+ trimmed_password.c_str(), GetSystemSalt(proxy)));
+ passkey = old_up.GetPasskey();
+ *old_password_out = std::string(reinterpret_cast<char*>(&passkey[0]),
+ passkey.size());
+ }
+
+ return true;
+}
+
+bool AskHardQuestion(const std::string& user) {
+ std::cout << "!!! The password you entered did not unwrap the user's"
+ << std::endl
+ << "!!! vault key. If you proceed, the user's cryptohome"
+ << std::endl
+ << "!!! will be DELETED and RECREATED."
+ << std::endl
+ << "!!!"
+ << std::endl
+ << "!!! Re-enter the username at the prompt to create a new"
+ << std::endl
+ << "!!! cryptohome for the user."
+ << std::endl
+ << "Enter the username <" << user << ">: ";
+ std::string verification;
+ std::cin >> verification;
+ if(user != verification) {
+ LOG(ERROR) << "Usernames do not match.";
+ return false;
+ }
+ return true;
+}
+
+bool ConfirmRemove(const std::string& user) {
+ std::cout << "!!! Are you sure you want to remove the user's cryptohome?"
+ << std::endl
+ << "!!!"
+ << std::endl
+ << "!!! Re-enter the username at the prompt to remove the"
+ << std::endl
+ << "!!! cryptohome for the user."
+ << std::endl
+ << "Enter the username <" << user << ">: ";
+ std::string verification;
+ std::cin >> verification;
+ if(user != verification) {
+ LOG(ERROR) << "Usernames do not match.";
+ return false;
+ }
+ return true;
+}
+
+int main(int argc, char **argv) {
+ CommandLine::Init(argc, argv);
+ logging::InitLogging(NULL,
+ logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
+ logging::DONT_LOCK_LOG_FILE,
+ logging::APPEND_TO_OLD_LOG_FILE);
+
+ CommandLine *cl = CommandLine::ForCurrentProcess();
+ std::string action = cl->GetSwitchValueASCII(switches::kActionSwitch);
+ g_type_init();
+ chromeos::dbus::BusConnection bus = chromeos::dbus::GetSystemBusConnection();
+ chromeos::dbus::Proxy proxy(bus,
+ cryptohome::kCryptohomeServiceName,
+ cryptohome::kCryptohomeServicePath,
+ cryptohome::kCryptohomeInterface);
+ DCHECK(proxy.gproxy()) << "Failed to acquire proxy";
+
+ if (!strcmp(switches::kActions[switches::ACTION_MOUNT], action.c_str())) {
+ std::string user, password;
+
+ if(!GetUsernamePassword(proxy, cl, &user, &password)) {
+ return 1;
+ }
+
+ gboolean done = false;
+ chromeos::glib::ScopedError error;
+ GError **errptr = &chromeos::Resetter(&error).lvalue();
+ org_chromium_CryptohomeInterface_check_key(proxy.gproxy(),
+ user.c_str(),
+ password.c_str(),
+ &done,
+ errptr);
+ if(!done) {
+ // TODO(fes): Remove when Mount no longer automatically deletes cryptohome
+ // on passkey failure.
+ if(!AskHardQuestion(user)) {
+ return 1;
+ }
+ }
+
+ errptr = &chromeos::Resetter(&error).lvalue();
+ if (!org_chromium_CryptohomeInterface_mount(proxy.gproxy(),
+ user.c_str(),
+ password.c_str(),
+ &done,
+ errptr)) {
+ LOG(ERROR) << "Mount call failed: " << error->message;
+ }
+ LOG_IF(ERROR, !done) << "Mount did not complete?";
+ LOG_IF(INFO, done) << "Call completed";
+ } else if (!strcmp(switches::kActions[switches::ACTION_TEST_AUTH],
+ action.c_str())) {
+ std::string user, password;
+
+ if(!GetUsernamePassword(proxy, cl, &user, &password)) {
+ return 1;
+ }
+
+ gboolean done = false;
+ chromeos::glib::ScopedError error;
+ GError **errptr = &chromeos::Resetter(&error).lvalue();
+ if (!org_chromium_CryptohomeInterface_check_key(proxy.gproxy(),
+ user.c_str(),
+ password.c_str(),
+ &done,
+ errptr)) {
+ LOG(ERROR) << "CheckKey call failed: " << error->message;
+ }
+ LOG_IF(ERROR, !done) << "CheckKey did not complete?";
+ LOG_IF(INFO, done) << "Call completed";
+ } else if (!strcmp(switches::kActions[switches::ACTION_MIGRATE_KEY],
+ action.c_str())) {
+ std::string user, password, old_password;
+
+ if(!GetUsernamePassword(proxy, cl, &user, &password, &old_password)) {
+ return 1;
+ }
+
+ gboolean done = false;
+ chromeos::glib::ScopedError error;
+ GError **errptr = &chromeos::Resetter(&error).lvalue();
+ if (!org_chromium_CryptohomeInterface_migrate_key(proxy.gproxy(),
+ user.c_str(),
+ old_password.c_str(),
+ password.c_str(),
+ &done,
+ errptr)) {
+ LOG(ERROR) << "MigrateKey call failed: " << error->message;
+ }
+ LOG_IF(ERROR, !done) << "MigrateKey did not complete?";
+ LOG_IF(INFO, done) << "Call completed";
+ } else if (!strcmp(switches::kActions[switches::ACTION_REMOVE],
+ action.c_str())) {
+ std::string user;
+
+ if(!GetUsername(cl, &user)) {
+ return 1;
+ }
+
+ if(!ConfirmRemove(user)) {
+ return 1;
+ }
+
+ gboolean done = false;
+ chromeos::glib::ScopedError error;
+ GError **errptr = &chromeos::Resetter(&error).lvalue();
+ if (!org_chromium_CryptohomeInterface_remove(proxy.gproxy(),
+ user.c_str(),
+ &done,
+ errptr)) {
+ LOG(ERROR) << "Remove call failed: " << error->message;
+ }
+ LOG_IF(ERROR, !done) << "Remove did not complete?";
+ LOG_IF(INFO, done) << "Call completed";
+ } else if (!strcmp(switches::kActions[switches::ACTION_UNMOUNT],
+ action.c_str())) {
+ chromeos::glib::ScopedError error;
+ GError **errptr = &chromeos::Resetter(&error).lvalue();
+ gboolean done = false;
+ if (!org_chromium_CryptohomeInterface_unmount(proxy.gproxy(),
+ &done,
+ errptr)) {
+ LOG(ERROR) << "Unmount call failed: " << error->message;
+ }
+ LOG_IF(ERROR, !done) << "Unmount did not complete?";
+ LOG_IF(INFO, done) << "Call completed";
+ } else if (!strcmp(switches::kActions[switches::ACTION_MOUNTED],
+ action.c_str())) {
+ chromeos::glib::ScopedError error;
+ GError **errptr = &chromeos::Resetter(&error).lvalue();
+ gboolean done = false;
+ if (!org_chromium_CryptohomeInterface_is_mounted(proxy.gproxy(),
+ &done,
+ errptr)) {
+ LOG(ERROR) << "IsMounted call failed: " << error->message;
+ }
+ std::cout << done << std::endl;
+
+ } else {
+ LOG(ERROR) << "Unknown action or no action given. Available actions: ";
+ for(int i = 0; /* loop forever */; i++) {
+ if(!switches::kActions[i]) {
+ break;
+ }
+ LOG(ERROR) << " --action=" << switches::kActions[i];
+ }
+ }
+ return 0;
+}

Powered by Google App Engine
This is Rietveld 408576698