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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4 //
5 // Cryptohome client that uses the dbus client interface
6
7 #include <base/basictypes.h>
8 #include <base/command_line.h>
9 #include <base/logging.h>
10 #include <base/string_util.h>
11 #include <chromeos/dbus/dbus.h>
12 #include <chromeos/dbus/service_constants.h>
13 #include <chromeos/utility.h>
14
15 #include <iostream>
16 #include <openssl/err.h>
17 #include <openssl/evp.h>
18 #include <openssl/rand.h>
19 #include <openssl/sha.h>
20 #include <termios.h>
21 #include <unistd.h>
22
23 #include "cryptohome/username_passkey.h"
24 #include "cryptohome/bindings/client.h"
25
26 namespace switches {
27 static const char kActionSwitch[] = "action";
28 static const char *kActions[] = {
29 "mount",
30 "unmount",
31 "is_mounted",
32 "test_auth",
33 "migrate_key",
34 "remove",
35 NULL };
36 enum ActionEnum {
37 ACTION_MOUNT,
38 ACTION_UNMOUNT,
39 ACTION_MOUNTED,
40 ACTION_TEST_AUTH,
41 ACTION_MIGRATE_KEY,
42 ACTION_REMOVE };
43 static const char kUserSwitch[] = "user";
44 static const char kPasswordSwitch[] = "password";
45 static const char kOldPasswordSwitch[] = "old_password";
46 } // namespace switches
47
48 chromeos::Blob GetSystemSalt(const chromeos::dbus::Proxy& proxy) {
49 chromeos::glib::ScopedError error;
50 GArray* salt;
51 GError **errptr = &chromeos::Resetter(&error).lvalue();
52 if (!org_chromium_CryptohomeInterface_get_system_salt(proxy.gproxy(),
53 &salt,
54 errptr)) {
55 LOG(ERROR) << "GetSystemSalt failed: " << error->message;
56 return chromeos::Blob();
57 }
58
59 chromeos::Blob system_salt;
60 system_salt.resize(salt->len);
61 if(system_salt.size() == salt->len) {
62 memcpy(&system_salt[0], static_cast<const void*>(salt->data), salt->len);
63 } else {
64 system_salt.clear();
65 }
66 g_array_free(salt, false);
67 return system_salt;
68 }
69
70 bool GetUsername(const CommandLine* cl, std::string* user_out) {
71 *user_out = cl->GetSwitchValueASCII(switches::kUserSwitch);
72
73 if(user_out->length() == 0) {
74 LOG(ERROR) << "No user specified (--user=<user>)";
75 return false;
76 }
77 return true;
78 }
79
80 bool GetUsernamePassword(const chromeos::dbus::Proxy& proxy,
81 const CommandLine* cl,
82 std::string* user_out,
83 std::string* password_out,
84 std::string* old_password_out = NULL) {
85 if(!GetUsername(cl, user_out)) {
86 return false;
87 }
88
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) {
106 struct termios original_attr;
107 struct termios new_attr;
108 tcgetattr(0, &original_attr);
109 memcpy(&new_attr, &original_attr, sizeof(new_attr));
110 new_attr.c_lflag &= ~(ECHO);
111 tcsetattr(0, TCSANOW, &new_attr);
112 std::cout << "Enter password for <" << (*user_out) << ">: ";
113 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;
119 tcsetattr(0, TCSANOW, &original_attr);
120 if(verification != password) {
121 LOG(ERROR) << "Passwords do not match.";
122 return false;
123 }
124 }
125
126 std::string trimmed_password;
127 TrimString(password, "\r\n", &trimmed_password);
128 cryptohome::UsernamePasskey up(
129 cryptohome::UsernamePasskey::FromUsernamePassword((*user_out).c_str(),
130 trimmed_password.c_str(), GetSystemSalt(proxy)));
131 cryptohome::SecureBlob passkey = up.GetPasskey();
132 *password_out = std::string(reinterpret_cast<char*>(&passkey[0]),
133 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
144 return true;
145 }
146
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) {
171 std::cout << "!!! Are you sure you want to remove the user's cryptohome?"
172 << std::endl
173 << "!!!"
174 << std::endl
175 << "!!! Re-enter the username at the prompt to remove the"
176 << std::endl
177 << "!!! cryptohome for the user."
178 << std::endl
179 << "Enter the username <" << user << ">: ";
180 std::string verification;
181 std::cin >> verification;
182 if(user != verification) {
183 LOG(ERROR) << "Usernames do not match.";
184 return false;
185 }
186 return true;
187 }
188
189 int main(int argc, char **argv) {
190 CommandLine::Init(argc, argv);
191 logging::InitLogging(NULL,
192 logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
193 logging::DONT_LOCK_LOG_FILE,
194 logging::APPEND_TO_OLD_LOG_FILE);
195
196 CommandLine *cl = CommandLine::ForCurrentProcess();
197 std::string action = cl->GetSwitchValueASCII(switches::kActionSwitch);
198 g_type_init();
199 chromeos::dbus::BusConnection bus = chromeos::dbus::GetSystemBusConnection();
200 chromeos::dbus::Proxy proxy(bus,
201 cryptohome::kCryptohomeServiceName,
202 cryptohome::kCryptohomeServicePath,
203 cryptohome::kCryptohomeInterface);
204 DCHECK(proxy.gproxy()) << "Failed to acquire proxy";
205
206 if (!strcmp(switches::kActions[switches::ACTION_MOUNT], action.c_str())) {
207 std::string user, password;
208
209 if(!GetUsernamePassword(proxy, cl, &user, &password)) {
210 return 1;
211 }
212
213 gboolean done = false;
214 chromeos::glib::ScopedError error;
215 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(),
231 user.c_str(),
232 password.c_str(),
233 &done,
234 errptr)) {
235 LOG(ERROR) << "Mount call failed: " << error->message;
236 }
237 LOG_IF(ERROR, !done) << "Mount did not complete?";
238 LOG_IF(INFO, done) << "Call completed";
239 } else if (!strcmp(switches::kActions[switches::ACTION_TEST_AUTH],
240 action.c_str())) {
241 std::string user, password;
242
243 if(!GetUsernamePassword(proxy, cl, &user, &password)) {
244 return 1;
245 }
246
247 gboolean done = false;
248 chromeos::glib::ScopedError error;
249 GError **errptr = &chromeos::Resetter(&error).lvalue();
250 if (!org_chromium_CryptohomeInterface_check_key(proxy.gproxy(),
251 user.c_str(),
252 password.c_str(),
253 &done,
254 errptr)) {
255 LOG(ERROR) << "CheckKey call failed: " << error->message;
256 }
257 LOG_IF(ERROR, !done) << "CheckKey did not complete?";
258 LOG_IF(INFO, done) << "Call completed";
259 } else if (!strcmp(switches::kActions[switches::ACTION_MIGRATE_KEY],
260 action.c_str())) {
261 std::string user, password, old_password;
262
263 if(!GetUsernamePassword(proxy, cl, &user, &password, &old_password)) {
264 return 1;
265 }
266
267 gboolean done = false;
268 chromeos::glib::ScopedError error;
269 GError **errptr = &chromeos::Resetter(&error).lvalue();
270 if (!org_chromium_CryptohomeInterface_migrate_key(proxy.gproxy(),
271 user.c_str(),
272 old_password.c_str(),
273 password.c_str(),
274 &done,
275 errptr)) {
276 LOG(ERROR) << "MigrateKey call failed: " << error->message;
277 }
278 LOG_IF(ERROR, !done) << "MigrateKey did not complete?";
279 LOG_IF(INFO, done) << "Call completed";
280 } else if (!strcmp(switches::kActions[switches::ACTION_REMOVE],
281 action.c_str())) {
282 std::string user;
283
284 if(!GetUsername(cl, &user)) {
285 return 1;
286 }
287
288 if(!ConfirmRemove(user)) {
289 return 1;
290 }
291
292 gboolean done = false;
293 chromeos::glib::ScopedError error;
294 GError **errptr = &chromeos::Resetter(&error).lvalue();
295 if (!org_chromium_CryptohomeInterface_remove(proxy.gproxy(),
296 user.c_str(),
297 &done,
298 errptr)) {
299 LOG(ERROR) << "Remove call failed: " << error->message;
300 }
301 LOG_IF(ERROR, !done) << "Remove did not complete?";
302 LOG_IF(INFO, done) << "Call completed";
303 } else if (!strcmp(switches::kActions[switches::ACTION_UNMOUNT],
304 action.c_str())) {
305 chromeos::glib::ScopedError error;
306 GError **errptr = &chromeos::Resetter(&error).lvalue();
307 gboolean done = false;
308 if (!org_chromium_CryptohomeInterface_unmount(proxy.gproxy(),
309 &done,
310 errptr)) {
311 LOG(ERROR) << "Unmount call failed: " << error->message;
312 }
313 LOG_IF(ERROR, !done) << "Unmount did not complete?";
314 LOG_IF(INFO, done) << "Call completed";
315 } else if (!strcmp(switches::kActions[switches::ACTION_MOUNTED],
316 action.c_str())) {
317 chromeos::glib::ScopedError error;
318 GError **errptr = &chromeos::Resetter(&error).lvalue();
319 gboolean done = false;
320 if (!org_chromium_CryptohomeInterface_is_mounted(proxy.gproxy(),
321 &done,
322 errptr)) {
323 LOG(ERROR) << "IsMounted call failed: " << error->message;
324 }
325 std::cout << done << std::endl;
326
327 } else {
328 LOG(ERROR) << "Unknown action or no action given. Available actions: ";
329 for(int i = 0; /* loop forever */; i++) {
330 if(!switches::kActions[i]) {
331 break;
332 }
333 LOG(ERROR) << " --action=" << switches::kActions[i];
334 }
335 }
336 return 0;
337 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698