| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_gnome_x.h" | 5 #include "chrome/browser/password_manager/native_backend_gnome_x.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 #include <gnome-keyring.h> | 8 #include <gnome-keyring.h> |
| 9 | 9 |
| 10 #include <map> | 10 #include <map> |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #include "base/synchronization/waitable_event.h" | 23 #include "base/synchronization/waitable_event.h" |
| 24 #include "base/time/time.h" | 24 #include "base/time/time.h" |
| 25 #include "components/autofill/core/common/password_form.h" | 25 #include "components/autofill/core/common/password_form.h" |
| 26 #include "components/password_manager/core/browser/psl_matching_helper.h" | 26 #include "components/password_manager/core/browser/psl_matching_helper.h" |
| 27 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
| 28 | 28 |
| 29 using autofill::PasswordForm; | 29 using autofill::PasswordForm; |
| 30 using base::UTF8ToUTF16; | 30 using base::UTF8ToUTF16; |
| 31 using base::UTF16ToUTF8; | 31 using base::UTF16ToUTF8; |
| 32 using content::BrowserThread; | 32 using content::BrowserThread; |
| 33 using password_manager::PSLMatchingHelper; | |
| 34 | 33 |
| 35 #define GNOME_KEYRING_DEFINE_POINTER(name) \ | 34 #define GNOME_KEYRING_DEFINE_POINTER(name) \ |
| 36 typeof(&::gnome_keyring_##name) GnomeKeyringLoader::gnome_keyring_##name; | 35 typeof(&::gnome_keyring_##name) GnomeKeyringLoader::gnome_keyring_##name; |
| 37 GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_DEFINE_POINTER) | 36 GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_DEFINE_POINTER) |
| 38 #undef GNOME_KEYRING_DEFINE_POINTER | 37 #undef GNOME_KEYRING_DEFINE_POINTER |
| 39 | 38 |
| 40 bool GnomeKeyringLoader::keyring_loaded = false; | 39 bool GnomeKeyringLoader::keyring_loaded = false; |
| 41 | 40 |
| 42 #if defined(DLOPEN_GNOME_KEYRING) | 41 #if defined(DLOPEN_GNOME_KEYRING) |
| 43 | 42 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 form->avatar_url = GURL(string_attr_map["avatar_url"]); | 143 form->avatar_url = GURL(string_attr_map["avatar_url"]); |
| 145 form->federation_url = GURL(string_attr_map["federation_url"]); | 144 form->federation_url = GURL(string_attr_map["federation_url"]); |
| 146 form->is_zero_click = uint_attr_map["is_zero_click"]; | 145 form->is_zero_click = uint_attr_map["is_zero_click"]; |
| 147 | 146 |
| 148 return form.Pass(); | 147 return form.Pass(); |
| 149 } | 148 } |
| 150 | 149 |
| 151 // Parse all the results from the given GList into a PasswordFormList, and free | 150 // Parse all the results from the given GList into a PasswordFormList, and free |
| 152 // the GList. PasswordForms are allocated on the heap, and should be deleted by | 151 // the GList. PasswordForms are allocated on the heap, and should be deleted by |
| 153 // the consumer. If not NULL, |lookup_form| is used to filter out results -- | 152 // the consumer. If not NULL, |lookup_form| is used to filter out results -- |
| 154 // only credentials with signon realms passing the PSL matching (done by | 153 // only credentials with signon realms passing the PSL matching against |
| 155 // |helper|) against |lookup_form->signon_realm| will be kept. PSL matched | 154 // |lookup_form->signon_realm| will be kept. PSL matched results get their |
| 156 // results get their signon_realm, origin, and action rewritten to those of | 155 // signon_realm, origin, and action rewritten to those of |lookup_form_|, with |
| 157 // |lookup_form_|, with the original signon_realm saved into the result's | 156 // the original signon_realm saved into the result's original_signon_realm data |
| 158 // original_signon_realm data member. | 157 // member. |
| 159 void ConvertFormList(GList* found, | 158 void ConvertFormList(GList* found, |
| 160 const PasswordForm* lookup_form, | 159 const PasswordForm* lookup_form, |
| 161 const PSLMatchingHelper& helper, | |
| 162 NativeBackendGnome::PasswordFormList* forms) { | 160 NativeBackendGnome::PasswordFormList* forms) { |
| 163 PSLMatchingHelper::PSLDomainMatchMetric psl_domain_match_metric = | 161 password_manager::PSLDomainMatchMetric psl_domain_match_metric = |
| 164 PSLMatchingHelper::PSL_DOMAIN_MATCH_NONE; | 162 password_manager::PSL_DOMAIN_MATCH_NONE; |
| 165 for (GList* element = g_list_first(found); element != NULL; | 163 for (GList* element = g_list_first(found); element != NULL; |
| 166 element = g_list_next(element)) { | 164 element = g_list_next(element)) { |
| 167 GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data); | 165 GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data); |
| 168 GnomeKeyringAttributeList* attrs = data->attributes; | 166 GnomeKeyringAttributeList* attrs = data->attributes; |
| 169 | 167 |
| 170 scoped_ptr<PasswordForm> form(FormFromAttributes(attrs)); | 168 scoped_ptr<PasswordForm> form(FormFromAttributes(attrs)); |
| 171 if (form) { | 169 if (form) { |
| 172 if (lookup_form && form->signon_realm != lookup_form->signon_realm) { | 170 if (lookup_form && form->signon_realm != lookup_form->signon_realm) { |
| 173 // This is not an exact match, we try PSL matching. | 171 // This is not an exact match, we try PSL matching. |
| 174 if (lookup_form->scheme != PasswordForm::SCHEME_HTML || | 172 if (lookup_form->scheme != PasswordForm::SCHEME_HTML || |
| 175 form->scheme != PasswordForm::SCHEME_HTML || | 173 form->scheme != PasswordForm::SCHEME_HTML || |
| 176 !(PSLMatchingHelper::IsPublicSuffixDomainMatch( | 174 !(password_manager::IsPublicSuffixDomainMatch( |
| 177 lookup_form->signon_realm, form->signon_realm))) { | 175 lookup_form->signon_realm, form->signon_realm))) { |
| 178 continue; | 176 continue; |
| 179 } | 177 } |
| 180 psl_domain_match_metric = PSLMatchingHelper::PSL_DOMAIN_MATCH_FOUND; | 178 psl_domain_match_metric = password_manager::PSL_DOMAIN_MATCH_FOUND; |
| 181 form->original_signon_realm = form->signon_realm; | 179 form->original_signon_realm = form->signon_realm; |
| 182 form->signon_realm = lookup_form->signon_realm; | 180 form->signon_realm = lookup_form->signon_realm; |
| 183 form->origin = lookup_form->origin; | 181 form->origin = lookup_form->origin; |
| 184 form->action = lookup_form->action; | 182 form->action = lookup_form->action; |
| 185 } | 183 } |
| 186 if (data->secret) { | 184 if (data->secret) { |
| 187 form->password_value = UTF8ToUTF16(data->secret); | 185 form->password_value = UTF8ToUTF16(data->secret); |
| 188 } else { | 186 } else { |
| 189 LOG(WARNING) << "Unable to access password from list element!"; | 187 LOG(WARNING) << "Unable to access password from list element!"; |
| 190 } | 188 } |
| 191 forms->push_back(form.release()); | 189 forms->push_back(form.release()); |
| 192 } else { | 190 } else { |
| 193 LOG(WARNING) << "Could not initialize PasswordForm from attributes!"; | 191 LOG(WARNING) << "Could not initialize PasswordForm from attributes!"; |
| 194 } | 192 } |
| 195 } | 193 } |
| 196 if (lookup_form) { | 194 if (lookup_form) { |
| 195 const GURL signon_realm(lookup_form->signon_realm); |
| 196 std::string registered_domain = |
| 197 password_manager::GetRegistryControlledDomain(signon_realm); |
| 197 UMA_HISTOGRAM_ENUMERATION( | 198 UMA_HISTOGRAM_ENUMERATION( |
| 198 "PasswordManager.PslDomainMatchTriggering", | 199 "PasswordManager.PslDomainMatchTriggering", |
| 199 helper.IsMatchingEnabled() | 200 password_manager::ShouldPSLDomainMatchingApply(registered_domain) |
| 200 ? psl_domain_match_metric | 201 ? psl_domain_match_metric |
| 201 : PSLMatchingHelper::PSL_DOMAIN_MATCH_DISABLED, | 202 : password_manager::PSL_DOMAIN_MATCH_NOT_USED, |
| 202 PSLMatchingHelper::PSL_DOMAIN_MATCH_COUNT); | 203 password_manager::PSL_DOMAIN_MATCH_COUNT); |
| 203 } | 204 } |
| 204 } | 205 } |
| 205 | 206 |
| 206 // Schema is analagous to the fields in PasswordForm. | 207 // Schema is analagous to the fields in PasswordForm. |
| 207 // TODO(gcasto): Adding 'form_data' would be nice, but we would need to | 208 // TODO(gcasto): Adding 'form_data' would be nice, but we would need to |
| 208 // serialize in a way that is guaranteed to not have any embedded NULLs. Pickle | 209 // serialize in a way that is guaranteed to not have any embedded NULLs. Pickle |
| 209 // doesn't make this guarantee, so we just don't serialize this field. Since | 210 // doesn't make this guarantee, so we just don't serialize this field. Since |
| 210 // it's only used to crowd source data collection it doesn't matter that much | 211 // it's only used to crowd source data collection it doesn't matter that much |
| 211 // if it's not available on this platform. | 212 // if it's not available on this platform. |
| 212 const GnomeKeyringPasswordSchema kGnomeSchema = { | 213 const GnomeKeyringPasswordSchema kGnomeSchema = { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 GnomeKeyringResult result_; | 308 GnomeKeyringResult result_; |
| 308 NativeBackendGnome::PasswordFormList forms_; | 309 NativeBackendGnome::PasswordFormList forms_; |
| 309 // If the credential search is specified by a single form and needs to use PSL | 310 // If the credential search is specified by a single form and needs to use PSL |
| 310 // matching, then the specifying form is stored in |lookup_form_|. If PSL | 311 // matching, then the specifying form is stored in |lookup_form_|. If PSL |
| 311 // matching is used to find a result, then the results signon realm, origin | 312 // matching is used to find a result, then the results signon realm, origin |
| 312 // and action are stored are replaced by those of |lookup_form_|. | 313 // and action are stored are replaced by those of |lookup_form_|. |
| 313 // Additionally, |lookup_form_->signon_realm| is also used to narrow down the | 314 // Additionally, |lookup_form_->signon_realm| is also used to narrow down the |
| 314 // found logins to those which indeed PSL-match the look-up. And finally, | 315 // found logins to those which indeed PSL-match the look-up. And finally, |
| 315 // |lookup_form_| set to NULL means that PSL matching is not required. | 316 // |lookup_form_| set to NULL means that PSL matching is not required. |
| 316 scoped_ptr<PasswordForm> lookup_form_; | 317 scoped_ptr<PasswordForm> lookup_form_; |
| 317 const PSLMatchingHelper helper_; | |
| 318 }; | 318 }; |
| 319 | 319 |
| 320 void GKRMethod::AddLogin(const PasswordForm& form, const char* app_string) { | 320 void GKRMethod::AddLogin(const PasswordForm& form, const char* app_string) { |
| 321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 322 time_t date_created = form.date_created.ToTimeT(); | 322 time_t date_created = form.date_created.ToTimeT(); |
| 323 // If we are asked to save a password with 0 date, use the current time. | 323 // If we are asked to save a password with 0 date, use the current time. |
| 324 // We don't want to actually save passwords as though on January 1, 1970. | 324 // We don't want to actually save passwords as though on January 1, 1970. |
| 325 if (!date_created) | 325 if (!date_created) |
| 326 date_created = time(NULL); | 326 date_created = time(NULL); |
| 327 int64 date_synced = form.date_synced.ToInternalValue(); | 327 int64 date_synced = form.date_synced.ToInternalValue(); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 "signon_realm", form.signon_realm.c_str(), | 411 "signon_realm", form.signon_realm.c_str(), |
| 412 "application", app_string, | 412 "application", app_string, |
| 413 NULL); | 413 NULL); |
| 414 } | 414 } |
| 415 | 415 |
| 416 void GKRMethod::GetLogins(const PasswordForm& form, const char* app_string) { | 416 void GKRMethod::GetLogins(const PasswordForm& form, const char* app_string) { |
| 417 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 417 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 418 lookup_form_.reset(new PasswordForm(form)); | 418 lookup_form_.reset(new PasswordForm(form)); |
| 419 // Search GNOME Keyring for matching passwords. | 419 // Search GNOME Keyring for matching passwords. |
| 420 ScopedAttributeList attrs(gnome_keyring_attribute_list_new()); | 420 ScopedAttributeList attrs(gnome_keyring_attribute_list_new()); |
| 421 if (!helper_.ShouldPSLDomainMatchingApply( | 421 if (!password_manager::ShouldPSLDomainMatchingApply( |
| 422 PSLMatchingHelper::GetRegistryControlledDomain( | 422 password_manager::GetRegistryControlledDomain( |
| 423 GURL(form.signon_realm)))) { | 423 GURL(form.signon_realm)))) { |
| 424 AppendString(&attrs, "signon_realm", form.signon_realm); | 424 AppendString(&attrs, "signon_realm", form.signon_realm); |
| 425 } | 425 } |
| 426 AppendString(&attrs, "application", app_string); | 426 AppendString(&attrs, "application", app_string); |
| 427 gnome_keyring_find_items(GNOME_KEYRING_ITEM_GENERIC_SECRET, | 427 gnome_keyring_find_items(GNOME_KEYRING_ITEM_GENERIC_SECRET, |
| 428 attrs.get(), | 428 attrs.get(), |
| 429 OnOperationGetList, | 429 OnOperationGetList, |
| 430 /*data=*/this, | 430 /*data=*/this, |
| 431 /*destroy_data=*/NULL); | 431 /*destroy_data=*/NULL); |
| 432 } | 432 } |
| 433 | 433 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 method->event_.Signal(); | 508 method->event_.Signal(); |
| 509 } | 509 } |
| 510 | 510 |
| 511 // static | 511 // static |
| 512 void GKRMethod::OnOperationGetList(GnomeKeyringResult result, GList* list, | 512 void GKRMethod::OnOperationGetList(GnomeKeyringResult result, GList* list, |
| 513 gpointer data) { | 513 gpointer data) { |
| 514 GKRMethod* method = static_cast<GKRMethod*>(data); | 514 GKRMethod* method = static_cast<GKRMethod*>(data); |
| 515 method->result_ = result; | 515 method->result_ = result; |
| 516 method->forms_.clear(); | 516 method->forms_.clear(); |
| 517 // |list| will be freed after this callback returns, so convert it now. | 517 // |list| will be freed after this callback returns, so convert it now. |
| 518 ConvertFormList( | 518 ConvertFormList(list, method->lookup_form_.get(), &method->forms_); |
| 519 list, method->lookup_form_.get(), method->helper_, &method->forms_); | |
| 520 method->lookup_form_.reset(NULL); | 519 method->lookup_form_.reset(NULL); |
| 521 method->event_.Signal(); | 520 method->event_.Signal(); |
| 522 } | 521 } |
| 523 | 522 |
| 524 } // namespace | 523 } // namespace |
| 525 | 524 |
| 526 NativeBackendGnome::NativeBackendGnome(LocalProfileId id) | 525 NativeBackendGnome::NativeBackendGnome(LocalProfileId id) |
| 527 : profile_id_(id) { | 526 : profile_id_(id) { |
| 528 app_string_ = GetProfileSpecificAppString(); | 527 app_string_ = GetProfileSpecificAppString(); |
| 529 } | 528 } |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 786 } | 785 } |
| 787 return ok; | 786 return ok; |
| 788 } | 787 } |
| 789 | 788 |
| 790 std::string NativeBackendGnome::GetProfileSpecificAppString() const { | 789 std::string NativeBackendGnome::GetProfileSpecificAppString() const { |
| 791 // Originally, the application string was always just "chrome" and used only | 790 // Originally, the application string was always just "chrome" and used only |
| 792 // so that we had *something* to search for since GNOME Keyring won't search | 791 // so that we had *something* to search for since GNOME Keyring won't search |
| 793 // for nothing. Now we use it to distinguish passwords for different profiles. | 792 // for nothing. Now we use it to distinguish passwords for different profiles. |
| 794 return base::StringPrintf("%s-%d", kGnomeKeyringAppString, profile_id_); | 793 return base::StringPrintf("%s-%d", kGnomeKeyringAppString, profile_id_); |
| 795 } | 794 } |
| OLD | NEW |