OLD | NEW |
1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 #include "cryptohome/service.h" | 4 #include "cryptohome/service.h" |
5 | 5 |
6 #include <base/logging.h> | 6 #include <base/logging.h> |
7 #include <chromeos/dbus/dbus.h> | 7 #include <chromeos/dbus/dbus.h> |
8 #include <stdio.h> | 8 #include <stdio.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 | 10 |
11 #include "cryptohome/authenticator.h" | |
12 #include "cryptohome/interface.h" | 11 #include "cryptohome/interface.h" |
13 #include "cryptohome/username_passhash.h" | 12 #include "cryptohome/mount.h" |
| 13 #include "cryptohome/secure_blob.h" |
| 14 #include "cryptohome/username_passkey.h" |
14 | 15 |
15 // Forcibly namespace the dbus-bindings generated server bindings instead of | 16 // Forcibly namespace the dbus-bindings generated server bindings instead of |
16 // modifying the files afterward. | 17 // modifying the files afterward. |
17 namespace cryptohome { // NOLINT | 18 namespace cryptohome { // NOLINT |
18 namespace gobject { // NOLINT | 19 namespace gobject { // NOLINT |
19 #include "cryptohome/bindings/server.h" | 20 #include "cryptohome/bindings/server.h" |
20 } // namespace gobject | 21 } // namespace gobject |
21 } // namespace cryptohome | 22 } // namespace cryptohome |
22 | 23 |
23 namespace cryptohome { | 24 namespace cryptohome { |
24 | 25 |
25 const char *Service::kDefaultMountCommand = "/usr/sbin/mount.cryptohome"; | 26 Service::Service() : loop_(NULL), |
26 const char *Service::kDefaultUnmountCommand = "/usr/sbin/umount.cryptohome"; | 27 cryptohome_(NULL), |
27 const char *Service::kDefaultIsMountedCommand = | 28 system_salt_(), |
28 "/bin/mount | /bin/grep -q ' /home/chronos/user '"; | 29 mount_(NULL) { } |
29 | 30 |
30 Service::Service() : loop_(NULL), | |
31 auth_(new Authenticator), | |
32 cryptohome_(NULL), | |
33 mount_command_(kDefaultMountCommand), | |
34 unmount_command_(kDefaultUnmountCommand), | |
35 is_mounted_command_(kDefaultIsMountedCommand) { } | |
36 Service::~Service() { | 31 Service::~Service() { |
37 if (loop_) | 32 if (loop_) |
38 g_main_loop_unref(loop_); | 33 g_main_loop_unref(loop_); |
39 if (cryptohome_) | 34 if (cryptohome_) |
40 g_object_unref(cryptohome_); | 35 g_object_unref(cryptohome_); |
| 36 if (mount_) |
| 37 delete mount_; |
41 } | 38 } |
42 | 39 |
43 bool Service::Initialize() { | 40 bool Service::Initialize() { |
| 41 if(mount_ == NULL) { |
| 42 mount_ = new cryptohome::Mount(); |
| 43 mount_->Init(); |
| 44 } |
44 // Install the type-info for the service with dbus. | 45 // Install the type-info for the service with dbus. |
45 dbus_g_object_type_install_info(gobject::cryptohome_get_type(), | 46 dbus_g_object_type_install_info(gobject::cryptohome_get_type(), |
46 &gobject::dbus_glib_cryptohome_object_info); | 47 &gobject::dbus_glib_cryptohome_object_info); |
47 return Reset(); | 48 return Reset(); |
48 } | 49 } |
49 | 50 |
50 bool Service::Reset() { | 51 bool Service::Reset() { |
51 if (cryptohome_) | 52 if (cryptohome_) |
52 g_object_unref(cryptohome_); | 53 g_object_unref(cryptohome_); |
53 cryptohome_ = reinterpret_cast<gobject::Cryptohome*>( | 54 cryptohome_ = reinterpret_cast<gobject::Cryptohome*>( |
54 g_object_new(gobject::cryptohome_get_type(), NULL)); | 55 g_object_new(gobject::cryptohome_get_type(), NULL)); |
55 // Allow references to this instance. | 56 // Allow references to this instance. |
56 cryptohome_->service = this; | 57 cryptohome_->service = this; |
57 | 58 |
58 if (loop_) { | 59 if (loop_) { |
59 ::g_main_loop_unref(loop_); | 60 ::g_main_loop_unref(loop_); |
60 } | 61 } |
61 loop_ = g_main_loop_new(NULL, false); | 62 loop_ = g_main_loop_new(NULL, false); |
62 if (!loop_) { | 63 if (!loop_) { |
63 LOG(ERROR) << "Failed to create main loop"; | 64 LOG(ERROR) << "Failed to create main loop"; |
64 return false; | 65 return false; |
65 } | 66 } |
66 return true; | 67 return true; |
67 } | 68 } |
68 | 69 |
69 gboolean Service::CheckKey(gchar *userid, | 70 gboolean Service::CheckKey(gchar *userid, |
70 gchar *key, | 71 gchar *key, |
71 gboolean *OUT_success, | 72 gboolean *OUT_success, |
72 GError **error) { | 73 GError **error) { |
73 UsernamePasshash creds(userid, strlen(userid), key, strlen(key)); | 74 UsernamePasskey credentials(userid, strlen(userid), |
74 if (!auth_->Init()) { | 75 chromeos::Blob(key, key + strlen(key))); |
75 *OUT_success = FALSE; | 76 |
76 return TRUE; | 77 // TODO(fes): Handle CHROMEOS_PAM_LOCALACCOUNT |
| 78 *OUT_success = mount_->TestCredentials(credentials); |
| 79 return TRUE; |
| 80 } |
| 81 |
| 82 gboolean Service::MigrateKey(gchar *userid, |
| 83 gchar *from_key, |
| 84 gchar *to_key, |
| 85 gboolean *OUT_success, |
| 86 GError **error) { |
| 87 UsernamePasskey credentials(userid, strlen(userid), |
| 88 chromeos::Blob(to_key, to_key + strlen(to_key))); |
| 89 |
| 90 *OUT_success = mount_->MigratePasskey(credentials, from_key); |
| 91 return TRUE; |
| 92 } |
| 93 |
| 94 gboolean Service::Remove(gchar *userid, |
| 95 gboolean *OUT_success, |
| 96 GError **error) { |
| 97 UsernamePasskey credentials(userid, strlen(userid), |
| 98 chromeos::Blob()); |
| 99 |
| 100 *OUT_success = mount_->RemoveCryptohome(credentials); |
| 101 return TRUE; |
| 102 } |
| 103 |
| 104 gboolean Service::GetSystemSalt(GArray **OUT_salt, GError **error) { |
| 105 if(system_salt_.size() == 0) { |
| 106 system_salt_ = mount_->GetSystemSalt(); |
77 } | 107 } |
78 *OUT_success = auth_->TestAllMasterKeys(creds); | 108 *OUT_salt = g_array_new(false, false, 1); |
| 109 g_array_append_vals(*OUT_salt, &system_salt_.front(), system_salt_.size()); |
| 110 |
79 return TRUE; | 111 return TRUE; |
80 } | 112 } |
81 | 113 |
82 gboolean Service::IsMounted(gboolean *OUT_is_mounted, GError **error) { | 114 gboolean Service::IsMounted(gboolean *OUT_is_mounted, GError **error) { |
83 int status = system(is_mounted_command()); | 115 *OUT_is_mounted = mount_->IsCryptohomeMounted(); |
84 *OUT_is_mounted = !status; | |
85 return TRUE; | 116 return TRUE; |
86 } | 117 } |
87 | 118 |
88 gboolean Service::Mount(gchar *userid, | 119 gboolean Service::Mount(gchar *userid, |
89 gchar *key, | 120 gchar *key, |
90 gboolean *OUT_done, | 121 gboolean *OUT_done, |
91 GError **error) { | 122 GError **error) { |
92 // Never double mount. | 123 UsernamePasskey credentials(userid, strlen(userid), |
93 // This will mean we don't mount over existing mounts, | 124 chromeos::Blob(key, key + strlen(key))); |
94 // but at present, we reboot on user change so it is ok. | 125 |
95 // Later, this can be more intelligent. | 126 if(mount_->IsCryptohomeMounted()) { |
96 if (IsMounted(OUT_done, error) && *OUT_done) { | 127 if(mount_->IsCryptohomeMountedForUser(credentials)) { |
97 *OUT_done = FALSE; | 128 LOG(INFO) << "Cryptohome already mounted for this user"; |
98 return TRUE; | 129 *OUT_done = TRUE; |
| 130 return TRUE; |
| 131 } else { |
| 132 if(!mount_->UnmountCryptohome()) { |
| 133 LOG(ERROR) << "Could not unmount cryptohome from previous user"; |
| 134 *OUT_done = FALSE; |
| 135 return TRUE; |
| 136 } |
| 137 } |
99 } | 138 } |
100 // Note, by doing this we allow any chronos caller to | 139 |
101 // send a variable for use in the scripts. Bad idea. | 140 // TODO(fes): Iterate keys if we change how cryptohome keeps track of key |
102 // Thankfully, this will go away with the scripts. | 141 // indexes. Right now, 0 is always the current, and 0+n should only be used |
103 setenv("CHROMEOS_USER", userid, 1); | 142 // temporarily during password migration. |
104 FILE *mount = popen(mount_command(), "w"); | 143 Mount::MountError mount_error = Mount::MOUNT_ERROR_NONE; |
105 if (!mount) { | 144 *OUT_done = mount_->MountCryptohome(credentials, 0, &mount_error); |
106 // TODO(wad) *error = | 145 if(!(*OUT_done) && (mount_error == Mount::MOUNT_ERROR_KEY_FAILURE)) { |
107 return FALSE; | 146 // If there is a key failure, create cryptohome from scratch. |
108 } | 147 // TODO(fes): remove this when Chrome is no longer expecting this behavior. |
109 fprintf(mount, "%s", key); | 148 if(mount_->RemoveCryptohome(credentials)) { |
110 int status = pclose(mount); | 149 *OUT_done = mount_->MountCryptohome(credentials, 0, &mount_error); |
111 if (status != 0) { | 150 } |
112 *OUT_done = FALSE; | |
113 } else { | |
114 *OUT_done = TRUE; | |
115 } | 151 } |
116 return TRUE; | 152 return TRUE; |
117 } | 153 } |
118 | 154 |
119 gboolean Service::Unmount(gboolean *OUT_done, GError **error) { | 155 gboolean Service::Unmount(gboolean *OUT_done, GError **error) { |
120 // Check for a mount first. | 156 if(mount_->IsCryptohomeMounted()) { |
121 if (IsMounted(OUT_done, error) && !*OUT_done) { | 157 *OUT_done = mount_->UnmountCryptohome(); |
122 *OUT_done = TRUE; // unmounting nothing works fine. | 158 } else { |
123 return TRUE; | 159 *OUT_done = true; |
124 } | 160 } |
125 | |
126 int status = system(unmount_command()); | |
127 *OUT_done = !status; | |
128 return TRUE; | 161 return TRUE; |
129 } | 162 } |
130 | 163 |
131 } // namespace cryptohome | 164 } // namespace cryptohome |
OLD | NEW |