Commit d86263dc authored by isherman@chromium.org's avatar isherman@chromium.org

[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
parent ab792692
......@@ -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',
],
},
......
......@@ -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)
......
......@@ -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,
......
......@@ -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)
......
......@@ -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() ||
......
......@@ -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,
......
......@@ -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() {
......
......@@ -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();
......
......@@ -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);
......
......@@ -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,
......
// 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
// 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_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment