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, extracts a SecretValue, asserting that there was at |
| 37 // most one result. Returns nullptr if there are no results. |
| 38 SecretValue* ToSingleSecret(GList* secret_items) { |
| 39 GList* first = g_list_first(secret_items); |
| 40 if (first == nullptr) |
| 41 return nullptr; |
| 42 if (g_list_next(first) != nullptr) { |
| 43 VLOG(1) << "OSCrypt found more than one encryption keys."; |
| 44 } |
| 45 SecretItem* secret_item = static_cast<SecretItem*>(first->data); |
| 46 SecretValue* secret_value = |
| 47 LibsecretLoader::secret_item_get_secret(secret_item); |
| 48 g_list_free(secret_items); |
| 49 return secret_value; |
| 50 } |
| 51 |
36 } // namespace | 52 } // namespace |
37 | 53 |
38 std::string KeyStorageLibsecret::AddRandomPasswordInLibsecret() { | 54 std::string KeyStorageLibsecret::AddRandomPasswordInLibsecret() { |
39 std::string password; | 55 std::string password; |
40 base::Base64Encode(base::RandBytesAsString(16), &password); | 56 base::Base64Encode(base::RandBytesAsString(16), &password); |
41 GError* error = nullptr; | 57 GError* error = nullptr; |
42 bool success = LibsecretLoader::secret_password_store_sync( | 58 bool success = LibsecretLoader::secret_password_store_sync( |
43 &kKeystoreSchemaV2, nullptr, KeyStorageLinux::kKey, password.c_str(), | 59 &kKeystoreSchemaV2, nullptr, KeyStorageLinux::kKey, password.c_str(), |
44 nullptr, &error, "application", kApplicationName, nullptr); | 60 nullptr, &error, "application", kApplicationName, nullptr); |
45 if (error || !success) { | 61 if (error) { |
46 VLOG(1) << "Libsecret lookup failed: " << error->message; | 62 VLOG(1) << "Libsecret lookup failed: " << error->message; |
| 63 g_error_free(error); |
| 64 return std::string(); |
| 65 } |
| 66 if (!success) { |
| 67 VLOG(1) << "Libsecret lookup failed."; |
47 return std::string(); | 68 return std::string(); |
48 } | 69 } |
49 | 70 |
50 VLOG(1) << "OSCrypt generated a new password."; | 71 VLOG(1) << "OSCrypt generated a new password."; |
51 return password; | 72 return password; |
52 } | 73 } |
53 | 74 |
54 std::string KeyStorageLibsecret::GetKey() { | 75 std::string KeyStorageLibsecret::GetKey() { |
55 GError* error = nullptr; | 76 GError* error = nullptr; |
56 LibsecretAttributesBuilder attrs; | 77 LibsecretAttributesBuilder attrs; |
57 attrs.Append("application", kApplicationName); | 78 attrs.Append("application", kApplicationName); |
58 SecretValue* password_libsecret = LibsecretLoader::secret_service_lookup_sync( | 79 GList* search_results = LibsecretLoader::secret_service_search_sync( |
59 nullptr, &kKeystoreSchemaV2, attrs.Get(), nullptr, &error); | 80 nullptr /* default secret service */, &kKeystoreSchemaV2, attrs.Get(), |
| 81 static_cast<SecretSearchFlags>(SECRET_SEARCH_UNLOCK | |
| 82 SECRET_SEARCH_LOAD_SECRETS), |
| 83 nullptr, &error); |
60 if (error) { | 84 if (error) { |
61 VLOG(1) << "Libsecret lookup failed: " << error->message; | 85 VLOG(1) << "Libsecret lookup failed: " << error->message; |
62 g_error_free(error); | 86 g_error_free(error); |
63 return std::string(); | 87 return std::string(); |
64 } | 88 } |
| 89 SecretValue* password_libsecret = ToSingleSecret(search_results); |
65 if (!password_libsecret) { | 90 if (!password_libsecret) { |
66 std::string password = Migrate(); | 91 std::string password = Migrate(); |
67 if (!password.empty()) | 92 if (!password.empty()) |
68 return password; | 93 return password; |
69 return AddRandomPasswordInLibsecret(); | 94 return AddRandomPasswordInLibsecret(); |
70 } | 95 } |
71 std::string password( | 96 std::string password( |
72 LibsecretLoader::secret_value_get_text(password_libsecret)); | 97 LibsecretLoader::secret_value_get_text(password_libsecret)); |
73 LibsecretLoader::secret_value_unref(password_libsecret); | 98 LibsecretLoader::secret_value_unref(password_libsecret); |
74 return password; | 99 return password; |
75 } | 100 } |
76 | 101 |
77 bool KeyStorageLibsecret::Init() { | 102 bool KeyStorageLibsecret::Init() { |
78 return LibsecretLoader::EnsureLibsecretLoaded(); | 103 return LibsecretLoader::EnsureLibsecretLoaded(); |
79 } | 104 } |
80 | 105 |
81 std::string KeyStorageLibsecret::Migrate() { | 106 std::string KeyStorageLibsecret::Migrate() { |
82 GError* error = nullptr; | 107 GError* error = nullptr; |
83 LibsecretAttributesBuilder attrs; | 108 LibsecretAttributesBuilder attrs; |
84 | 109 |
85 // Detect old entry. | 110 // Detect old entry. |
86 SecretValue* password_libsecret = LibsecretLoader::secret_service_lookup_sync( | 111 GList* search_results = LibsecretLoader::secret_service_search_sync( |
87 nullptr, &kKeystoreSchemaV1, attrs.Get(), nullptr, &error); | 112 nullptr /* default secret service */, &kKeystoreSchemaV1, attrs.Get(), |
88 if (error || !password_libsecret) | 113 static_cast<SecretSearchFlags>(SECRET_SEARCH_UNLOCK | |
| 114 SECRET_SEARCH_LOAD_SECRETS), |
| 115 nullptr, &error); |
| 116 if (error) { |
| 117 g_error_free(error); |
| 118 g_list_free(search_results); |
| 119 return std::string(); |
| 120 } |
| 121 SecretValue* password_libsecret = ToSingleSecret(search_results); |
| 122 if (!password_libsecret) |
89 return std::string(); | 123 return std::string(); |
90 | 124 |
91 VLOG(1) << "OSCrypt detected a deprecated password in Libsecret."; | 125 VLOG(1) << "OSCrypt detected a deprecated password in Libsecret."; |
92 std::string password( | 126 std::string password( |
93 LibsecretLoader::secret_value_get_text(password_libsecret)); | 127 LibsecretLoader::secret_value_get_text(password_libsecret)); |
| 128 LibsecretLoader::secret_value_unref(password_libsecret); |
94 | 129 |
95 // Create new entry. | 130 // Create new entry. |
96 bool success = LibsecretLoader::secret_password_store_sync( | 131 bool success = LibsecretLoader::secret_password_store_sync( |
97 &kKeystoreSchemaV2, nullptr, KeyStorageLinux::kKey, password.c_str(), | 132 &kKeystoreSchemaV2, nullptr, KeyStorageLinux::kKey, password.c_str(), |
98 nullptr, &error, "application", kApplicationName, nullptr); | 133 nullptr, &error, "application", kApplicationName, nullptr); |
99 if (error || !success) | 134 if (error) { |
| 135 VLOG(1) << "Failed to store migrated password. " << error->message; |
| 136 g_error_free(error); |
100 return std::string(); | 137 return std::string(); |
| 138 } |
| 139 if (!success) { |
| 140 VLOG(1) << "Failed to store migrated password."; |
| 141 return std::string(); |
| 142 } |
101 | 143 |
102 // Delete old entry. | 144 // Delete old entry. |
103 // Even if deletion failed, we have to use the password that we created. | 145 // Even if deletion failed, we have to use the password that we created. |
104 success = LibsecretLoader::secret_password_clear_sync( | 146 success = LibsecretLoader::secret_password_clear_sync( |
105 &kKeystoreSchemaV1, nullptr, &error, nullptr); | 147 &kKeystoreSchemaV1, nullptr, &error, nullptr); |
| 148 if (error) { |
| 149 VLOG(1) << "OSCrypt failed to delete deprecated password. " |
| 150 << error->message; |
| 151 g_error_free(error); |
| 152 } |
106 | 153 |
107 VLOG(1) << "OSCrypt migrated from deprecated password."; | 154 VLOG(1) << "OSCrypt migrated from deprecated password."; |
108 | 155 |
109 return password; | 156 return password; |
110 } | 157 } |
OLD | NEW |