Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium 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 "components/os_crypt/key_storage_libsecret.h" | 5 #include "components/os_crypt/key_storage_libsecret.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/rand_util.h" | 8 #include "base/rand_util.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "components/os_crypt/libsecret_util_linux.h" | 10 #include "components/os_crypt/libsecret_util_linux.h" |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 }}; | 26 }}; |
| 27 | 27 |
| 28 const SecretSchema kKeystoreSchemaV2 = { | 28 const SecretSchema kKeystoreSchemaV2 = { |
| 29 "chrome_libsecret_os_crypt_password_v2", | 29 "chrome_libsecret_os_crypt_password_v2", |
| 30 SECRET_SCHEMA_DONT_MATCH_NAME, | 30 SECRET_SCHEMA_DONT_MATCH_NAME, |
| 31 { | 31 { |
| 32 {"application", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 32 {"application", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 33 {nullptr, SECRET_SCHEMA_ATTRIBUTE_STRING}, | 33 {nullptr, SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 34 }}; | 34 }}; |
| 35 | 35 |
| 36 // From a search result, extract a SecretValue, asserting that there was only | |
| 37 // one result. | |
| 38 SecretValue* ToSingleSecret(GList* secret_items) { | |
| 39 GList* first = g_list_first(secret_items); | |
| 40 if (g_list_next(first) != nullptr) { | |
| 41 LOG(ERROR) << "OSCrypt found more than one encryption keys."; | |
|
vasilii
2016/10/21 14:10:07
Seems like you use VLOG everywhere?
cfroussios
2016/10/21 17:56:35
Done.
| |
| 42 } | |
| 43 SecretItem* secret_item = static_cast<SecretItem*>(first->data); | |
| 44 g_list_free(secret_items); | |
|
vasilii
2016/10/21 14:10:07
Doesn't it destroy SecretItem* too?
cfroussios
2016/10/21 17:56:35
There is no method to free a SecretItem.
https://d
vasilii
2016/10/24 10:41:14
The concern was that secret_item_get_secret(secret
cfroussios
2016/10/24 11:25:55
Yes, I forgot to complete my point that if doesn't
| |
| 45 return LibsecretLoader::secret_item_get_secret(secret_item); | |
| 46 } | |
| 47 | |
| 36 } // namespace | 48 } // namespace |
| 37 | 49 |
| 38 std::string KeyStorageLibsecret::AddRandomPasswordInLibsecret() { | 50 std::string KeyStorageLibsecret::AddRandomPasswordInLibsecret() { |
| 39 std::string password; | 51 std::string password; |
| 40 base::Base64Encode(base::RandBytesAsString(16), &password); | 52 base::Base64Encode(base::RandBytesAsString(16), &password); |
| 41 GError* error = nullptr; | 53 GError* error = nullptr; |
| 42 bool success = LibsecretLoader::secret_password_store_sync( | 54 bool success = LibsecretLoader::secret_password_store_sync( |
| 43 &kKeystoreSchemaV2, nullptr, KeyStorageLinux::kKey, password.c_str(), | 55 &kKeystoreSchemaV2, nullptr, KeyStorageLinux::kKey, password.c_str(), |
| 44 nullptr, &error, "application", kApplicationName, nullptr); | 56 nullptr, &error, "application", kApplicationName, nullptr); |
| 45 if (error || !success) { | 57 if (error || !success) { |
| 46 VLOG(1) << "Libsecret lookup failed: " << error->message; | 58 VLOG(1) << "Libsecret lookup failed: " << error->message; |
| 47 return std::string(); | 59 return std::string(); |
| 48 } | 60 } |
| 49 | 61 |
| 50 VLOG(1) << "OSCrypt generated a new password."; | 62 VLOG(1) << "OSCrypt generated a new password."; |
| 51 return password; | 63 return password; |
| 52 } | 64 } |
| 53 | 65 |
| 54 std::string KeyStorageLibsecret::GetKey() { | 66 std::string KeyStorageLibsecret::GetKey() { |
| 55 GError* error = nullptr; | 67 GError* error = nullptr; |
| 56 LibsecretAttributesBuilder attrs; | 68 LibsecretAttributesBuilder attrs; |
| 57 attrs.Append("application", kApplicationName); | 69 attrs.Append("application", kApplicationName); |
| 58 SecretValue* password_libsecret = LibsecretLoader::secret_service_lookup_sync( | 70 GList* search_results = LibsecretLoader::secret_service_search_sync( |
| 59 nullptr, &kKeystoreSchemaV2, attrs.Get(), nullptr, &error); | 71 nullptr /* default secret service */, &kKeystoreSchemaV2, attrs.Get(), |
| 72 static_cast<SecretSearchFlags>(SECRET_SEARCH_UNLOCK | | |
| 73 SECRET_SEARCH_LOAD_SECRETS), | |
| 74 nullptr, &error); | |
| 75 if (error) { | |
| 76 g_error_free(error); | |
| 77 return std::string(); | |
| 78 } | |
| 79 SecretValue* password_libsecret = ToSingleSecret(search_results); | |
| 60 if (error) { | 80 if (error) { |
|
vasilii
2016/10/21 14:10:07
if (error) again?
cfroussios
2016/10/21 17:56:35
Done.
| |
| 61 VLOG(1) << "Libsecret lookup failed: " << error->message; | 81 VLOG(1) << "Libsecret lookup failed: " << error->message; |
| 62 g_error_free(error); | 82 g_error_free(error); |
| 63 return std::string(); | 83 return std::string(); |
| 64 } | 84 } |
| 65 if (!password_libsecret) { | 85 if (!password_libsecret) { |
| 66 std::string password = Migrate(); | 86 std::string password = Migrate(); |
| 67 if (!password.empty()) | 87 if (!password.empty()) |
| 68 return password; | 88 return password; |
| 69 return AddRandomPasswordInLibsecret(); | 89 return AddRandomPasswordInLibsecret(); |
| 70 } | 90 } |
| 71 std::string password( | 91 std::string password( |
| 72 LibsecretLoader::secret_value_get_text(password_libsecret)); | 92 LibsecretLoader::secret_value_get_text(password_libsecret)); |
| 73 LibsecretLoader::secret_value_unref(password_libsecret); | 93 LibsecretLoader::secret_value_unref(password_libsecret); |
| 74 return password; | 94 return password; |
| 75 } | 95 } |
| 76 | 96 |
| 77 bool KeyStorageLibsecret::Init() { | 97 bool KeyStorageLibsecret::Init() { |
| 78 return LibsecretLoader::EnsureLibsecretLoaded(); | 98 return LibsecretLoader::EnsureLibsecretLoaded(); |
| 79 } | 99 } |
| 80 | 100 |
| 81 std::string KeyStorageLibsecret::Migrate() { | 101 std::string KeyStorageLibsecret::Migrate() { |
| 82 GError* error = nullptr; | 102 GError* error = nullptr; |
| 83 LibsecretAttributesBuilder attrs; | 103 LibsecretAttributesBuilder attrs; |
| 84 | 104 |
| 85 // Detect old entry. | 105 // Detect old entry. |
| 86 SecretValue* password_libsecret = LibsecretLoader::secret_service_lookup_sync( | 106 GList* search_results = LibsecretLoader::secret_service_search_sync( |
| 87 nullptr, &kKeystoreSchemaV1, attrs.Get(), nullptr, &error); | 107 nullptr /* default secret service */, &kKeystoreSchemaV1, attrs.Get(), |
| 88 if (error || !password_libsecret) | 108 static_cast<SecretSearchFlags>(SECRET_SEARCH_UNLOCK | |
| 109 SECRET_SEARCH_LOAD_SECRETS), | |
| 110 nullptr, &error); | |
| 111 if (error || !search_results) { | |
|
vasilii
2016/10/21 14:10:07
Why the identical logic above checks just |error|.
cfroussios
2016/10/21 17:56:35
I intended to flatten the nulls in ToSingleSecret(
| |
| 112 g_error_free(error); | |
|
vasilii
2016/10/21 14:10:07
is it ok to free 0?
cfroussios
2016/10/21 17:56:35
They check that it's not null.
https://github.com/
| |
| 113 return std::string(); | |
| 114 } | |
| 115 SecretValue* password_libsecret = ToSingleSecret(search_results); | |
| 116 if (!password_libsecret) | |
| 89 return std::string(); | 117 return std::string(); |
| 90 | 118 |
| 91 VLOG(1) << "OSCrypt detected a deprecated password in Libsecret."; | 119 VLOG(1) << "OSCrypt detected a deprecated password in Libsecret."; |
| 92 std::string password( | 120 std::string password( |
| 93 LibsecretLoader::secret_value_get_text(password_libsecret)); | 121 LibsecretLoader::secret_value_get_text(password_libsecret)); |
| 122 LibsecretLoader::secret_value_unref(password_libsecret); | |
| 94 | 123 |
| 95 // Create new entry. | 124 // Create new entry. |
| 96 bool success = LibsecretLoader::secret_password_store_sync( | 125 bool success = LibsecretLoader::secret_password_store_sync( |
| 97 &kKeystoreSchemaV2, nullptr, KeyStorageLinux::kKey, password.c_str(), | 126 &kKeystoreSchemaV2, nullptr, KeyStorageLinux::kKey, password.c_str(), |
| 98 nullptr, &error, "application", kApplicationName, nullptr); | 127 nullptr, &error, "application", kApplicationName, nullptr); |
| 99 if (error || !success) | 128 if (error || !success) { |
| 129 g_error_free(error); | |
| 100 return std::string(); | 130 return std::string(); |
| 131 } | |
| 101 | 132 |
| 102 // Delete old entry. | 133 // Delete old entry. |
| 103 // Even if deletion failed, we have to use the password that we created. | 134 // Even if deletion failed, we have to use the password that we created. |
| 104 success = LibsecretLoader::secret_password_clear_sync( | 135 success = LibsecretLoader::secret_password_clear_sync( |
| 105 &kKeystoreSchemaV1, nullptr, &error, nullptr); | 136 &kKeystoreSchemaV1, nullptr, &error, nullptr); |
| 137 if (error) | |
| 138 g_error_free(error); | |
| 106 | 139 |
| 107 VLOG(1) << "OSCrypt migrated from deprecated password."; | 140 VLOG(1) << "OSCrypt migrated from deprecated password."; |
| 108 | 141 |
| 109 return password; | 142 return password; |
| 110 } | 143 } |
| OLD | NEW |