Index: src/platform/cryptohome/service.cc |
diff --git a/src/platform/cryptohome/service.cc b/src/platform/cryptohome/service.cc |
index b4d89bc5001073ef49707aa648da9214a383b49b..bbe5c35c536e045e911278c642b77bb9904c1034 100644 |
--- a/src/platform/cryptohome/service.cc |
+++ b/src/platform/cryptohome/service.cc |
@@ -8,9 +8,10 @@ |
#include <stdio.h> |
#include <stdlib.h> |
-#include "cryptohome/authenticator.h" |
#include "cryptohome/interface.h" |
-#include "cryptohome/username_passhash.h" |
+#include "cryptohome/mount.h" |
+#include "cryptohome/secure_blob.h" |
+#include "cryptohome/username_passkey.h" |
// Forcibly namespace the dbus-bindings generated server bindings instead of |
// modifying the files afterward. |
@@ -22,25 +23,25 @@ namespace gobject { // NOLINT |
namespace cryptohome { |
-const char *Service::kDefaultMountCommand = "/usr/sbin/mount.cryptohome"; |
-const char *Service::kDefaultUnmountCommand = "/usr/sbin/umount.cryptohome"; |
-const char *Service::kDefaultIsMountedCommand = |
- "/bin/mount | /bin/grep -q ' /home/chronos/user '"; |
- |
Service::Service() : loop_(NULL), |
- auth_(new Authenticator), |
cryptohome_(NULL), |
- mount_command_(kDefaultMountCommand), |
- unmount_command_(kDefaultUnmountCommand), |
- is_mounted_command_(kDefaultIsMountedCommand) { } |
+ system_salt_(), |
+ mount_(NULL) { } |
+ |
Service::~Service() { |
if (loop_) |
g_main_loop_unref(loop_); |
if (cryptohome_) |
g_object_unref(cryptohome_); |
+ if (mount_) |
+ delete mount_; |
} |
bool Service::Initialize() { |
+ if(mount_ == NULL) { |
+ mount_ = new cryptohome::Mount(); |
+ mount_->Init(); |
+ } |
// Install the type-info for the service with dbus. |
dbus_g_object_type_install_info(gobject::cryptohome_get_type(), |
&gobject::dbus_glib_cryptohome_object_info); |
@@ -70,18 +71,48 @@ gboolean Service::CheckKey(gchar *userid, |
gchar *key, |
gboolean *OUT_success, |
GError **error) { |
- UsernamePasshash creds(userid, strlen(userid), key, strlen(key)); |
- if (!auth_->Init()) { |
- *OUT_success = FALSE; |
- return TRUE; |
+ UsernamePasskey credentials(userid, strlen(userid), |
+ chromeos::Blob(key, key + strlen(key))); |
+ |
+ // TODO(fes): Handle CHROMEOS_PAM_LOCALACCOUNT |
+ *OUT_success = mount_->TestCredentials(credentials); |
+ return TRUE; |
+} |
+ |
+gboolean Service::MigrateKey(gchar *userid, |
+ gchar *from_key, |
+ gchar *to_key, |
+ gboolean *OUT_success, |
+ GError **error) { |
+ UsernamePasskey credentials(userid, strlen(userid), |
+ chromeos::Blob(to_key, to_key + strlen(to_key))); |
+ |
+ *OUT_success = mount_->MigratePasskey(credentials, from_key); |
+ return TRUE; |
+} |
+ |
+gboolean Service::Remove(gchar *userid, |
+ gboolean *OUT_success, |
+ GError **error) { |
+ UsernamePasskey credentials(userid, strlen(userid), |
+ chromeos::Blob()); |
+ |
+ *OUT_success = mount_->RemoveCryptohome(credentials); |
+ return TRUE; |
+} |
+ |
+gboolean Service::GetSystemSalt(GArray **OUT_salt, GError **error) { |
+ if(system_salt_.size() == 0) { |
+ system_salt_ = mount_->GetSystemSalt(); |
} |
- *OUT_success = auth_->TestAllMasterKeys(creds); |
+ *OUT_salt = g_array_new(false, false, 1); |
+ g_array_append_vals(*OUT_salt, &system_salt_.front(), system_salt_.size()); |
+ |
return TRUE; |
} |
gboolean Service::IsMounted(gboolean *OUT_is_mounted, GError **error) { |
- int status = system(is_mounted_command()); |
- *OUT_is_mounted = !status; |
+ *OUT_is_mounted = mount_->IsCryptohomeMounted(); |
return TRUE; |
} |
@@ -89,42 +120,44 @@ gboolean Service::Mount(gchar *userid, |
gchar *key, |
gboolean *OUT_done, |
GError **error) { |
- // Never double mount. |
- // This will mean we don't mount over existing mounts, |
- // but at present, we reboot on user change so it is ok. |
- // Later, this can be more intelligent. |
- if (IsMounted(OUT_done, error) && *OUT_done) { |
- *OUT_done = FALSE; |
- return TRUE; |
- } |
- // Note, by doing this we allow any chronos caller to |
- // send a variable for use in the scripts. Bad idea. |
- // Thankfully, this will go away with the scripts. |
- setenv("CHROMEOS_USER", userid, 1); |
- FILE *mount = popen(mount_command(), "w"); |
- if (!mount) { |
- // TODO(wad) *error = |
- return FALSE; |
+ UsernamePasskey credentials(userid, strlen(userid), |
+ chromeos::Blob(key, key + strlen(key))); |
+ |
+ if(mount_->IsCryptohomeMounted()) { |
+ if(mount_->IsCryptohomeMountedForUser(credentials)) { |
+ LOG(INFO) << "Cryptohome already mounted for this user"; |
+ *OUT_done = TRUE; |
+ return TRUE; |
+ } else { |
+ if(!mount_->UnmountCryptohome()) { |
+ LOG(ERROR) << "Could not unmount cryptohome from previous user"; |
+ *OUT_done = FALSE; |
+ return TRUE; |
+ } |
+ } |
} |
- fprintf(mount, "%s", key); |
- int status = pclose(mount); |
- if (status != 0) { |
- *OUT_done = FALSE; |
- } else { |
- *OUT_done = TRUE; |
+ |
+ // TODO(fes): Iterate keys if we change how cryptohome keeps track of key |
+ // indexes. Right now, 0 is always the current, and 0+n should only be used |
+ // temporarily during password migration. |
+ Mount::MountError mount_error = Mount::MOUNT_ERROR_NONE; |
+ *OUT_done = mount_->MountCryptohome(credentials, 0, &mount_error); |
+ if(!(*OUT_done) && (mount_error == Mount::MOUNT_ERROR_KEY_FAILURE)) { |
+ // If there is a key failure, create cryptohome from scratch. |
+ // TODO(fes): remove this when Chrome is no longer expecting this behavior. |
+ if(mount_->RemoveCryptohome(credentials)) { |
+ *OUT_done = mount_->MountCryptohome(credentials, 0, &mount_error); |
+ } |
} |
return TRUE; |
} |
gboolean Service::Unmount(gboolean *OUT_done, GError **error) { |
- // Check for a mount first. |
- if (IsMounted(OUT_done, error) && !*OUT_done) { |
- *OUT_done = TRUE; // unmounting nothing works fine. |
- return TRUE; |
+ if(mount_->IsCryptohomeMounted()) { |
+ *OUT_done = mount_->UnmountCryptohome(); |
+ } else { |
+ *OUT_done = true; |
} |
- |
- int status = system(unmount_command()); |
- *OUT_done = !status; |
return TRUE; |
} |