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 |