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

Side by Side Diff: session_manager_service.cc

Issue 6469072: [login_manager] Use keygen helper to generate owner key (Closed) Base URL: http://git.chromium.org/git/login_manager.git@master
Patch Set: Add a few constants Created 9 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « session_manager_service.h ('k') | session_manager_unittest.cc » ('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-2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2009-2010 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 #include "login_manager/session_manager_service.h" 5 #include "login_manager/session_manager_service.h"
6 6
7 #include <dbus/dbus-glib-lowlevel.h> 7 #include <dbus/dbus-glib-lowlevel.h>
8 #include <errno.h> 8 #include <errno.h>
9 #include <glib.h> 9 #include <glib.h>
10 #include <grp.h> 10 #include <grp.h>
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 ".@1234567890-+_"; 123 ".@1234567890-+_";
124 // static 124 // static
125 const char SessionManagerService::kIncognitoUser[] = ""; 125 const char SessionManagerService::kIncognitoUser[] = "";
126 // static 126 // static
127 const char SessionManagerService::kDeviceOwnerPref[] = "cros.device.owner"; 127 const char SessionManagerService::kDeviceOwnerPref[] = "cros.device.owner";
128 // static 128 // static
129 const char SessionManagerService::kTestingChannelFlag[] = 129 const char SessionManagerService::kTestingChannelFlag[] =
130 "--testing-channel=NamedTestingInterface:"; 130 "--testing-channel=NamedTestingInterface:";
131 // static 131 // static
132 const char SessionManagerService::kIOThreadName[] = "ThreadForIO"; 132 const char SessionManagerService::kIOThreadName[] = "ThreadForIO";
133 // static
134 const char SessionManagerService::kKeygenExecutable[] = "/sbin/keygen";
135 // static
136 const char SessionManagerService::kTemporaryKeyFilename[] = "key.pub";
133 137
134 namespace { 138 namespace {
135 139
136 // Time we wait for child job to die (in seconds). 140 // Time we wait for child job to die (in seconds).
137 const int kKillTimeout = 3; 141 const int kKillTimeout = 3;
138 142
139 const int kMaxArgumentsSize = 512; 143 const int kMaxArgumentsSize = 512;
140 144
141 } // namespace 145 } // namespace
142 146
143 SessionManagerService::SessionManagerService( 147 SessionManagerService::SessionManagerService(
144 std::vector<ChildJobInterface*> child_jobs) 148 std::vector<ChildJobInterface*> child_jobs)
145 : child_jobs_(child_jobs.begin(), child_jobs.end()), 149 : child_jobs_(child_jobs.begin(), child_jobs.end()),
146 child_pids_(child_jobs.size(), -1), 150 child_pids_(child_jobs.size(), -1),
147 exit_on_child_done_(false), 151 exit_on_child_done_(false),
152 keygen_job_(NULL),
148 session_manager_(NULL), 153 session_manager_(NULL),
149 main_loop_(g_main_loop_new(NULL, FALSE)), 154 main_loop_(g_main_loop_new(NULL, FALSE)),
150 system_(new SystemUtils), 155 system_(new SystemUtils),
151 nss_(NssUtil::Create()), 156 nss_(NssUtil::Create()),
152 key_(new OwnerKey(nss_->GetOwnerKeyFilePath())), 157 key_(new OwnerKey(nss_->GetOwnerKeyFilePath())),
153 store_(new PrefStore(FilePath(PrefStore::kDefaultPath))), 158 store_(new PrefStore(FilePath(PrefStore::kDefaultPath))),
154 upstart_signal_emitter_(new UpstartSignalEmitter), 159 upstart_signal_emitter_(new UpstartSignalEmitter),
155 session_started_(false), 160 session_started_(false),
156 io_thread_(kIOThreadName), 161 io_thread_(kIOThreadName),
157 dont_use_directly_(new MessageLoopForUI), 162 dont_use_directly_(new MessageLoopForUI),
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 StoreOwnerProperties(NULL); 477 StoreOwnerProperties(NULL);
473 // Now, the flip side...if we believe the current user to be the owner 478 // Now, the flip side...if we believe the current user to be the owner
474 // based on the cros.owner.device setting, and he DOESN'T have the private 479 // based on the cros.owner.device setting, and he DOESN'T have the private
475 // half of the public key, we must mitigate. 480 // half of the public key, we must mitigate.
476 if (CurrentUserIsOwner(error) && 481 if (CurrentUserIsOwner(error) &&
477 !CurrentUserHasOwnerKey(key_->public_key_der(), error)) { 482 !CurrentUserHasOwnerKey(key_->public_key_der(), error)) {
478 if (!(*OUT_done = mitigator_->Mitigate())) 483 if (!(*OUT_done = mitigator_->Mitigate()))
479 return FALSE; 484 return FALSE;
480 } 485 }
481 486
482 if (set_uid_) { 487 *OUT_done =
483 *OUT_done = 488 upstart_signal_emitter_->EmitSignal(
484 upstart_signal_emitter_->EmitSignal( 489 "start-user-session",
485 "start-user-session", 490 StringPrintf("CHROMEOS_USER=%s", current_user_.c_str()),
486 StringPrintf("CHROMEOS_USER=%s USER_ID=%d", 491 error);
487 current_user_.c_str(), uid_),
488 error);
489 } else {
490 *OUT_done =
491 upstart_signal_emitter_->EmitSignal(
492 "start-user-session",
493 StringPrintf("CHROMEOS_USER=%s", current_user_.c_str()),
494 error);
495 }
496 492
497 if (*OUT_done) { 493 if (*OUT_done) {
498 for (size_t i_child = 0; i_child < child_jobs_.size(); ++i_child) { 494 for (size_t i_child = 0; i_child < child_jobs_.size(); ++i_child) {
499 ChildJobInterface* child_job = child_jobs_[i_child]; 495 ChildJobInterface* child_job = child_jobs_[i_child];
500 child_job->StartSession(current_user_); 496 child_job->StartSession(current_user_);
501 } 497 }
502 session_started_ = true; 498 session_started_ = true;
503 DLOG(INFO) << "emitting D-Bus signal SessionStateChanged:started"; 499 DLOG(INFO) << "emitting D-Bus signal SessionStateChanged:started";
504 if (signals_[kSignalSessionStateChanged]) { 500 if (signals_[kSignalSessionStateChanged]) {
505 g_signal_emit(session_manager_, 501 g_signal_emit(session_manager_,
506 signals_[kSignalSessionStateChanged], 502 signals_[kSignalSessionStateChanged],
507 0, "started", current_user_.c_str()); 503 0, "started", current_user_.c_str());
508 } 504 }
505 if (key_->HaveCheckedDisk() && !key_->IsPopulated())
506 StartKeyGeneration();
509 } 507 }
510 508
511 return *OUT_done; 509 return *OUT_done;
512 } 510 }
513 511
512 void SessionManagerService::HandleKeygenExit(GPid pid,
513 gint status,
514 gpointer data) {
515 SessionManagerService* manager = static_cast<SessionManagerService*>(data);
516 int i_child = manager->FindChildByPid(pid);
517 manager->child_pids_[i_child] = -1;
518 delete *(manager->child_jobs_.erase(manager->child_jobs_.begin() + i_child));
519
520 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
521 std::string key;
522 file_util::ReadFileToString(
523 FilePath(file_util::GetHomeDir().AppendASCII(kTemporaryKeyFilename)),
524 &key);
525 manager->ValidateAndStoreOwnerKey(key);
526 } else {
527 if (WIFSIGNALED(status))
528 LOG(ERROR) << "keygen exited on signal " << WTERMSIG(status);
529 else
530 LOG(ERROR) << "keygen exited with exit code " << WEXITSTATUS(status);
531 }
532 }
533
534 void SessionManagerService::ValidateAndStoreOwnerKey(const std::string& buf) {
535 std::vector<uint8> pub_key;
536 NssUtil::KeyFromBuffer(buf, &pub_key);
537
538 if (!CurrentUserHasOwnerKey(pub_key, NULL)) {
539 SendSignal(chromium::kOwnerKeySetSignal, false);
540 return;
541 }
542
543 if (!key_->PopulateFromBuffer(pub_key)) {
544 SendSignal(chromium::kOwnerKeySetSignal, false);
545 return;
546 }
547 io_thread_.message_loop()->PostTask(
548 FROM_HERE, NewRunnableMethod(this, &SessionManagerService::PersistKey));
549 StoreOwnerProperties(NULL);
550 }
551
552 void SessionManagerService::StartKeyGeneration() {
553 if (!keygen_job_.get()) {
554 LOG(INFO) << "Creating keygen job";
555 std::vector<std::string> keygen_argv;
556 keygen_argv.push_back(kKeygenExecutable);
557 keygen_argv.push_back(
558 file_util::GetHomeDir().AppendASCII(kTemporaryKeyFilename).value());
Will Drewry 2011/02/23 03:30:16 I was going to suggest a random location, but sinc
559 keygen_job_.reset(new ChildJob(keygen_argv));
560 }
561
562 if (set_uid_)
563 keygen_job_->SetDesiredUid(uid_);
564 int pid = key_->StartGeneration(keygen_job_.get());
565 g_child_watch_add_full(G_PRIORITY_HIGH_IDLE,
566 pid,
567 HandleKeygenExit,
568 this,
569 NULL);
570 child_jobs_.push_back(keygen_job_.release());
571 child_pids_.push_back(pid);
572 }
573
514 gboolean SessionManagerService::StopSession(gchar* unique_identifier, 574 gboolean SessionManagerService::StopSession(gchar* unique_identifier,
515 gboolean* OUT_done, 575 gboolean* OUT_done,
516 GError** error) { 576 GError** error) {
517 // Most calls to StopSession() will log the reason for the call. 577 // Most calls to StopSession() will log the reason for the call.
518 // If you don't see a log message saying the reason for the call, it is 578 // If you don't see a log message saying the reason for the call, it is
519 // likely a DBUS message. See interface.cc for that call. 579 // likely a DBUS message. See interface.cc for that call.
520 LOG(INFO) << "SessionManagerService StopSession"; 580 LOG(INFO) << "SessionManagerService StopSession";
521 g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, 581 g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
522 ServiceShutdown, 582 ServiceShutdown,
523 this, 583 this,
524 NULL); 584 NULL);
525 // TODO(cmasone): re-enable these when we try to enable logout without exiting 585 // TODO(cmasone): re-enable these when we try to enable logout without exiting
526 // the session manager 586 // the session manager
527 // child_job_->StopSession(); 587 // child_job_->StopSession();
528 // session_started_ = false; 588 // session_started_ = false;
529 return *OUT_done = TRUE; 589 return *OUT_done = TRUE;
530 } 590 }
531 591
532 gboolean SessionManagerService::SetOwnerKey(GArray* public_key_der, 592 gboolean SessionManagerService::SetOwnerKey(GArray* public_key_der,
533 GError** error) { 593 GError** error) {
534 LOG(INFO) << "key size is " << public_key_der->len; 594 SetGError(error,
535 595 CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY,
536 if (!session_started_) { 596 "The session_manager now sets the Owner's public key.");
537 SetGError(error, 597 // Just to be safe, send back a nACK in addition to returning an error.
538 CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, 598 SendSignal(chromium::kOwnerKeySetSignal, false);
539 "Cannot set the owner's public key outside of a session."); 599 return FALSE;
540 return FALSE;
541 }
542
543 std::vector<uint8> pub_key;
544 NssUtil::KeyFromBuffer(public_key_der, &pub_key);
545
546 if (!CurrentUserHasOwnerKey(pub_key, error)) {
547 return FALSE; // error set by CurrentUserHasOwnerKey()
548 }
549
550 if (!key_->PopulateFromBuffer(pub_key)) {
551 SetGError(error,
552 CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY,
553 "Attempted to set invalid key as owner's public key.");
554 return FALSE;
555 }
556 io_thread_.message_loop()->PostTask(
557 FROM_HERE, NewRunnableMethod(this, &SessionManagerService::PersistKey));
558 return StoreOwnerProperties(error);
559 } 600 }
560 601
561 gboolean SessionManagerService::Unwhitelist(gchar* email_address, 602 gboolean SessionManagerService::Unwhitelist(gchar* email_address,
562 GArray* signature, 603 GArray* signature,
563 GError** error) { 604 GError** error) {
564 LOG(INFO) << "Unwhitelisting " << email_address; 605 LOG(INFO) << "Unwhitelisting " << email_address;
565 if (!key_->IsPopulated()) { 606 if (!key_->IsPopulated()) {
566 SetGError(error, 607 SetGError(error,
567 CHROMEOS_LOGIN_ERROR_NO_OWNER_KEY, 608 CHROMEOS_LOGIN_ERROR_NO_OWNER_KEY,
568 "Attempt to unwhitelist before owner's key is set."); 609 "Attempt to unwhitelist before owner's key is set.");
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 DLOG(INFO) << " Exited...somehow, without an exit code or a signal??"; 818 DLOG(INFO) << " Exited...somehow, without an exit code or a signal??";
778 } 819 }
779 820
780 // If the child _ever_ exits uncleanly, we want to start it up again. 821 // If the child _ever_ exits uncleanly, we want to start it up again.
781 SessionManagerService* manager = static_cast<SessionManagerService*>(data); 822 SessionManagerService* manager = static_cast<SessionManagerService*>(data);
782 823
783 // Do nothing if already shutting down. 824 // Do nothing if already shutting down.
784 if (manager->shutting_down_) 825 if (manager->shutting_down_)
785 return; 826 return;
786 827
787 int i_child = -1; 828 ChildJobInterface* child_job = NULL;
788 for (int i = 0; i < manager->child_pids_.size(); ++i) { 829 int i_child = manager->FindChildByPid(pid);
789 if (manager->child_pids_[i] == pid) { 830 if (i_child >= 0) {
790 i_child = i; 831 child_job = manager->child_jobs_[i_child];
791 manager->child_pids_[i] = -1; 832 manager->child_pids_[i_child] = -1;
792 break;
793 }
794 } 833 }
795 834
796 ChildJobInterface* child_job = i_child >= 0
797 ? manager->child_jobs_[i_child]
798 : NULL;
799
800 LOG(ERROR) << StringPrintf( 835 LOG(ERROR) << StringPrintf(
801 "Process %s(%d) exited.", 836 "Process %s(%d) exited.",
802 child_job ? child_job->GetName().c_str() : "", 837 child_job ? child_job->GetName().c_str() : "",
803 pid); 838 pid);
804 if (manager->screen_locked_) { 839 if (manager->screen_locked_) {
805 LOG(ERROR) << "Screen locked, shutting down", 840 LOG(ERROR) << "Screen locked, shutting down",
806 ServiceShutdown(data); 841 ServiceShutdown(data);
807 return; 842 return;
808 } 843 }
809 844
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
1021 if (email_string != kIncognitoUser && !ValidateEmail(email_string)) { 1056 if (email_string != kIncognitoUser && !ValidateEmail(email_string)) {
1022 SetGError(error, 1057 SetGError(error,
1023 CHROMEOS_LOGIN_ERROR_INVALID_EMAIL, 1058 CHROMEOS_LOGIN_ERROR_INVALID_EMAIL,
1024 "Provided email address is not valid. ASCII only."); 1059 "Provided email address is not valid. ASCII only.");
1025 return FALSE; 1060 return FALSE;
1026 } 1061 }
1027 current_user_ = StringToLowerASCII(email_string); 1062 current_user_ = StringToLowerASCII(email_string);
1028 return TRUE; 1063 return TRUE;
1029 } 1064 }
1030 1065
1066 int SessionManagerService::FindChildByPid(int pid) {
1067 for (int i = 0; i < child_pids_.size(); ++i) {
1068 if (child_pids_[i] == pid)
1069 return i;
1070 }
1071 return -1;
1072 }
1073
1031 void SessionManagerService::CleanupChildren(int timeout) { 1074 void SessionManagerService::CleanupChildren(int timeout) {
1032 vector<pair<int, uid_t> > pids_to_kill; 1075 vector<pair<int, uid_t> > pids_to_kill;
1033 1076
1034 for (size_t i = 0; i < child_pids_.size(); ++i) { 1077 for (size_t i = 0; i < child_pids_.size(); ++i) {
1035 const int pid = child_pids_[i]; 1078 const int pid = child_pids_[i];
1036 if (pid < 0) 1079 if (pid < 0)
1037 continue; 1080 continue;
1038 1081
1039 ChildJobInterface* job = child_jobs_[i]; 1082 ChildJobInterface* job = child_jobs_[i];
1040 if (job->ShouldNeverKill()) 1083 if (job->ShouldNeverKill())
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1174 arg_list.push_back(args[i_arg]); 1217 arg_list.push_back(args[i_arg]);
1175 } 1218 }
1176 } 1219 }
1177 if (arg_list.size()) { 1220 if (arg_list.size()) {
1178 arg_lists.push_back(arg_list); 1221 arg_lists.push_back(arg_list);
1179 } 1222 }
1180 return arg_lists; 1223 return arg_lists;
1181 } 1224 }
1182 1225
1183 } // namespace login_manager 1226 } // namespace login_manager
OLDNEW
« no previous file with comments | « session_manager_service.h ('k') | session_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698