| OLD | NEW |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 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 "chrome/browser/password_manager/native_backend_libsecret.h" | 5 #include "chrome/browser/password_manager/native_backend_libsecret.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 #include <list> | 8 #include <list> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 libsecret_loaded = true; | 84 libsecret_loaded = true; |
| 85 // We leak the library handle. That's OK: this function is called only once. | 85 // We leak the library handle. That's OK: this function is called only once. |
| 86 return true; | 86 return true; |
| 87 } | 87 } |
| 88 | 88 |
| 89 namespace { | 89 namespace { |
| 90 | 90 |
| 91 const char kLibsecretAppString[] = "chrome"; | 91 const char kLibsecretAppString[] = "chrome"; |
| 92 | 92 |
| 93 // Schema is analagous to the fields in PasswordForm. | 93 // Schema is analagous to the fields in PasswordForm. |
| 94 // TODO(gcasto): Adding 'form_data' would be nice, but we would need to | |
| 95 // serialize in a way that is guaranteed to not have any embedded NULLs. Pickle | |
| 96 // doesn't make this guarantee, so we just don't serialize this field. Since | |
| 97 // it's only used to crowd source data collection it doesn't matter that much | |
| 98 // if it's not available on this platform. | |
| 99 const SecretSchema kLibsecretSchema = { | 94 const SecretSchema kLibsecretSchema = { |
| 100 "chrome_libsecret_password_schema", | 95 "chrome_libsecret_password_schema", |
| 101 // We have to use SECRET_SCHEMA_DONT_MATCH_NAME in order to get old | 96 // We have to use SECRET_SCHEMA_DONT_MATCH_NAME in order to get old |
| 102 // passwords stored with gnome_keyring. | 97 // passwords stored with gnome_keyring. |
| 103 SECRET_SCHEMA_DONT_MATCH_NAME, | 98 SECRET_SCHEMA_DONT_MATCH_NAME, |
| 104 {{"origin_url", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 99 {{"origin_url", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 105 {"action_url", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 100 {"action_url", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 106 {"username_element", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 101 {"username_element", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 107 {"username_value", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 102 {"username_value", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 108 {"password_element", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 103 {"password_element", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 109 {"submit_element", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 104 {"submit_element", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 110 {"signon_realm", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 105 {"signon_realm", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 111 {"ssl_valid", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, | 106 {"ssl_valid", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, |
| 112 {"preferred", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, | 107 {"preferred", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, |
| 113 {"date_created", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 108 {"date_created", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 114 {"blacklisted_by_user", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, | 109 {"blacklisted_by_user", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, |
| 115 {"scheme", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, | 110 {"scheme", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, |
| 116 {"type", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, | 111 {"type", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, |
| 117 {"times_used", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, | 112 {"times_used", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, |
| 118 {"date_synced", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 113 {"date_synced", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 119 {"display_name", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 114 {"display_name", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 120 {"avatar_url", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 115 {"avatar_url", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 121 {"federation_url", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 116 {"federation_url", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 122 {"skip_zero_click", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, | 117 {"skip_zero_click", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, |
| 123 {"generation_upload_status", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, | 118 {"generation_upload_status", SECRET_SCHEMA_ATTRIBUTE_INTEGER}, |
| 119 {"form_data", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 124 // This field is always "chrome-profile_id" so that we can search for it. | 120 // This field is always "chrome-profile_id" so that we can search for it. |
| 125 {"application", SECRET_SCHEMA_ATTRIBUTE_STRING}, | 121 {"application", SECRET_SCHEMA_ATTRIBUTE_STRING}, |
| 126 {nullptr, SECRET_SCHEMA_ATTRIBUTE_STRING}}}; | 122 {nullptr, SECRET_SCHEMA_ATTRIBUTE_STRING}}}; |
| 127 | 123 |
| 128 const char* GetStringFromAttributes(GHashTable* attrs, const char* keyname) { | 124 const char* GetStringFromAttributes(GHashTable* attrs, const char* keyname) { |
| 129 gpointer value = g_hash_table_lookup(attrs, keyname); | 125 gpointer value = g_hash_table_lookup(attrs, keyname); |
| 130 return value ? static_cast<char*>(value) : kEmptyString; | 126 return value ? static_cast<char*>(value) : kEmptyString; |
| 131 } | 127 } |
| 132 | 128 |
| 133 uint32_t GetUintFromAttributes(GHashTable* attrs, const char* keyname) { | 129 uint32_t GetUintFromAttributes(GHashTable* attrs, const char* keyname) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 &date_synced); | 183 &date_synced); |
| 188 form->date_synced = base::Time::FromInternalValue(date_synced); | 184 form->date_synced = base::Time::FromInternalValue(date_synced); |
| 189 form->display_name = | 185 form->display_name = |
| 190 UTF8ToUTF16(GetStringFromAttributes(attrs, "display_name")); | 186 UTF8ToUTF16(GetStringFromAttributes(attrs, "display_name")); |
| 191 form->avatar_url = GURL(GetStringFromAttributes(attrs, "avatar_url")); | 187 form->avatar_url = GURL(GetStringFromAttributes(attrs, "avatar_url")); |
| 192 form->federation_url = GURL(GetStringFromAttributes(attrs, "federation_url")); | 188 form->federation_url = GURL(GetStringFromAttributes(attrs, "federation_url")); |
| 193 form->skip_zero_click = GetUintFromAttributes(attrs, "skip_zero_click"); | 189 form->skip_zero_click = GetUintFromAttributes(attrs, "skip_zero_click"); |
| 194 form->generation_upload_status = | 190 form->generation_upload_status = |
| 195 static_cast<PasswordForm::GenerationUploadStatus>( | 191 static_cast<PasswordForm::GenerationUploadStatus>( |
| 196 GetUintFromAttributes(attrs, "generation_upload_status")); | 192 GetUintFromAttributes(attrs, "generation_upload_status")); |
| 197 | 193 DeserializeFormDataFromBase64String( |
| 194 GetStringFromAttributes(attrs, "form_data"), &form->form_data); |
| 198 return form.Pass(); | 195 return form.Pass(); |
| 199 } | 196 } |
| 200 | 197 |
| 201 class LibsecretAttributesBuilder { | 198 class LibsecretAttributesBuilder { |
| 202 public: | 199 public: |
| 203 LibsecretAttributesBuilder(); | 200 LibsecretAttributesBuilder(); |
| 204 ~LibsecretAttributesBuilder(); | 201 ~LibsecretAttributesBuilder(); |
| 205 void Append(const std::string& name, const std::string& value); | 202 void Append(const std::string& name, const std::string& value); |
| 206 void Append(const std::string& name, int64 value); | 203 void Append(const std::string& name, int64 value); |
| 207 // GHashTable, its keys and values returned from Get() are destroyed in | 204 // GHashTable, its keys and values returned from Get() are destroyed in |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 ConvertFormList(found, &lookup_form, forms); | 406 ConvertFormList(found, &lookup_form, forms); |
| 410 } | 407 } |
| 411 | 408 |
| 412 bool NativeBackendLibsecret::RawAddLogin(const PasswordForm& form) { | 409 bool NativeBackendLibsecret::RawAddLogin(const PasswordForm& form) { |
| 413 int64 date_created = form.date_created.ToInternalValue(); | 410 int64 date_created = form.date_created.ToInternalValue(); |
| 414 // If we are asked to save a password with 0 date, use the current time. | 411 // If we are asked to save a password with 0 date, use the current time. |
| 415 // We don't want to actually save passwords as though on January 1, 1601. | 412 // We don't want to actually save passwords as though on January 1, 1601. |
| 416 if (!date_created) | 413 if (!date_created) |
| 417 date_created = base::Time::Now().ToInternalValue(); | 414 date_created = base::Time::Now().ToInternalValue(); |
| 418 int64 date_synced = form.date_synced.ToInternalValue(); | 415 int64 date_synced = form.date_synced.ToInternalValue(); |
| 416 std::string form_data; |
| 417 SerializeFormDataToBase64String(form.form_data, &form_data); |
| 419 GError* error = nullptr; | 418 GError* error = nullptr; |
| 420 secret_password_store_sync( | 419 secret_password_store_sync( |
| 421 &kLibsecretSchema, | 420 &kLibsecretSchema, |
| 422 nullptr, // Default collection. | 421 nullptr, // Default collection. |
| 423 form.origin.spec().c_str(), // Display name. | 422 form.origin.spec().c_str(), // Display name. |
| 424 UTF16ToUTF8(form.password_value).c_str(), | 423 UTF16ToUTF8(form.password_value).c_str(), |
| 425 nullptr, // no cancellable ojbect | 424 nullptr, // no cancellable ojbect |
| 426 &error, | 425 &error, |
| 427 "origin_url", form.origin.spec().c_str(), | 426 "origin_url", form.origin.spec().c_str(), |
| 428 "action_url", form.action.spec().c_str(), | 427 "action_url", form.action.spec().c_str(), |
| 429 "username_element", UTF16ToUTF8(form.username_element).c_str(), | 428 "username_element", UTF16ToUTF8(form.username_element).c_str(), |
| 430 "username_value", UTF16ToUTF8(form.username_value).c_str(), | 429 "username_value", UTF16ToUTF8(form.username_value).c_str(), |
| 431 "password_element", UTF16ToUTF8(form.password_element).c_str(), | 430 "password_element", UTF16ToUTF8(form.password_element).c_str(), |
| 432 "submit_element", UTF16ToUTF8(form.submit_element).c_str(), | 431 "submit_element", UTF16ToUTF8(form.submit_element).c_str(), |
| 433 "signon_realm", form.signon_realm.c_str(), | 432 "signon_realm", form.signon_realm.c_str(), |
| 434 "ssl_valid", form.ssl_valid, | 433 "ssl_valid", form.ssl_valid, |
| 435 "preferred", form.preferred, | 434 "preferred", form.preferred, |
| 436 "date_created", base::Int64ToString(date_created).c_str(), | 435 "date_created", base::Int64ToString(date_created).c_str(), |
| 437 "blacklisted_by_user", form.blacklisted_by_user, | 436 "blacklisted_by_user", form.blacklisted_by_user, |
| 438 "type", form.type, | 437 "type", form.type, |
| 439 "times_used", form.times_used, | 438 "times_used", form.times_used, |
| 440 "scheme", form.scheme, | 439 "scheme", form.scheme, |
| 441 "date_synced", base::Int64ToString(date_synced).c_str(), | 440 "date_synced", base::Int64ToString(date_synced).c_str(), |
| 442 "display_name", UTF16ToUTF8(form.display_name).c_str(), | 441 "display_name", UTF16ToUTF8(form.display_name).c_str(), |
| 443 "avatar_url", form.avatar_url.spec().c_str(), | 442 "avatar_url", form.avatar_url.spec().c_str(), |
| 444 "federation_url", form.federation_url.spec().c_str(), | 443 "federation_url", form.federation_url.spec().c_str(), |
| 445 "skip_zero_click", form.skip_zero_click, | 444 "skip_zero_click", form.skip_zero_click, |
| 446 "generation_upload_status", form.generation_upload_status, | 445 "generation_upload_status", form.generation_upload_status, |
| 446 "form_data", form_data.c_str(), |
| 447 "application", app_string_.c_str(), nullptr); | 447 "application", app_string_.c_str(), nullptr); |
| 448 | 448 |
| 449 if (error) { | 449 if (error) { |
| 450 VLOG(1) << "Libsecret add raw login failed: " << error->message; | 450 VLOG(1) << "Libsecret add raw login failed: " << error->message; |
| 451 g_error_free(error); | 451 g_error_free(error); |
| 452 return false; | 452 return false; |
| 453 } | 453 } |
| 454 return true; | 454 return true; |
| 455 } | 455 } |
| 456 | 456 |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 return true; | 609 return true; |
| 610 } | 610 } |
| 611 | 611 |
| 612 std::string NativeBackendLibsecret::GetProfileSpecificAppString( | 612 std::string NativeBackendLibsecret::GetProfileSpecificAppString( |
| 613 LocalProfileId id) { | 613 LocalProfileId id) { |
| 614 // Originally, the application string was always just "chrome" and used only | 614 // Originally, the application string was always just "chrome" and used only |
| 615 // so that we had *something* to search for since GNOME Keyring won't search | 615 // so that we had *something* to search for since GNOME Keyring won't search |
| 616 // for nothing. Now we use it to distinguish passwords for different profiles. | 616 // for nothing. Now we use it to distinguish passwords for different profiles. |
| 617 return base::StringPrintf("%s-%d", kLibsecretAppString, id); | 617 return base::StringPrintf("%s-%d", kLibsecretAppString, id); |
| 618 } | 618 } |
| OLD | NEW |