| Index: session_manager_service.cc
|
| diff --git a/session_manager_service.cc b/session_manager_service.cc
|
| index a5e9c27b79b645e2bcac204157306c09292108ca..25afa85a3fc59f03c59662b225e5861f21dbc7e4 100644
|
| --- a/session_manager_service.cc
|
| +++ b/session_manager_service.cc
|
| @@ -1,4 +1,4 @@
|
| -// Copyright (c) 2009-2010 The Chromium OS Authors. All rights reserved.
|
| +// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| @@ -550,7 +550,7 @@ void SessionManagerService::HandleKeygenExit(GPid pid,
|
|
|
| void SessionManagerService::ValidateAndStoreOwnerKey(const std::string& buf) {
|
| std::vector<uint8> pub_key;
|
| - NssUtil::KeyFromBuffer(buf, &pub_key);
|
| + NssUtil::BlobFromBuffer(buf, &pub_key);
|
|
|
| if (!CurrentUserHasOwnerKey(pub_key, NULL)) {
|
| SendSignal(chromium::kOwnerKeySetSignal, false);
|
| @@ -745,30 +745,63 @@ void SessionManagerService::SendBooleanReply(DBusGMethodInvocation* context,
|
| gboolean SessionManagerService::StorePolicy(GArray* policy_blob,
|
| DBusGMethodInvocation* context) {
|
| std::string policy_str(policy_blob->data, policy_blob->len);
|
| - GError* error = NULL;
|
| enterprise_management::PolicyFetchResponse policy;
|
| if (!policy.ParseFromString(policy_str) ||
|
| !policy.has_policy_data() ||
|
| !policy.has_policy_data_signature()) {
|
| const char msg[] = "Unable to parse policy protobuf.";
|
| LOG(ERROR) << msg;
|
| - SetGError(&error, CHROMEOS_LOGIN_ERROR_DECODE_FAIL, msg);
|
| - dbus_g_method_return_error(context, error);
|
| - g_error_free(error);
|
| + SetAndSendGError(CHROMEOS_LOGIN_ERROR_DECODE_FAIL, context, msg);
|
| return FALSE;
|
| }
|
| +
|
| + // Determine if the policy has pushed a new owner key and, if so, set it and
|
| + // schedule a task to persist it to disk.
|
| + if (policy.has_new_public_key() && !key_->Equals(policy.new_public_key())) {
|
| + // The policy contains a new key, and it is different from |key_|.
|
| + std::vector<uint8> der;
|
| + nss_->BlobFromBuffer(policy.new_public_key(), &der);
|
| +
|
| + if (session_started_) {
|
| + bool rotated = false;
|
| + if (policy.has_new_public_key_signature()) {
|
| + // Graceful key rotation.
|
| + std::vector<uint8> sig;
|
| + nss_->BlobFromBuffer(policy.new_public_key_signature(), &sig);
|
| + rotated = key_->Rotate(der, sig);
|
| + }
|
| + if (!rotated) {
|
| + const char msg[] = "Failed attempted key rotation!";
|
| + LOG(ERROR) << msg;
|
| + SetAndSendGError(CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, context, msg);
|
| + return FALSE;
|
| + }
|
| + } else {
|
| + // Force a new key, regardless of whether we have one or not.
|
| + if (key_->IsPopulated()) {
|
| + key_->ClobberCompromisedKey(der);
|
| + LOG(INFO) << "Clobbered existing key outside of session";
|
| + } else {
|
| + CHECK(key_->PopulateFromBuffer(der)); // Should be unable to fail.
|
| + LOG(INFO) << "Setting key outside of session";
|
| + }
|
| + }
|
| + // If here, need to persit new key to disk. Already loaded key into memory.
|
| + io_thread_.message_loop()->PostTask(
|
| + FROM_HERE, NewRunnableMethod(this, &SessionManagerService::PersistKey));
|
| + }
|
| +
|
| + // Validate signature on policy and persist to disk
|
| const std::string& sig = policy.policy_data_signature();
|
| SessionManagerService::SigReturnCode verify_result =
|
| VerifyHelper(policy.policy_data(), sig.c_str(), sig.length());
|
| if (verify_result == NO_KEY) {
|
| - const char msg[] = "Attempt to store policy before owner's key is set.";
|
| - LOG(ERROR) << msg;
|
| - SetGError(&error, CHROMEOS_LOGIN_ERROR_NO_OWNER_KEY, msg);
|
| + NOTREACHED() << "Should have set the key earlier in this function!";
|
| return FALSE;
|
| } else if (verify_result == SIGNATURE_FAIL) {
|
| const char msg[] = "Signature could not be verified in StorePolicy.";
|
| LOG(ERROR) << msg;
|
| - SetGError(&error, CHROMEOS_LOGIN_ERROR_VERIFY_FAIL, msg);
|
| + SetAndSendGError(CHROMEOS_LOGIN_ERROR_VERIFY_FAIL, context, msg);
|
| return FALSE;
|
| }
|
| policy_->Set(policy);
|
| @@ -1000,6 +1033,15 @@ void SessionManagerService::SetGError(GError** error,
|
| g_set_error(error, CHROMEOS_LOGIN_ERROR, code, "Login error: %s", message);
|
| }
|
|
|
| +// static
|
| +void SessionManagerService::SetAndSendGError(ChromeOSLoginError code,
|
| + DBusGMethodInvocation* context,
|
| + const char* msg) {
|
| + GError* error = NULL;
|
| + SetGError(&error, code, msg);
|
| + dbus_g_method_return_error(context, error);
|
| + g_error_free(error);
|
| +}
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| // Utility Methods
|
| @@ -1102,10 +1144,7 @@ gboolean SessionManagerService::CurrentUserIsOwner(GError** error) {
|
| std::string was_signed = base::StringPrintf("%s=%s",
|
| kDeviceOwnerPref,
|
| value.c_str());
|
| - if (!key_->Verify(was_signed.c_str(),
|
| - was_signed.length(),
|
| - decoded.c_str(),
|
| - decoded.length())) {
|
| + if (VerifyHelper(was_signed, decoded.c_str(), decoded.length()) != SUCCESS) {
|
| const char msg[] = "Owner pref signature could not be verified.";
|
| LOG(ERROR) << msg;
|
| SetGError(error, CHROMEOS_LOGIN_ERROR_VERIFY_FAIL, msg);
|
| @@ -1203,7 +1242,8 @@ gboolean SessionManagerService::SignAndStoreProperty(const std::string& name,
|
| std::string to_sign = base::StringPrintf("%s=%s",
|
| kDeviceOwnerPref,
|
| current_user_.c_str());
|
| - if (!key_->Sign(to_sign.c_str(), to_sign.length(), &signature)) {
|
| + const uint8* data = reinterpret_cast<const uint8*>(to_sign.c_str());
|
| + if (!key_->Sign(data, to_sign.length(), &signature)) {
|
| LOG_IF(ERROR, error) << err_msg;
|
| LOG_IF(WARNING, !error) << err_msg;
|
| SetGError(error, CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, err_msg.c_str());
|
| @@ -1221,7 +1261,8 @@ gboolean SessionManagerService::SignAndWhitelist(const std::string& email,
|
| const std::string& err_msg,
|
| GError** error) {
|
| std::vector<uint8> signature;
|
| - if (!key_->Sign(current_user_.c_str(), current_user_.length(), &signature)) {
|
| + const uint8* data = reinterpret_cast<const uint8*>(current_user_.c_str());
|
| + if (!key_->Sign(data, current_user_.length(), &signature)) {
|
| LOG_IF(ERROR, error) << err_msg;
|
| LOG_IF(WARNING, !error) << err_msg;
|
| SetGError(error, CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, err_msg.c_str());
|
| @@ -1260,8 +1301,12 @@ SessionManagerService::VerifyHelper(const std::string& data,
|
| uint32 sig_len) {
|
| if (!key_->IsPopulated())
|
| return NO_KEY;
|
| - if (!key_->Verify(data.c_str(), data.length(), sig, sig_len))
|
| + if (!key_->Verify(reinterpret_cast<const uint8*>(data.c_str()),
|
| + data.length(),
|
| + reinterpret_cast<const uint8*>(sig),
|
| + sig_len)) {
|
| return SIGNATURE_FAIL;
|
| + }
|
| return SUCCESS;
|
| }
|
|
|
|
|