Index: session_manager_service.cc |
diff --git a/session_manager_service.cc b/session_manager_service.cc |
index f4bfd8bef7e0a6e2c7b133bba7c968b0d691d532..57245eb6da3bdef89e47dc29eef313a9a86e78eb 100644 |
--- a/session_manager_service.cc |
+++ b/session_manager_service.cc |
@@ -130,6 +130,10 @@ const char SessionManagerService::kTestingChannelFlag[] = |
"--testing-channel=NamedTestingInterface:"; |
// static |
const char SessionManagerService::kIOThreadName[] = "ThreadForIO"; |
+// static |
+const char SessionManagerService::kKeygenExecutable[] = "/sbin/keygen"; |
+// static |
+const char SessionManagerService::kTemporaryKeyFilename[] = "key.pub"; |
namespace { |
@@ -145,6 +149,7 @@ SessionManagerService::SessionManagerService( |
: child_jobs_(child_jobs.begin(), child_jobs.end()), |
child_pids_(child_jobs.size(), -1), |
exit_on_child_done_(false), |
+ keygen_job_(NULL), |
session_manager_(NULL), |
main_loop_(g_main_loop_new(NULL, FALSE)), |
system_(new SystemUtils), |
@@ -479,20 +484,11 @@ gboolean SessionManagerService::StartSession(gchar* email_address, |
return FALSE; |
} |
- if (set_uid_) { |
- *OUT_done = |
- upstart_signal_emitter_->EmitSignal( |
- "start-user-session", |
- StringPrintf("CHROMEOS_USER=%s USER_ID=%d", |
- current_user_.c_str(), uid_), |
- error); |
- } else { |
- *OUT_done = |
- upstart_signal_emitter_->EmitSignal( |
- "start-user-session", |
- StringPrintf("CHROMEOS_USER=%s", current_user_.c_str()), |
- error); |
- } |
+ *OUT_done = |
+ upstart_signal_emitter_->EmitSignal( |
+ "start-user-session", |
+ StringPrintf("CHROMEOS_USER=%s", current_user_.c_str()), |
+ error); |
if (*OUT_done) { |
for (size_t i_child = 0; i_child < child_jobs_.size(); ++i_child) { |
@@ -506,11 +502,75 @@ gboolean SessionManagerService::StartSession(gchar* email_address, |
signals_[kSignalSessionStateChanged], |
0, "started", current_user_.c_str()); |
} |
+ if (key_->HaveCheckedDisk() && !key_->IsPopulated()) |
+ StartKeyGeneration(); |
} |
return *OUT_done; |
} |
+void SessionManagerService::HandleKeygenExit(GPid pid, |
+ gint status, |
+ gpointer data) { |
+ SessionManagerService* manager = static_cast<SessionManagerService*>(data); |
+ int i_child = manager->FindChildByPid(pid); |
+ manager->child_pids_[i_child] = -1; |
+ delete *(manager->child_jobs_.erase(manager->child_jobs_.begin() + i_child)); |
+ |
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { |
+ std::string key; |
+ file_util::ReadFileToString( |
+ FilePath(file_util::GetHomeDir().AppendASCII(kTemporaryKeyFilename)), |
+ &key); |
+ manager->ValidateAndStoreOwnerKey(key); |
+ } else { |
+ if (WIFSIGNALED(status)) |
+ LOG(ERROR) << "keygen exited on signal " << WTERMSIG(status); |
+ else |
+ LOG(ERROR) << "keygen exited with exit code " << WEXITSTATUS(status); |
+ } |
+} |
+ |
+void SessionManagerService::ValidateAndStoreOwnerKey(const std::string& buf) { |
+ std::vector<uint8> pub_key; |
+ NssUtil::KeyFromBuffer(buf, &pub_key); |
+ |
+ if (!CurrentUserHasOwnerKey(pub_key, NULL)) { |
+ SendSignal(chromium::kOwnerKeySetSignal, false); |
+ return; |
+ } |
+ |
+ if (!key_->PopulateFromBuffer(pub_key)) { |
+ SendSignal(chromium::kOwnerKeySetSignal, false); |
+ return; |
+ } |
+ io_thread_.message_loop()->PostTask( |
+ FROM_HERE, NewRunnableMethod(this, &SessionManagerService::PersistKey)); |
+ StoreOwnerProperties(NULL); |
+} |
+ |
+void SessionManagerService::StartKeyGeneration() { |
+ if (!keygen_job_.get()) { |
+ LOG(INFO) << "Creating keygen job"; |
+ std::vector<std::string> keygen_argv; |
+ keygen_argv.push_back(kKeygenExecutable); |
+ keygen_argv.push_back( |
+ file_util::GetHomeDir().AppendASCII(kTemporaryKeyFilename).value()); |
Will Drewry
2011/02/23 03:30:16
I was going to suggest a random location, but sinc
|
+ keygen_job_.reset(new ChildJob(keygen_argv)); |
+ } |
+ |
+ if (set_uid_) |
+ keygen_job_->SetDesiredUid(uid_); |
+ int pid = key_->StartGeneration(keygen_job_.get()); |
+ g_child_watch_add_full(G_PRIORITY_HIGH_IDLE, |
+ pid, |
+ HandleKeygenExit, |
+ this, |
+ NULL); |
+ child_jobs_.push_back(keygen_job_.release()); |
+ child_pids_.push_back(pid); |
+} |
+ |
gboolean SessionManagerService::StopSession(gchar* unique_identifier, |
gboolean* OUT_done, |
GError** error) { |
@@ -531,31 +591,12 @@ gboolean SessionManagerService::StopSession(gchar* unique_identifier, |
gboolean SessionManagerService::SetOwnerKey(GArray* public_key_der, |
GError** error) { |
- LOG(INFO) << "key size is " << public_key_der->len; |
- |
- if (!session_started_) { |
- SetGError(error, |
- CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, |
- "Cannot set the owner's public key outside of a session."); |
- return FALSE; |
- } |
- |
- std::vector<uint8> pub_key; |
- NssUtil::KeyFromBuffer(public_key_der, &pub_key); |
- |
- if (!CurrentUserHasOwnerKey(pub_key, error)) { |
- return FALSE; // error set by CurrentUserHasOwnerKey() |
- } |
- |
- if (!key_->PopulateFromBuffer(pub_key)) { |
- SetGError(error, |
- CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, |
- "Attempted to set invalid key as owner's public key."); |
- return FALSE; |
- } |
- io_thread_.message_loop()->PostTask( |
- FROM_HERE, NewRunnableMethod(this, &SessionManagerService::PersistKey)); |
- return StoreOwnerProperties(error); |
+ SetGError(error, |
+ CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, |
+ "The session_manager now sets the Owner's public key."); |
+ // Just to be safe, send back a nACK in addition to returning an error. |
+ SendSignal(chromium::kOwnerKeySetSignal, false); |
+ return FALSE; |
} |
gboolean SessionManagerService::Unwhitelist(gchar* email_address, |
@@ -784,19 +825,13 @@ void SessionManagerService::HandleChildExit(GPid pid, |
if (manager->shutting_down_) |
return; |
- int i_child = -1; |
- for (int i = 0; i < manager->child_pids_.size(); ++i) { |
- if (manager->child_pids_[i] == pid) { |
- i_child = i; |
- manager->child_pids_[i] = -1; |
- break; |
- } |
+ ChildJobInterface* child_job = NULL; |
+ int i_child = manager->FindChildByPid(pid); |
+ if (i_child >= 0) { |
+ child_job = manager->child_jobs_[i_child]; |
+ manager->child_pids_[i_child] = -1; |
} |
- ChildJobInterface* child_job = i_child >= 0 |
- ? manager->child_jobs_[i_child] |
- : NULL; |
- |
LOG(ERROR) << StringPrintf( |
"Process %s(%d) exited.", |
child_job ? child_job->GetName().c_str() : "", |
@@ -1028,6 +1063,14 @@ gboolean SessionManagerService::ValidateAndCacheUserEmail( |
return TRUE; |
} |
+int SessionManagerService::FindChildByPid(int pid) { |
+ for (int i = 0; i < child_pids_.size(); ++i) { |
+ if (child_pids_[i] == pid) |
+ return i; |
+ } |
+ return -1; |
+} |
+ |
void SessionManagerService::CleanupChildren(int timeout) { |
vector<pair<int, uid_t> > pids_to_kill; |