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

Side by Side Diff: cryptohome.cc

Issue 2645008: Update on feedback, update dbus API, add unit tests. TEST=manual,unit,BVT BUG=3628 323 (Closed) Base URL: ssh://git@chromiumos-git/cryptohome.git
Patch Set: Address second round of feedback. Created 10 years, 6 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 unified diff | Download patch
« no previous file with comments | « crypto_unittest.cc ('k') | cryptohome.xml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 // 4 //
5 // Cryptohome client that uses the dbus client interface 5 // Cryptohome client that uses the dbus client interface
6 6
7 #include <openssl/err.h>
8 #include <openssl/evp.h>
9 #include <openssl/rand.h>
10 #include <openssl/sha.h>
11 #include <termios.h>
12 #include <unistd.h>
13
7 #include <base/basictypes.h> 14 #include <base/basictypes.h>
8 #include <base/command_line.h> 15 #include <base/command_line.h>
9 #include <base/logging.h> 16 #include <base/logging.h>
10 #include <base/string_util.h> 17 #include <base/string_util.h>
11 #include <chromeos/dbus/dbus.h> 18 #include <chromeos/dbus/dbus.h>
12 #include <chromeos/dbus/service_constants.h> 19 #include <chromeos/dbus/service_constants.h>
13 #include <chromeos/utility.h> 20 #include <chromeos/utility.h>
21 #include <iostream>
14 22
15 #include <iostream> 23 #include "bindings/client.h"
16 #include <openssl/err.h> 24 #include "crypto.h"
17 #include <openssl/evp.h> 25 #include "secure_blob.h"
18 #include <openssl/rand.h> 26 #include "username_passkey.h"
19 #include <openssl/sha.h>
20 #include <termios.h>
21 #include <unistd.h>
22 27
23 #include "cryptohome/username_passkey.h"
24 #include "cryptohome/bindings/client.h"
25 28
26 namespace switches { 29 namespace switches {
27 static const char kActionSwitch[] = "action"; 30 static const char kActionSwitch[] = "action";
28 static const char *kActions[] = { 31 static const char *kActions[] = {
29 "mount", 32 "mount",
33 "mount_guest",
30 "unmount", 34 "unmount",
31 "is_mounted", 35 "is_mounted",
32 "test_auth", 36 "test_auth",
33 "migrate_key", 37 "migrate_key",
34 "remove", 38 "remove",
39 "obfuscate_user",
35 NULL }; 40 NULL };
36 enum ActionEnum { 41 enum ActionEnum {
37 ACTION_MOUNT, 42 ACTION_MOUNT,
43 ACTION_MOUNT_GUEST,
38 ACTION_UNMOUNT, 44 ACTION_UNMOUNT,
39 ACTION_MOUNTED, 45 ACTION_MOUNTED,
40 ACTION_TEST_AUTH, 46 ACTION_TEST_AUTH,
41 ACTION_MIGRATE_KEY, 47 ACTION_MIGRATE_KEY,
42 ACTION_REMOVE }; 48 ACTION_REMOVE,
49 ACTION_OBFUSCATE_USER };
43 static const char kUserSwitch[] = "user"; 50 static const char kUserSwitch[] = "user";
44 static const char kPasswordSwitch[] = "password"; 51 static const char kPasswordSwitch[] = "password";
45 static const char kOldPasswordSwitch[] = "old_password"; 52 static const char kOldPasswordSwitch[] = "old_password";
46 } // namespace switches 53 } // namespace switches
47 54
48 chromeos::Blob GetSystemSalt(const chromeos::dbus::Proxy& proxy) { 55 chromeos::Blob GetSystemSalt(const chromeos::dbus::Proxy& proxy) {
49 chromeos::glib::ScopedError error; 56 chromeos::glib::ScopedError error;
50 GArray* salt; 57 GArray* salt;
51 GError **errptr = &chromeos::Resetter(&error).lvalue(); 58 GError **errptr = &chromeos::Resetter(&error).lvalue();
52 if (!org_chromium_CryptohomeInterface_get_system_salt(proxy.gproxy(), 59 if (!org_chromium_CryptohomeInterface_get_system_salt(proxy.gproxy(),
(...skipping 17 matching lines...) Expand all
70 bool GetUsername(const CommandLine* cl, std::string* user_out) { 77 bool GetUsername(const CommandLine* cl, std::string* user_out) {
71 *user_out = cl->GetSwitchValueASCII(switches::kUserSwitch); 78 *user_out = cl->GetSwitchValueASCII(switches::kUserSwitch);
72 79
73 if(user_out->length() == 0) { 80 if(user_out->length() == 0) {
74 LOG(ERROR) << "No user specified (--user=<user>)"; 81 LOG(ERROR) << "No user specified (--user=<user>)";
75 return false; 82 return false;
76 } 83 }
77 return true; 84 return true;
78 } 85 }
79 86
80 bool GetUsernamePassword(const chromeos::dbus::Proxy& proxy, 87 bool GetPassword(const chromeos::dbus::Proxy& proxy,
81 const CommandLine* cl, 88 const CommandLine* cl,
82 std::string* user_out, 89 const std::string& cl_switch,
83 std::string* password_out, 90 const std::string& prompt,
84 std::string* old_password_out = NULL) { 91 std::string* password_out) {
85 if(!GetUsername(cl, user_out)) { 92 std::string password = cl->GetSwitchValueASCII(cl_switch);
86 return false;
87 }
88 93
89 std::string password = cl->GetSwitchValueASCII(switches::kPasswordSwitch);
90 std::string old_password = cl->GetSwitchValueASCII(
91 switches::kOldPasswordSwitch);
92
93 if(old_password_out != NULL && old_password.length() == 0) {
94 struct termios original_attr;
95 struct termios new_attr;
96 tcgetattr(0, &original_attr);
97 memcpy(&new_attr, &original_attr, sizeof(new_attr));
98 new_attr.c_lflag &= ~(ECHO);
99 tcsetattr(0, TCSANOW, &new_attr);
100 std::cout << "Enter old password for <" << (*user_out) << ">: ";
101 std::cin >> old_password;
102 std::cout << std::endl;
103 tcsetattr(0, TCSANOW, &original_attr);
104 }
105 if(password.length() == 0) { 94 if(password.length() == 0) {
106 struct termios original_attr; 95 struct termios original_attr;
107 struct termios new_attr; 96 struct termios new_attr;
108 tcgetattr(0, &original_attr); 97 tcgetattr(0, &original_attr);
109 memcpy(&new_attr, &original_attr, sizeof(new_attr)); 98 memcpy(&new_attr, &original_attr, sizeof(new_attr));
110 new_attr.c_lflag &= ~(ECHO); 99 new_attr.c_lflag &= ~(ECHO);
111 tcsetattr(0, TCSANOW, &new_attr); 100 tcsetattr(0, TCSANOW, &new_attr);
112 std::cout << "Enter password for <" << (*user_out) << ">: "; 101 std::cout << prompt << ": ";
113 std::cin >> password; 102 std::cin >> password;
114 std::cout << std::endl
115 << "Re-enter password for <" << (*user_out) << ">: ";
116 std::string verification;
117 std::cin >> verification;
118 std::cout << std::endl; 103 std::cout << std::endl;
119 tcsetattr(0, TCSANOW, &original_attr); 104 tcsetattr(0, TCSANOW, &original_attr);
120 if(verification != password) {
121 LOG(ERROR) << "Passwords do not match.";
122 return false;
123 }
124 } 105 }
125 106
126 std::string trimmed_password; 107 std::string trimmed_password;
127 TrimString(password, "\r\n", &trimmed_password); 108 TrimString(password, "\r\n", &trimmed_password);
128 cryptohome::UsernamePasskey up( 109 cryptohome::SecureBlob passkey;
129 cryptohome::UsernamePasskey::FromUsernamePassword((*user_out).c_str(), 110 cryptohome::Crypto::PasswordToPasskey(trimmed_password.c_str(),
130 trimmed_password.c_str(), GetSystemSalt(proxy))); 111 GetSystemSalt(proxy), &passkey);
131 cryptohome::SecureBlob passkey = up.GetPasskey(); 112 *password_out = std::string(static_cast<char*>(passkey.data()),
132 *password_out = std::string(reinterpret_cast<char*>(&passkey[0]),
133 passkey.size()); 113 passkey.size());
134 if(old_password_out != NULL) {
135 TrimString(old_password, "\r\n", &trimmed_password);
136 cryptohome::UsernamePasskey old_up(
137 cryptohome::UsernamePasskey::FromUsernamePassword((*user_out).c_str(),
138 trimmed_password.c_str(), GetSystemSalt(proxy)));
139 passkey = old_up.GetPasskey();
140 *old_password_out = std::string(reinterpret_cast<char*>(&passkey[0]),
141 passkey.size());
142 }
143 114
144 return true; 115 return true;
145 } 116 }
146 117
147 bool AskHardQuestion(const std::string& user) {
148 std::cout << "!!! The password you entered did not unwrap the user's"
149 << std::endl
150 << "!!! vault key. If you proceed, the user's cryptohome"
151 << std::endl
152 << "!!! will be DELETED and RECREATED."
153 << std::endl
154 << "!!!"
155 << std::endl
156 << "!!! Re-enter the username at the prompt to create a new"
157 << std::endl
158 << "!!! cryptohome for the user."
159 << std::endl
160 << "Enter the username <" << user << ">: ";
161 std::string verification;
162 std::cin >> verification;
163 if(user != verification) {
164 LOG(ERROR) << "Usernames do not match.";
165 return false;
166 }
167 return true;
168 }
169
170 bool ConfirmRemove(const std::string& user) { 118 bool ConfirmRemove(const std::string& user) {
171 std::cout << "!!! Are you sure you want to remove the user's cryptohome?" 119 std::cout << "!!! Are you sure you want to remove the user's cryptohome?"
172 << std::endl 120 << std::endl
173 << "!!!" 121 << "!!!"
174 << std::endl 122 << std::endl
175 << "!!! Re-enter the username at the prompt to remove the" 123 << "!!! Re-enter the username at the prompt to remove the"
176 << std::endl 124 << std::endl
177 << "!!! cryptohome for the user." 125 << "!!! cryptohome for the user."
178 << std::endl 126 << std::endl
179 << "Enter the username <" << user << ">: "; 127 << "Enter the username <" << user << ">: ";
(...skipping 19 matching lines...) Expand all
199 chromeos::dbus::BusConnection bus = chromeos::dbus::GetSystemBusConnection(); 147 chromeos::dbus::BusConnection bus = chromeos::dbus::GetSystemBusConnection();
200 chromeos::dbus::Proxy proxy(bus, 148 chromeos::dbus::Proxy proxy(bus,
201 cryptohome::kCryptohomeServiceName, 149 cryptohome::kCryptohomeServiceName,
202 cryptohome::kCryptohomeServicePath, 150 cryptohome::kCryptohomeServicePath,
203 cryptohome::kCryptohomeInterface); 151 cryptohome::kCryptohomeInterface);
204 DCHECK(proxy.gproxy()) << "Failed to acquire proxy"; 152 DCHECK(proxy.gproxy()) << "Failed to acquire proxy";
205 153
206 if (!strcmp(switches::kActions[switches::ACTION_MOUNT], action.c_str())) { 154 if (!strcmp(switches::kActions[switches::ACTION_MOUNT], action.c_str())) {
207 std::string user, password; 155 std::string user, password;
208 156
209 if(!GetUsernamePassword(proxy, cl, &user, &password)) { 157 if (!GetUsername(cl, &user)) {
158 LOG(ERROR) << "No username specified";
210 return 1; 159 return 1;
211 } 160 }
212 161
162 GetPassword(proxy, cl, switches::kPasswordSwitch,
163 StringPrintf("Enter the password for <%s>", user.c_str()),
164 &password);
165
213 gboolean done = false; 166 gboolean done = false;
167 gint mount_error = 0;
214 chromeos::glib::ScopedError error; 168 chromeos::glib::ScopedError error;
215 GError **errptr = &chromeos::Resetter(&error).lvalue(); 169 GError **errptr = &chromeos::Resetter(&error).lvalue();
216 org_chromium_CryptohomeInterface_check_key(proxy.gproxy(),
217 user.c_str(),
218 password.c_str(),
219 &done,
220 errptr);
221 if(!done) {
222 // TODO(fes): Remove when Mount no longer automatically deletes cryptohome
223 // on passkey failure.
224 if(!AskHardQuestion(user)) {
225 return 1;
226 }
227 }
228
229 errptr = &chromeos::Resetter(&error).lvalue();
230 if (!org_chromium_CryptohomeInterface_mount(proxy.gproxy(), 170 if (!org_chromium_CryptohomeInterface_mount(proxy.gproxy(),
231 user.c_str(), 171 user.c_str(),
232 password.c_str(), 172 password.c_str(),
173 &mount_error,
233 &done, 174 &done,
234 errptr)) { 175 errptr)) {
235 LOG(ERROR) << "Mount call failed: " << error->message; 176 LOG(ERROR) << "Mount call failed: " << error->message
177 << ", with reason code: " << mount_error;
236 } 178 }
237 LOG_IF(ERROR, !done) << "Mount did not complete?"; 179 LOG_IF(ERROR, !done) << "Mount did not complete?";
238 LOG_IF(INFO, done) << "Call completed"; 180 LOG_IF(INFO, done) << "Call completed";
181 } else if (!strcmp(switches::kActions[switches::ACTION_MOUNT_GUEST],
182 action.c_str())) {
183 gboolean done = false;
184 gint mount_error = 0;
185 chromeos::glib::ScopedError error;
186 GError **errptr = &chromeos::Resetter(&error).lvalue();
187 if (!org_chromium_CryptohomeInterface_mount_guest(proxy.gproxy(),
188 &mount_error,
189 &done,
190 errptr)) {
191 LOG(ERROR) << "MountGuest call failed: " << error->message
192 << ", with reason code: " << mount_error;
193 }
194 LOG_IF(ERROR, !done) << "MountGuest did not complete?";
195 LOG_IF(INFO, done) << "Call completed";
239 } else if (!strcmp(switches::kActions[switches::ACTION_TEST_AUTH], 196 } else if (!strcmp(switches::kActions[switches::ACTION_TEST_AUTH],
240 action.c_str())) { 197 action.c_str())) {
241 std::string user, password; 198 std::string user, password;
242 199
243 if(!GetUsernamePassword(proxy, cl, &user, &password)) { 200 if (!GetUsername(cl, &user)) {
201 LOG(ERROR) << "No username specified";
244 return 1; 202 return 1;
245 } 203 }
246 204
205 GetPassword(proxy, cl, switches::kPasswordSwitch,
206 StringPrintf("Enter the password for <%s>", user.c_str()),
207 &password);
208
247 gboolean done = false; 209 gboolean done = false;
248 chromeos::glib::ScopedError error; 210 chromeos::glib::ScopedError error;
249 GError **errptr = &chromeos::Resetter(&error).lvalue(); 211 GError **errptr = &chromeos::Resetter(&error).lvalue();
250 if (!org_chromium_CryptohomeInterface_check_key(proxy.gproxy(), 212 if (!org_chromium_CryptohomeInterface_check_key(proxy.gproxy(),
251 user.c_str(), 213 user.c_str(),
252 password.c_str(), 214 password.c_str(),
253 &done, 215 &done,
254 errptr)) { 216 errptr)) {
255 LOG(ERROR) << "CheckKey call failed: " << error->message; 217 LOG(ERROR) << "CheckKey call failed: " << error->message;
256 } 218 }
257 LOG_IF(ERROR, !done) << "CheckKey did not complete?"; 219 LOG_IF(ERROR, !done) << "CheckKey did not complete?";
258 LOG_IF(INFO, done) << "Call completed"; 220 LOG_IF(INFO, done) << "Call completed";
259 } else if (!strcmp(switches::kActions[switches::ACTION_MIGRATE_KEY], 221 } else if (!strcmp(switches::kActions[switches::ACTION_MIGRATE_KEY],
260 action.c_str())) { 222 action.c_str())) {
261 std::string user, password, old_password; 223 std::string user, password, old_password;
262 224
263 if(!GetUsernamePassword(proxy, cl, &user, &password, &old_password)) { 225 if (!GetUsername(cl, &user)) {
226 LOG(ERROR) << "No username specified";
264 return 1; 227 return 1;
265 } 228 }
266 229
230 GetPassword(proxy, cl, switches::kPasswordSwitch,
231 StringPrintf("Enter the password for <%s>", user.c_str()),
232 &password);
233 GetPassword(proxy, cl, switches::kOldPasswordSwitch,
234 StringPrintf("Enter the old password for <%s>", user.c_str()),
235 &old_password);
236
267 gboolean done = false; 237 gboolean done = false;
268 chromeos::glib::ScopedError error; 238 chromeos::glib::ScopedError error;
269 GError **errptr = &chromeos::Resetter(&error).lvalue(); 239 GError **errptr = &chromeos::Resetter(&error).lvalue();
270 if (!org_chromium_CryptohomeInterface_migrate_key(proxy.gproxy(), 240 if (!org_chromium_CryptohomeInterface_migrate_key(proxy.gproxy(),
271 user.c_str(), 241 user.c_str(),
272 old_password.c_str(), 242 old_password.c_str(),
273 password.c_str(), 243 password.c_str(),
274 &done, 244 &done,
275 errptr)) { 245 errptr)) {
276 LOG(ERROR) << "MigrateKey call failed: " << error->message; 246 LOG(ERROR) << "MigrateKey call failed: " << error->message;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 chromeos::glib::ScopedError error; 287 chromeos::glib::ScopedError error;
318 GError **errptr = &chromeos::Resetter(&error).lvalue(); 288 GError **errptr = &chromeos::Resetter(&error).lvalue();
319 gboolean done = false; 289 gboolean done = false;
320 if (!org_chromium_CryptohomeInterface_is_mounted(proxy.gproxy(), 290 if (!org_chromium_CryptohomeInterface_is_mounted(proxy.gproxy(),
321 &done, 291 &done,
322 errptr)) { 292 errptr)) {
323 LOG(ERROR) << "IsMounted call failed: " << error->message; 293 LOG(ERROR) << "IsMounted call failed: " << error->message;
324 } 294 }
325 std::cout << done << std::endl; 295 std::cout << done << std::endl;
326 296
297 } else if (!strcmp(switches::kActions[switches::ACTION_OBFUSCATE_USER],
298 action.c_str())) {
299 std::string user;
300
301 if(!GetUsername(cl, &user)) {
302 return 1;
303 }
304
305 cryptohome::UsernamePasskey up(user.c_str(), cryptohome::SecureBlob());
306 LOG(INFO) << up.GetObfuscatedUsername(GetSystemSalt(proxy));
327 } else { 307 } else {
328 LOG(ERROR) << "Unknown action or no action given. Available actions: "; 308 LOG(ERROR) << "Unknown action or no action given. Available actions: ";
329 for(int i = 0; /* loop forever */; i++) { 309 for(int i = 0; /* loop forever */; i++) {
330 if(!switches::kActions[i]) { 310 if(!switches::kActions[i]) {
331 break; 311 break;
332 } 312 }
333 LOG(ERROR) << " --action=" << switches::kActions[i]; 313 LOG(ERROR) << " --action=" << switches::kActions[i];
334 } 314 }
335 } 315 }
336 return 0; 316 return 0;
337 } 317 }
OLDNEW
« no previous file with comments | « crypto_unittest.cc ('k') | cryptohome.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698