diff options
author | isherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-09 10:35:21 +0000 |
---|---|---|
committer | isherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-09 10:35:21 +0000 |
commit | d86263dcd428c562d59d50a8e6545d0392ba13ff (patch) | |
tree | a2e204cf9d8205f47e9d8aa41de0f56c46a8be99 /components | |
parent | ab7926922b5fac4f6cc8f14b0fec878b84fe2f32 (diff) | |
download | chromium_src-d86263dcd428c562d59d50a8e6545d0392ba13ff.zip chromium_src-d86263dcd428c562d59d50a8e6545d0392ba13ff.tar.gz chromium_src-d86263dcd428c562d59d50a8e6545d0392ba13ff.tar.bz2 |
[Autofill] Sanitize all data that comes in over IPC.
BUG=329978
TEST=none
R=palmer@chromium.org
Review URL: https://codereview.chromium.org/98753005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243833 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components')
12 files changed, 217 insertions, 45 deletions
diff --git a/components/autofill.gypi b/components/autofill.gypi index 9bbe26e..255288a 100644 --- a/components/autofill.gypi +++ b/components/autofill.gypi @@ -22,7 +22,7 @@ 'autofill/core/browser/autofill_regex_constants.cc.utf8'], }], }, - + { 'target_name': 'autofill_core_common', 'type': 'static_library', @@ -52,6 +52,8 @@ 'autofill/core/browser/android/personal_data_manager_android.cc', 'autofill/core/common/autofill_constants.cc', 'autofill/core/common/autofill_constants.h', + 'autofill/core/common/autofill_data_validation.cc', + 'autofill/core/common/autofill_data_validation.h', 'autofill/core/common/autofill_pref_names.cc', 'autofill/core/common/autofill_pref_names.h', 'autofill/core/common/autofill_switches.cc', @@ -258,9 +260,9 @@ '..', ], 'sources': [ - 'autofill/content/common/autofill_messages.h', 'autofill/content/common/autofill_message_generator.cc', 'autofill/content/common/autofill_message_generator.h', + 'autofill/content/common/autofill_messages.h', 'autofill/content/common/autofill_param_traits_macros.h', ], }, diff --git a/components/autofill/content/browser/autofill_driver_impl.cc b/components/autofill/content/browser/autofill_driver_impl.cc index fcc825f..b6d7cbc 100644 --- a/components/autofill/content/browser/autofill_driver_impl.cc +++ b/components/autofill/content/browser/autofill_driver_impl.cc @@ -185,9 +185,6 @@ bool AutofillDriverImpl::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_FORWARD(AutofillHostMsg_QueryFormFieldAutofill, autofill_manager_.get(), AutofillManager::OnQueryFormFieldAutofill) - IPC_MESSAGE_FORWARD(AutofillHostMsg_ShowAutofillDialog, - autofill_manager_.get(), - AutofillManager::OnShowAutofillDialog) IPC_MESSAGE_FORWARD(AutofillHostMsg_FillAutofillFormData, autofill_manager_.get(), AutofillManager::OnFillAutofillFormData) diff --git a/components/autofill/content/browser/request_autocomplete_manager.cc b/components/autofill/content/browser/request_autocomplete_manager.cc index f48610f..79b0121 100644 --- a/components/autofill/content/browser/request_autocomplete_manager.cc +++ b/components/autofill/content/browser/request_autocomplete_manager.cc @@ -7,6 +7,7 @@ #include "components/autofill/content/browser/autofill_driver_impl.h" #include "components/autofill/content/common/autofill_messages.h" #include "components/autofill/core/browser/form_structure.h" +#include "components/autofill/core/common/autofill_data_validation.h" #include "components/autofill/core/common/form_data.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" @@ -26,6 +27,9 @@ RequestAutocompleteManager::~RequestAutocompleteManager() {} void RequestAutocompleteManager::OnRequestAutocomplete( const FormData& form, const GURL& frame_url) { + if (!IsValidFormData(form)) + return; + if (!autofill_driver_->autofill_manager()->IsAutofillEnabled()) { ReturnAutocompleteResult( blink::WebFormElement::AutocompleteResultErrorDisabled, diff --git a/components/autofill/content/common/autofill_messages.h b/components/autofill/content/common/autofill_messages.h index 4e38832..2e6e960 100644 --- a/components/autofill/content/common/autofill_messages.h +++ b/components/autofill/content/common/autofill_messages.h @@ -226,9 +226,6 @@ IPC_MESSAGE_ROUTED2(AutofillHostMsg_RequestAutocomplete, autofill::FormData /* form_data */, GURL /* frame_url */) -// Instructs the browser to show the Autofill dialog. -IPC_MESSAGE_ROUTED0(AutofillHostMsg_ShowAutofillDialog) - // Send when a text field is done editing. IPC_MESSAGE_ROUTED0(AutofillHostMsg_DidEndTextFieldEditing) diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index 11ac21d..45970d8 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc @@ -16,6 +16,7 @@ #include "components/autofill/content/renderer/page_click_tracker.h" #include "components/autofill/content/renderer/password_autofill_agent.h" #include "components/autofill/core/common/autofill_constants.h" +#include "components/autofill/core/common/autofill_data_validation.h" #include "components/autofill/core/common/autofill_switches.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/form_data_predictions.h" @@ -54,16 +55,9 @@ using blink::WebNodeCollection; using blink::WebOptionElement; using blink::WebString; -namespace { - -// The size above which we stop triggering autofill for an input text field -// (so to avoid sending long strings through IPC). -const size_t kMaximumTextSizeForAutofill = 1000; - -// The maximum number of data list elements to send to the browser process -// via IPC (to prevent long IPC messages). -const size_t kMaximumDataListSizeForAutofill = 30; +namespace autofill { +namespace { // Gets all the data list values (with corresponding label) for the given // element. @@ -105,13 +99,13 @@ void GetDataListSuggestions(const blink::WebInputElement& element, // don't send too much data through the IPC. void TrimStringVectorForIPC(std::vector<base::string16>* strings) { // Limit the size of the vector. - if (strings->size() > kMaximumDataListSizeForAutofill) - strings->resize(kMaximumDataListSizeForAutofill); + if (strings->size() > kMaxListSize) + strings->resize(kMaxListSize); // Limit the size of the strings in the vector. for (size_t i = 0; i < strings->size(); ++i) { - if ((*strings)[i].length() > kMaximumTextSizeForAutofill) - (*strings)[i].resize(kMaximumTextSizeForAutofill); + if ((*strings)[i].length() > kMaxDataLength) + (*strings)[i].resize(kMaxDataLength); } } @@ -125,8 +119,6 @@ gfx::RectF GetScaledBoundingBox(float scale, WebInputElement* element) { } // namespace -namespace autofill { - AutofillAgent::AutofillAgent(content::RenderView* render_view, PasswordAutofillAgent* password_autofill_agent) : content::RenderViewObserver(render_view), @@ -512,7 +504,7 @@ void AutofillAgent::ShowSuggestions(const WebInputElement& element, // criteria are not met. WebString value = element.editingValue(); if (!datalist_only && - (value.length() > kMaximumTextSizeForAutofill || + (value.length() > kMaxDataLength || (!autofill_on_empty_values && value.isEmpty()) || (requires_caret_at_end && (element.selectionStart() != element.selectionEnd() || diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc index 42b340e..9876748 100644 --- a/components/autofill/content/renderer/form_autofill_util.cc +++ b/components/autofill/content/renderer/form_autofill_util.cc @@ -12,6 +12,7 @@ #include "base/metrics/field_trial.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/common/autofill_data_validation.h" #include "components/autofill/core/common/autofill_switches.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/form_field_data.h" @@ -51,9 +52,6 @@ using blink::WebVector; namespace autofill { namespace { -// The maximum length allowed for form data. -const size_t kMaxDataLength = 1024; - // A bit field mask for FillForm functions to not fill some fields. enum FieldFilterMask { FILTER_NONE = 0, diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc index 7bbdeec..c436756 100644 --- a/components/autofill/core/browser/autofill_external_delegate.cc +++ b/components/autofill/core/browser/autofill_external_delegate.cc @@ -176,7 +176,7 @@ void AutofillExternalDelegate::DidAcceptSuggestion(const base::string16& value, int identifier) { if (identifier == WebAutofillClient::MenuItemIDAutofillOptions) { // User selected 'Autofill Options'. - autofill_manager_->OnShowAutofillDialog(); + autofill_manager_->ShowAutofillSettings(); } else if (identifier == WebAutofillClient::MenuItemIDClearForm) { // User selected 'Clear form'. autofill_driver_->RendererShouldClearFilledForm(); @@ -223,9 +223,9 @@ void AutofillExternalDelegate::Reset() { } void AutofillExternalDelegate::AddPasswordFormMapping( - const FormFieldData& form, + const FormFieldData& username_field, const PasswordFormFillData& fill_data) { - password_autofill_manager_.AddPasswordFormMapping(form, fill_data); + password_autofill_manager_.AddPasswordFormMapping(username_field, fill_data); } base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() { diff --git a/components/autofill/core/browser/autofill_external_delegate.h b/components/autofill/core/browser/autofill_external_delegate.h index 6f3f4d7..e399eb5 100644 --- a/components/autofill/core/browser/autofill_external_delegate.h +++ b/components/autofill/core/browser/autofill_external_delegate.h @@ -93,9 +93,8 @@ class AutofillExternalDelegate void Reset(); // Inform the Password Manager of a filled form. - void AddPasswordFormMapping( - const FormFieldData& form, - const PasswordFormFillData& fill_data); + void AddPasswordFormMapping(const FormFieldData& username_field, + const PasswordFormFillData& fill_data); protected: base::WeakPtr<AutofillExternalDelegate> GetWeakPtr(); diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index edaa35e..5aab9dc 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc @@ -35,6 +35,7 @@ #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/phone_number.h" #include "components/autofill/core/browser/phone_number_i18n.h" +#include "components/autofill/core/common/autofill_data_validation.h" #include "components/autofill/core/common/autofill_pref_names.h" #include "components/autofill/core/common/autofill_switches.h" #include "components/autofill/core/common/form_data.h" @@ -230,8 +231,15 @@ void AutofillManager::SetExternalDelegate(AutofillExternalDelegate* delegate) { autocomplete_history_manager_->SetExternalDelegate(delegate); } +void AutofillManager::ShowAutofillSettings() { + manager_delegate_->ShowAutofillSettings(); +} + bool AutofillManager::OnFormSubmitted(const FormData& form, const TimeTicks& timestamp) { + if (!IsValidFormData(form)) + return false; + // Let Autocomplete know as well. autocomplete_history_manager_->OnFormSubmitted(form); @@ -301,6 +309,9 @@ bool AutofillManager::OnFormSubmitted(const FormData& form, void AutofillManager::OnFormsSeen(const std::vector<FormData>& forms, const TimeTicks& timestamp, autofill::FormsSeenState state) { + if (!IsValidFormDataVector(forms)) + return; + bool is_post_document_load = state == autofill::DYNAMIC_FORMS_SEEN; // If new forms were added dynamically, treat as a new page. if (is_post_document_load) @@ -325,6 +336,9 @@ void AutofillManager::OnFormsSeen(const std::vector<FormData>& forms, void AutofillManager::OnTextFieldDidChange(const FormData& form, const FormFieldData& field, const TimeTicks& timestamp) { + if (!IsValidFormData(form) || !IsValidFormFieldData(field)) + return; + FormStructure* form_structure = NULL; AutofillField* autofill_field = NULL; if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field)) @@ -355,6 +369,9 @@ void AutofillManager::OnQueryFormFieldAutofill(int query_id, const FormFieldData& field, const gfx::RectF& bounding_box, bool display_warning) { + if (!IsValidFormData(form) || !IsValidFormFieldData(field)) + return; + std::vector<base::string16> values; std::vector<base::string16> labels; std::vector<base::string16> icons; @@ -442,6 +459,9 @@ void AutofillManager::OnFillAutofillFormData(int query_id, const FormData& form, const FormFieldData& field, int unique_id) { + if (!IsValidFormData(form) || !IsValidFormFieldData(field)) + return; + const AutofillDataModel* data_model = NULL; size_t variant = 0; FormStructure* form_structure = NULL; @@ -522,10 +542,6 @@ void AutofillManager::OnFillAutofillFormData(int query_id, driver_->SendFormDataToRenderer(query_id, result); } -void AutofillManager::OnShowAutofillDialog() { - manager_delegate_->ShowAutofillSettings(); -} - void AutofillManager::OnDidPreviewAutofillFormData() { if (test_delegate_) test_delegate_->DidPreviewFormData(); @@ -599,9 +615,13 @@ void AutofillManager::SetTestDelegate( } void AutofillManager::OnAddPasswordFormMapping( - const FormFieldData& form, + const FormFieldData& username_field, const PasswordFormFillData& fill_data) { - external_delegate_->AddPasswordFormMapping(form, fill_data); + if (!IsValidFormFieldData(username_field) || + !IsValidPasswordFormFillData(fill_data)) + return; + + external_delegate_->AddPasswordFormMapping(username_field, fill_data); } void AutofillManager::OnShowPasswordSuggestions( @@ -609,8 +629,9 @@ void AutofillManager::OnShowPasswordSuggestions( const gfx::RectF& bounds, const std::vector<base::string16>& suggestions, const std::vector<base::string16>& realms) { - // Bail if the IPC message is corrupt. - if (suggestions.size() != realms.size()) + if (!IsValidString16Vector(suggestions) || + !IsValidString16Vector(realms) || + suggestions.size() != realms.size()) return; external_delegate_->OnShowPasswordSuggestions(suggestions, @@ -621,8 +642,9 @@ void AutofillManager::OnShowPasswordSuggestions( void AutofillManager::OnSetDataList(const std::vector<base::string16>& values, const std::vector<base::string16>& labels) { - // Bail if the IPC message is corrupt. - if (values.size() != labels.size()) + if (!IsValidString16Vector(values) || + !IsValidString16Vector(labels) || + values.size() != labels.size()) return; external_delegate_->SetCurrentDataListValues(values, labels); diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h index f1ce426..1ebe952 100644 --- a/components/autofill/core/browser/autofill_manager.h +++ b/components/autofill/core/browser/autofill_manager.h @@ -84,6 +84,8 @@ class AutofillManager : public AutofillDownloadManager::Observer { // Sets an external delegate. void SetExternalDelegate(AutofillExternalDelegate* delegate); + void ShowAutofillSettings(); + // Called from our external delegate so they cannot be private. virtual void OnFillAutofillFormData(int query_id, const FormData& form, @@ -91,7 +93,6 @@ class AutofillManager : public AutofillDownloadManager::Observer { int unique_id); void OnDidShowAutofillSuggestions(bool is_new_popup); void OnDidFillAutofillFormData(const base::TimeTicks& timestamp); - void OnShowAutofillDialog(); void OnDidPreviewAutofillFormData(); // Remove the credit card or Autofill profile that matches |unique_id| @@ -140,7 +141,7 @@ class AutofillManager : public AutofillDownloadManager::Observer { void OnDidEndTextFieldEditing(); void OnHideAutofillUI(); void OnAddPasswordFormMapping( - const FormFieldData& form, + const FormFieldData& username_field, const PasswordFormFillData& fill_data); void OnShowPasswordSuggestions( const FormFieldData& field, diff --git a/components/autofill/core/common/autofill_data_validation.cc b/components/autofill/core/common/autofill_data_validation.cc new file mode 100644 index 0000000..3a456e2 --- /dev/null +++ b/components/autofill/core/common/autofill_data_validation.cc @@ -0,0 +1,115 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/common/autofill_data_validation.h" + +#include "components/autofill/core/common/form_data.h" +#include "components/autofill/core/common/form_field_data.h" +#include "components/autofill/core/common/password_form_fill_data.h" +#include "url/gurl.h" + +namespace autofill { + +const size_t kMaxDataLength = 1024; + +// Allow enough space for all countries (roughly 300 distinct values) and all +// timezones (roughly 400 distinct values), plus some extra wiggle room. +const size_t kMaxListSize = 512; + +bool IsValidString(const std::string& str) { + return str.size() <= kMaxDataLength; +} + +bool IsValidString16(const base::string16& str) { + return str.size() <= kMaxDataLength; +} + +bool IsValidGURL(const GURL& url) { + return url.is_empty() || url.is_valid(); +} + +bool IsValidFormFieldData(const FormFieldData& field) { + return + IsValidString16(field.label) && + IsValidString16(field.name) && + IsValidString16(field.value) && + IsValidString(field.form_control_type) && + IsValidString(field.autocomplete_attribute) && + IsValidString16Vector(field.option_values) && + IsValidString16Vector(field.option_contents); +} + +bool IsValidFormData(const FormData& form) { + if (!IsValidString16(form.name) || + !IsValidString16(form.method) || + !IsValidGURL(form.origin) || + !IsValidGURL(form.action)) + return false; + + if (form.fields.size() > kMaxListSize) + return false; + + for (std::vector<FormFieldData>::const_iterator it = form.fields.begin(); + it != form.fields.end(); ++it) { + if (!IsValidFormFieldData(*it)) + return false; + } + + return true; +} + +bool IsValidPasswordFormFillData(const PasswordFormFillData& form) { + if (!IsValidFormData(form.basic_data) || + !IsValidString(form.preferred_realm)) + return false; + + for (PasswordFormFillData::LoginCollection::const_iterator it = + form.additional_logins.begin(); + it != form.additional_logins.end(); ++it) { + if (!IsValidString16(it->first) || + !IsValidString16(it->second.password) || + !IsValidString(it->second.realm)) + return false; + } + + for (PasswordFormFillData::UsernamesCollection::const_iterator it = + form.other_possible_usernames.begin(); + it != form.other_possible_usernames.end(); ++it) { + if (!IsValidString16(it->first.username) || + !IsValidString16(it->first.password) || + !IsValidString(it->first.realm) || + !IsValidString16Vector(it->second)) + return false; + } + + return true; +} + +bool IsValidString16Vector(const std::vector<base::string16>& v) { + if (v.size() > kMaxListSize) + return false; + + for (std::vector<base::string16>::const_iterator it = v.begin(); + it != v.end(); ++it) { + if (!IsValidString16(*it)) + return false; + } + + return true; +} + +bool IsValidFormDataVector(const std::vector<FormData>& v) { + if (v.size() > kMaxListSize) + return false; + + for (std::vector<FormData>::const_iterator it = v.begin(); it != v.end(); + ++it) { + if (!IsValidFormData(*it)) + return false; + } + + return true; +} + +} // namespace autofill diff --git a/components/autofill/core/common/autofill_data_validation.h b/components/autofill/core/common/autofill_data_validation.h new file mode 100644 index 0000000..fd5e521 --- /dev/null +++ b/components/autofill/core/common/autofill_data_validation.h @@ -0,0 +1,45 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_DATA_VALIDATION_H_ +#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_DATA_VALIDATION_H_ + +#include <string> +#include <vector> + +#include "base/strings/string16.h" + +class GURL; + +namespace autofill { + +struct FormData; +struct FormFieldData; +struct PasswordFormFillData; + +// Constants to enforce data size caps, so as to avoid sending overly large +// messages over IPC or trying to act on potentialy corrupted data within the +// browser process: + +// The maximum string size supported by Autofill. +extern const size_t kMaxDataLength; + +// The maximum list size supported by Autofill. +extern const size_t kMaxListSize; + +// Functions to verify whether the objects passed to them satisfy basic sanity +// checks, including being capped to the maximums defined by the constants +// above. +bool IsValidString(const std::string& str); +bool IsValidString16(const base::string16& str); +bool IsValidGURL(const GURL& url); +bool IsValidFormFieldData(const FormFieldData& field); +bool IsValidFormData(const FormData& form); +bool IsValidPasswordFormFillData(const PasswordFormFillData& form); +bool IsValidString16Vector(const std::vector<base::string16>& v); +bool IsValidFormDataVector(const std::vector<FormData>& v); + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_DATA_VALIDATION_H_ |