summaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorisherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-09 10:35:21 +0000
committerisherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-09 10:35:21 +0000
commitd86263dcd428c562d59d50a8e6545d0392ba13ff (patch)
treea2e204cf9d8205f47e9d8aa41de0f56c46a8be99 /components
parentab7926922b5fac4f6cc8f14b0fec878b84fe2f32 (diff)
downloadchromium_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')
-rw-r--r--components/autofill.gypi6
-rw-r--r--components/autofill/content/browser/autofill_driver_impl.cc3
-rw-r--r--components/autofill/content/browser/request_autocomplete_manager.cc4
-rw-r--r--components/autofill/content/common/autofill_messages.h3
-rw-r--r--components/autofill/content/renderer/autofill_agent.cc24
-rw-r--r--components/autofill/content/renderer/form_autofill_util.cc4
-rw-r--r--components/autofill/core/browser/autofill_external_delegate.cc6
-rw-r--r--components/autofill/core/browser/autofill_external_delegate.h5
-rw-r--r--components/autofill/core/browser/autofill_manager.cc42
-rw-r--r--components/autofill/core/browser/autofill_manager.h5
-rw-r--r--components/autofill/core/common/autofill_data_validation.cc115
-rw-r--r--components/autofill/core/common/autofill_data_validation.h45
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_