OLD | NEW |
1 // Copyright (c) 2009-2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2011 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> |
11 #include <secder.h> | 11 #include <secder.h> |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 } else { | 543 } else { |
544 if (WIFSIGNALED(status)) | 544 if (WIFSIGNALED(status)) |
545 LOG(ERROR) << "keygen exited on signal " << WTERMSIG(status); | 545 LOG(ERROR) << "keygen exited on signal " << WTERMSIG(status); |
546 else | 546 else |
547 LOG(ERROR) << "keygen exited with exit code " << WEXITSTATUS(status); | 547 LOG(ERROR) << "keygen exited with exit code " << WEXITSTATUS(status); |
548 } | 548 } |
549 } | 549 } |
550 | 550 |
551 void SessionManagerService::ValidateAndStoreOwnerKey(const std::string& buf) { | 551 void SessionManagerService::ValidateAndStoreOwnerKey(const std::string& buf) { |
552 std::vector<uint8> pub_key; | 552 std::vector<uint8> pub_key; |
553 NssUtil::KeyFromBuffer(buf, &pub_key); | 553 NssUtil::BlobFromBuffer(buf, &pub_key); |
554 | 554 |
555 if (!CurrentUserHasOwnerKey(pub_key, NULL)) { | 555 if (!CurrentUserHasOwnerKey(pub_key, NULL)) { |
556 SendSignal(chromium::kOwnerKeySetSignal, false); | 556 SendSignal(chromium::kOwnerKeySetSignal, false); |
557 return; | 557 return; |
558 } | 558 } |
559 | 559 |
560 if (!key_->PopulateFromBuffer(pub_key)) { | 560 if (!key_->PopulateFromBuffer(pub_key)) { |
561 SendSignal(chromium::kOwnerKeySetSignal, false); | 561 SendSignal(chromium::kOwnerKeySetSignal, false); |
562 return; | 562 return; |
563 } | 563 } |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 | 738 |
739 void SessionManagerService::SendBooleanReply(DBusGMethodInvocation* context, | 739 void SessionManagerService::SendBooleanReply(DBusGMethodInvocation* context, |
740 bool succeeded) { | 740 bool succeeded) { |
741 if (context) | 741 if (context) |
742 dbus_g_method_return(context, succeeded); | 742 dbus_g_method_return(context, succeeded); |
743 } | 743 } |
744 | 744 |
745 gboolean SessionManagerService::StorePolicy(GArray* policy_blob, | 745 gboolean SessionManagerService::StorePolicy(GArray* policy_blob, |
746 DBusGMethodInvocation* context) { | 746 DBusGMethodInvocation* context) { |
747 std::string policy_str(policy_blob->data, policy_blob->len); | 747 std::string policy_str(policy_blob->data, policy_blob->len); |
748 GError* error = NULL; | |
749 enterprise_management::PolicyFetchResponse policy; | 748 enterprise_management::PolicyFetchResponse policy; |
750 if (!policy.ParseFromString(policy_str) || | 749 if (!policy.ParseFromString(policy_str) || |
751 !policy.has_policy_data() || | 750 !policy.has_policy_data() || |
752 !policy.has_policy_data_signature()) { | 751 !policy.has_policy_data_signature()) { |
753 const char msg[] = "Unable to parse policy protobuf."; | 752 const char msg[] = "Unable to parse policy protobuf."; |
754 LOG(ERROR) << msg; | 753 LOG(ERROR) << msg; |
755 SetGError(&error, CHROMEOS_LOGIN_ERROR_DECODE_FAIL, msg); | 754 SetAndSendGError(CHROMEOS_LOGIN_ERROR_DECODE_FAIL, context, msg); |
756 dbus_g_method_return_error(context, error); | |
757 g_error_free(error); | |
758 return FALSE; | 755 return FALSE; |
759 } | 756 } |
| 757 |
| 758 // Determine if the policy has pushed a new owner key and, if so, set it and |
| 759 // schedule a task to persist it to disk. |
| 760 if (policy.has_new_public_key() && !key_->Equals(policy.new_public_key())) { |
| 761 // The policy contains a new key, and it is different from |key_|. |
| 762 std::vector<uint8> der; |
| 763 nss_->BlobFromBuffer(policy.new_public_key(), &der); |
| 764 |
| 765 if (session_started_) { |
| 766 bool rotated = false; |
| 767 if (policy.has_new_public_key_signature()) { |
| 768 // Graceful key rotation. |
| 769 std::vector<uint8> sig; |
| 770 nss_->BlobFromBuffer(policy.new_public_key_signature(), &sig); |
| 771 rotated = key_->Rotate(der, sig); |
| 772 } |
| 773 if (!rotated) { |
| 774 const char msg[] = "Failed attempted key rotation!"; |
| 775 LOG(ERROR) << msg; |
| 776 SetAndSendGError(CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, context, msg); |
| 777 return FALSE; |
| 778 } |
| 779 } else { |
| 780 // Force a new key, regardless of whether we have one or not. |
| 781 if (key_->IsPopulated()) { |
| 782 key_->ClobberCompromisedKey(der); |
| 783 LOG(INFO) << "Clobbered existing key outside of session"; |
| 784 } else { |
| 785 CHECK(key_->PopulateFromBuffer(der)); // Should be unable to fail. |
| 786 LOG(INFO) << "Setting key outside of session"; |
| 787 } |
| 788 } |
| 789 // If here, need to persit new key to disk. Already loaded key into memory. |
| 790 io_thread_.message_loop()->PostTask( |
| 791 FROM_HERE, NewRunnableMethod(this, &SessionManagerService::PersistKey)); |
| 792 } |
| 793 |
| 794 // Validate signature on policy and persist to disk |
760 const std::string& sig = policy.policy_data_signature(); | 795 const std::string& sig = policy.policy_data_signature(); |
761 SessionManagerService::SigReturnCode verify_result = | 796 SessionManagerService::SigReturnCode verify_result = |
762 VerifyHelper(policy.policy_data(), sig.c_str(), sig.length()); | 797 VerifyHelper(policy.policy_data(), sig.c_str(), sig.length()); |
763 if (verify_result == NO_KEY) { | 798 if (verify_result == NO_KEY) { |
764 const char msg[] = "Attempt to store policy before owner's key is set."; | 799 NOTREACHED() << "Should have set the key earlier in this function!"; |
765 LOG(ERROR) << msg; | |
766 SetGError(&error, CHROMEOS_LOGIN_ERROR_NO_OWNER_KEY, msg); | |
767 return FALSE; | 800 return FALSE; |
768 } else if (verify_result == SIGNATURE_FAIL) { | 801 } else if (verify_result == SIGNATURE_FAIL) { |
769 const char msg[] = "Signature could not be verified in StorePolicy."; | 802 const char msg[] = "Signature could not be verified in StorePolicy."; |
770 LOG(ERROR) << msg; | 803 LOG(ERROR) << msg; |
771 SetGError(&error, CHROMEOS_LOGIN_ERROR_VERIFY_FAIL, msg); | 804 SetAndSendGError(CHROMEOS_LOGIN_ERROR_VERIFY_FAIL, context, msg); |
772 return FALSE; | 805 return FALSE; |
773 } | 806 } |
774 policy_->Set(policy); | 807 policy_->Set(policy); |
775 io_thread_.message_loop()->PostTask( | 808 io_thread_.message_loop()->PostTask( |
776 FROM_HERE, NewRunnableMethod(this, &SessionManagerService::PersistPolicy, | 809 FROM_HERE, NewRunnableMethod(this, &SessionManagerService::PersistPolicy, |
777 context)); | 810 context)); |
778 return TRUE; | 811 return TRUE; |
779 } | 812 } |
780 | 813 |
781 gboolean SessionManagerService::RetrievePolicy(GArray** OUT_policy_blob, | 814 gboolean SessionManagerService::RetrievePolicy(GArray** OUT_policy_blob, |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
993 what_happened)); | 1026 what_happened)); |
994 } | 1027 } |
995 | 1028 |
996 // static | 1029 // static |
997 void SessionManagerService::SetGError(GError** error, | 1030 void SessionManagerService::SetGError(GError** error, |
998 ChromeOSLoginError code, | 1031 ChromeOSLoginError code, |
999 const char* message) { | 1032 const char* message) { |
1000 g_set_error(error, CHROMEOS_LOGIN_ERROR, code, "Login error: %s", message); | 1033 g_set_error(error, CHROMEOS_LOGIN_ERROR, code, "Login error: %s", message); |
1001 } | 1034 } |
1002 | 1035 |
| 1036 // static |
| 1037 void SessionManagerService::SetAndSendGError(ChromeOSLoginError code, |
| 1038 DBusGMethodInvocation* context, |
| 1039 const char* msg) { |
| 1040 GError* error = NULL; |
| 1041 SetGError(&error, code, msg); |
| 1042 dbus_g_method_return_error(context, error); |
| 1043 g_error_free(error); |
| 1044 } |
1003 | 1045 |
1004 /////////////////////////////////////////////////////////////////////////////// | 1046 /////////////////////////////////////////////////////////////////////////////// |
1005 // Utility Methods | 1047 // Utility Methods |
1006 | 1048 |
1007 // This can probably be more efficient, if it needs to be. | 1049 // This can probably be more efficient, if it needs to be. |
1008 // static | 1050 // static |
1009 bool SessionManagerService::ValidateEmail(const string& email_address) { | 1051 bool SessionManagerService::ValidateEmail(const string& email_address) { |
1010 if (email_address.find_first_not_of(kLegalCharacters) != string::npos) | 1052 if (email_address.find_first_not_of(kLegalCharacters) != string::npos) |
1011 return false; | 1053 return false; |
1012 | 1054 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1095 } | 1137 } |
1096 | 1138 |
1097 gboolean SessionManagerService::CurrentUserIsOwner(GError** error) { | 1139 gboolean SessionManagerService::CurrentUserIsOwner(GError** error) { |
1098 std::string value; | 1140 std::string value; |
1099 std::string decoded; | 1141 std::string decoded; |
1100 if (!GetPropertyHelper(kDeviceOwnerPref, &value, &decoded, error)) | 1142 if (!GetPropertyHelper(kDeviceOwnerPref, &value, &decoded, error)) |
1101 return FALSE; | 1143 return FALSE; |
1102 std::string was_signed = base::StringPrintf("%s=%s", | 1144 std::string was_signed = base::StringPrintf("%s=%s", |
1103 kDeviceOwnerPref, | 1145 kDeviceOwnerPref, |
1104 value.c_str()); | 1146 value.c_str()); |
1105 if (!key_->Verify(was_signed.c_str(), | 1147 if (VerifyHelper(was_signed, decoded.c_str(), decoded.length()) != SUCCESS) { |
1106 was_signed.length(), | |
1107 decoded.c_str(), | |
1108 decoded.length())) { | |
1109 const char msg[] = "Owner pref signature could not be verified."; | 1148 const char msg[] = "Owner pref signature could not be verified."; |
1110 LOG(ERROR) << msg; | 1149 LOG(ERROR) << msg; |
1111 SetGError(error, CHROMEOS_LOGIN_ERROR_VERIFY_FAIL, msg); | 1150 SetGError(error, CHROMEOS_LOGIN_ERROR_VERIFY_FAIL, msg); |
1112 return FALSE; | 1151 return FALSE; |
1113 } | 1152 } |
1114 return value == current_user_; | 1153 return value == current_user_; |
1115 } | 1154 } |
1116 | 1155 |
1117 gboolean SessionManagerService::CurrentUserHasOwnerKey( | 1156 gboolean SessionManagerService::CurrentUserHasOwnerKey( |
1118 const std::vector<uint8>& pub_key, | 1157 const std::vector<uint8>& pub_key, |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1196 } | 1235 } |
1197 | 1236 |
1198 gboolean SessionManagerService::SignAndStoreProperty(const std::string& name, | 1237 gboolean SessionManagerService::SignAndStoreProperty(const std::string& name, |
1199 const std::string& value, | 1238 const std::string& value, |
1200 const std::string& err_msg, | 1239 const std::string& err_msg, |
1201 GError** error) { | 1240 GError** error) { |
1202 std::vector<uint8> signature; | 1241 std::vector<uint8> signature; |
1203 std::string to_sign = base::StringPrintf("%s=%s", | 1242 std::string to_sign = base::StringPrintf("%s=%s", |
1204 kDeviceOwnerPref, | 1243 kDeviceOwnerPref, |
1205 current_user_.c_str()); | 1244 current_user_.c_str()); |
1206 if (!key_->Sign(to_sign.c_str(), to_sign.length(), &signature)) { | 1245 const uint8* data = reinterpret_cast<const uint8*>(to_sign.c_str()); |
| 1246 if (!key_->Sign(data, to_sign.length(), &signature)) { |
1207 LOG_IF(ERROR, error) << err_msg; | 1247 LOG_IF(ERROR, error) << err_msg; |
1208 LOG_IF(WARNING, !error) << err_msg; | 1248 LOG_IF(WARNING, !error) << err_msg; |
1209 SetGError(error, CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, err_msg.c_str()); | 1249 SetGError(error, CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, err_msg.c_str()); |
1210 return FALSE; | 1250 return FALSE; |
1211 } | 1251 } |
1212 std::string signature_string(reinterpret_cast<const char*>(&signature[0]), | 1252 std::string signature_string(reinterpret_cast<const char*>(&signature[0]), |
1213 signature.size()); | 1253 signature.size()); |
1214 return SetPropertyHelper(kDeviceOwnerPref, | 1254 return SetPropertyHelper(kDeviceOwnerPref, |
1215 current_user_, | 1255 current_user_, |
1216 signature_string, | 1256 signature_string, |
1217 error); | 1257 error); |
1218 } | 1258 } |
1219 | 1259 |
1220 gboolean SessionManagerService::SignAndWhitelist(const std::string& email, | 1260 gboolean SessionManagerService::SignAndWhitelist(const std::string& email, |
1221 const std::string& err_msg, | 1261 const std::string& err_msg, |
1222 GError** error) { | 1262 GError** error) { |
1223 std::vector<uint8> signature; | 1263 std::vector<uint8> signature; |
1224 if (!key_->Sign(current_user_.c_str(), current_user_.length(), &signature)) { | 1264 const uint8* data = reinterpret_cast<const uint8*>(current_user_.c_str()); |
| 1265 if (!key_->Sign(data, current_user_.length(), &signature)) { |
1225 LOG_IF(ERROR, error) << err_msg; | 1266 LOG_IF(ERROR, error) << err_msg; |
1226 LOG_IF(WARNING, !error) << err_msg; | 1267 LOG_IF(WARNING, !error) << err_msg; |
1227 SetGError(error, CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, err_msg.c_str()); | 1268 SetGError(error, CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, err_msg.c_str()); |
1228 return FALSE; | 1269 return FALSE; |
1229 } | 1270 } |
1230 std::string signature_string(reinterpret_cast<const char*>(&signature[0]), | 1271 std::string signature_string(reinterpret_cast<const char*>(&signature[0]), |
1231 signature.size()); | 1272 signature.size()); |
1232 return WhitelistHelper(current_user_, signature_string, error); | 1273 return WhitelistHelper(current_user_, signature_string, error); |
1233 } | 1274 } |
1234 | 1275 |
(...skipping 18 matching lines...) Expand all Loading... |
1253 SessionManagerService::VerifyHelperArray(const std::string& data, GArray* sig) { | 1294 SessionManagerService::VerifyHelperArray(const std::string& data, GArray* sig) { |
1254 return VerifyHelper(data, sig->data, sig->len); | 1295 return VerifyHelper(data, sig->data, sig->len); |
1255 } | 1296 } |
1256 | 1297 |
1257 SessionManagerService::SigReturnCode | 1298 SessionManagerService::SigReturnCode |
1258 SessionManagerService::VerifyHelper(const std::string& data, | 1299 SessionManagerService::VerifyHelper(const std::string& data, |
1259 const char* sig, | 1300 const char* sig, |
1260 uint32 sig_len) { | 1301 uint32 sig_len) { |
1261 if (!key_->IsPopulated()) | 1302 if (!key_->IsPopulated()) |
1262 return NO_KEY; | 1303 return NO_KEY; |
1263 if (!key_->Verify(data.c_str(), data.length(), sig, sig_len)) | 1304 if (!key_->Verify(reinterpret_cast<const uint8*>(data.c_str()), |
| 1305 data.length(), |
| 1306 reinterpret_cast<const uint8*>(sig), |
| 1307 sig_len)) { |
1264 return SIGNATURE_FAIL; | 1308 return SIGNATURE_FAIL; |
| 1309 } |
1265 return SUCCESS; | 1310 return SUCCESS; |
1266 } | 1311 } |
1267 | 1312 |
1268 gboolean SessionManagerService::WhitelistHelper(const std::string& email, | 1313 gboolean SessionManagerService::WhitelistHelper(const std::string& email, |
1269 const std::string& signature, | 1314 const std::string& signature, |
1270 GError** error) { | 1315 GError** error) { |
1271 std::string encoded; | 1316 std::string encoded; |
1272 if (!base::Base64Encode(signature, &encoded)) { | 1317 if (!base::Base64Encode(signature, &encoded)) { |
1273 const char msg[] = "Signature could not be encoded."; | 1318 const char msg[] = "Signature could not be encoded."; |
1274 LOG(ERROR) << msg; | 1319 LOG(ERROR) << msg; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1324 arg_list.push_back(args[i_arg]); | 1369 arg_list.push_back(args[i_arg]); |
1325 } | 1370 } |
1326 } | 1371 } |
1327 if (arg_list.size()) { | 1372 if (arg_list.size()) { |
1328 arg_lists.push_back(arg_list); | 1373 arg_lists.push_back(arg_list); |
1329 } | 1374 } |
1330 return arg_lists; | 1375 return arg_lists; |
1331 } | 1376 } |
1332 | 1377 |
1333 } // namespace login_manager | 1378 } // namespace login_manager |
OLD | NEW |