Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1021)

Unified Diff: components/autofill/core/common/save_password_progress_logger.cc

Issue 235623002: Password manager internals page: Improve security (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: innerHTML -> innerText Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/autofill/core/common/save_password_progress_logger.cc
diff --git a/components/autofill/core/common/save_password_progress_logger.cc b/components/autofill/core/common/save_password_progress_logger.cc
index cdb8dd7a177e97f1542db30a714749683b3094f1..397b58762e44bb885cc06af7781a5f84560dc085 100644
--- a/components/autofill/core/common/save_password_progress_logger.cc
+++ b/components/autofill/core/common/save_password_progress_logger.cc
@@ -4,9 +4,15 @@
#include "components/autofill/core/common/save_password_progress_logger.h"
+#include <algorithm>
+
#include "base/json/json_writer.h"
#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/numerics/safe_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "components/autofill/core/common/password_form.h"
@@ -20,6 +26,42 @@ namespace autofill {
namespace {
+// These messages can be used as dictionary keys. Do not use '.' in them.
+const char* const kIDsToMessages[] = {
+ "Decision: ASK the user", // STRING_DECISION_ASK
+ "Decision: DROP the password", // STRING_DECISION_DROP,
+ "Decision: SAVE the password", // STRING_DECISION_SAVE,
+ "Form method", // STRING_METHOD,
+ "GET", // STRING_METHOD_GET,
+ "POST", // STRING_METHOD_POST,
+ "(empty)", // STRING_METHOD_EMPTY,
+ "(other)", // STRING_OTHER,
+ "HTML", // STRING_SCHEME_HTML,
+ "Basic", // STRING_SCHEME_BASIC,
+ "Digest", // STRING_SCHEME_DIGEST,
+ "Scheme", // STRING_SCHEME_MESSAGE,
+ "Signon realm", // STRING_SIGNON_REALM,
+ "Original signon realm", // STRING_ORIGINAL_SIGNON_REALM,
+ "Origin", // STRING_ORIGIN,
+ "Action", // STRING_ACTION,
+ "Username element", // STRING_USERNAME_ELEMENT,
+ "Password element", // STRING_PASSWORD_ELEMENT,
+ "Password autocomplete set", // STRING_PASSWORD_AUTOCOMPLETE_SET,
+ "Old password element", // STRING_OLD_PASSWORD_ELEMENT,
+ "SSL valid", // STRING_SSL_VALID,
+ "Password generated", // STRING_PASSWORD_GENERATED,
+ "Times used", // STRING_TIMES_USED,
+ "Use additional authentication", // STRING_USE_ADDITIONAL_AUTHENTICATION,
+ "PSL match", // STRING_PSL_MATCH,
+ "Form name or ID", // STRING_NAME_OR_ID,
+ "Message", // STRING_MESSAGE,
+ "INVALID", // STRING_INVALID,
+};
+
+COMPILE_ASSERT(SavePasswordProgressLogger::StringID::STRING_MAX + 1 ==
+ arraysize(kIDsToMessages),
+ IDsToMessagesMappingIsOutOfDate);
+
// Removes privacy sensitive parts of |url| (currently all but host and scheme).
std::string ScrubURL(const GURL& url) {
if (url.is_valid())
@@ -27,112 +69,302 @@ std::string ScrubURL(const GURL& url) {
return std::string();
}
-std::string FormSchemeToString(PasswordForm::Scheme scheme) {
+// Returns true for all characters which we don't want to see in the logged IDs
+// or names of HTML elements.
+bool IsUnwantedInElementID (char c) {
+ return !IsAsciiAlpha(c) && !IsAsciiDigit(c);
+}
+
+// Replaces all characters satisfying IsUnwantedInElementID by a ' ', and turns
+// all characters to lowercase. This damages some valid HTML element IDs or
+// names, but it is likely that it will be still possible to match the scrubbed
+// string to the original ID or name in the HTML doc. That's good enough for the
+// logging purposes, and provides some security benefits.
+std::string ScrubElementID(std::string element_id) {
+ std::replace_if(
+ element_id.begin(), element_id.end(), IsUnwantedInElementID, ' ');
+ return StringToLowerASCII(element_id);
+}
+
+SavePasswordProgressLogger::StringID FormSchemeToStringID(
+ PasswordForm::Scheme scheme) {
switch (scheme) {
case PasswordForm::SCHEME_HTML:
- return "HTML";
+ return SavePasswordProgressLogger::STRING_SCHEME_HTML;
case PasswordForm::SCHEME_BASIC:
- return "BASIC";
+ return SavePasswordProgressLogger::STRING_SCHEME_BASIC;
case PasswordForm::SCHEME_DIGEST:
- return "DIGEST";
+ return SavePasswordProgressLogger::STRING_SCHEME_DIGEST;
case PasswordForm::SCHEME_OTHER:
- return "OTHER";
+ return SavePasswordProgressLogger::STRING_OTHER;
}
NOTREACHED(); // Win compilers don't believe this is unreachable.
- return std::string();
+ return SavePasswordProgressLogger::StringID::STRING_INVALID;
+}
+
+SavePasswordProgressLogger::StringID FormMethodToStringID(
+ const std::string& method) {
+ std::string method_processed;
+ base::TrimWhitespaceASCII(
+ StringToLowerASCII(method), base::TRIM_ALL, &method_processed);
+ if (method_processed.empty())
+ return SavePasswordProgressLogger::STRING_METHOD_EMPTY;
+ else if (method_processed == "get")
+ return SavePasswordProgressLogger::STRING_METHOD_GET;
+ else if (method_processed == "post")
+ return SavePasswordProgressLogger::STRING_METHOD_POST;
+ else
+ return SavePasswordProgressLogger::STRING_OTHER;
}
-StringValue DecisionToStringValue(
- SavePasswordProgressLogger::Decision decision) {
- switch (decision) {
- case SavePasswordProgressLogger::DECISION_SAVE:
- return StringValue("SAVE the password");
- case SavePasswordProgressLogger::DECISION_ASK:
- return StringValue("ASK the user whether to save the password");
- case SavePasswordProgressLogger::DECISION_DROP:
- return StringValue("DROP the password");
+// Interprets |log|, sanitizes its value if needed, and returns it as
+// base::Value. Does not work on LOG_TYPE_LABEL logs.
+scoped_ptr<Value> GetValueFromStructuredLog(
+ const SavePasswordProgressLogger::StructuredLog& log) {
+ switch (log.log_type) {
+ case SavePasswordProgressLogger::StructuredLog::LOG_TYPE_LABEL:
+ NOTREACHED();
+ return scoped_ptr<Value>();
+ case SavePasswordProgressLogger::StructuredLog::LOG_TYPE_GURL:
+ return scoped_ptr<Value>(Value::CreateStringValue(ScrubURL(log.url)));
+ case SavePasswordProgressLogger::StructuredLog::LOG_TYPE_MESSAGE:
+ return scoped_ptr<Value>(
+ Value::CreateStringValue(kIDsToMessages[log.message]));
+ case SavePasswordProgressLogger::StructuredLog::LOG_TYPE_NUMBER:
+ return scoped_ptr<Value>(Value::CreateIntegerValue(log.number));
+ case SavePasswordProgressLogger::StructuredLog::LOG_TYPE_BOOL:
+ return scoped_ptr<Value>(Value::CreateBooleanValue(log.truth_value));
+ case SavePasswordProgressLogger::StructuredLog::LOG_TYPE_ELEMENT_ID:
+ return scoped_ptr<Value>(
+ Value::CreateStringValue(ScrubElementID(log.element_id)));
}
NOTREACHED(); // Win compilers don't believe this is unreachable.
- return StringValue(std::string());
+ return scoped_ptr<Value>();
}
} // namespace
-SavePasswordProgressLogger::SavePasswordProgressLogger() {}
+SavePasswordProgressLogger::StructuredLog::StructuredLog()
+ : log_type(LOG_TYPE_LABEL),
+ label(STRING_INVALID),
+ message(STRING_INVALID),
+ number(0),
+ truth_value(false) {
+}
-SavePasswordProgressLogger::~SavePasswordProgressLogger() {}
+SavePasswordProgressLogger::StructuredLog::StructuredLog(
+ SavePasswordProgressLogger::StringID label)
+ : log_type(LOG_TYPE_LABEL),
+ label(label),
+ message(STRING_INVALID),
+ number(0),
+ truth_value(false) {
+}
-void SavePasswordProgressLogger::LogPasswordForm(const std::string& message,
- const PasswordForm& form) {
- DictionaryValue log;
- // Do not use the "<<" operator for PasswordForms, because it also prints
- // passwords. Also, that operator is only for testing.
- log.SetString("scheme", FormSchemeToString(form.scheme));
- log.SetString("signon realm", ScrubURL(GURL(form.signon_realm)));
- log.SetString("original signon realm",
- ScrubURL(GURL(form.original_signon_realm)));
- log.SetString("origin", ScrubURL(form.origin));
- log.SetString("action", ScrubURL(form.action));
- log.SetString("username element", form.username_element);
- log.SetString("password element", form.password_element);
- log.SetBoolean("password autocomplete set", form.password_autocomplete_set);
- log.SetString("old password element", form.old_password_element);
- log.SetBoolean("ssl valid", form.ssl_valid);
- log.SetBoolean("password generated",
- form.type == PasswordForm::TYPE_GENERATED);
- log.SetInteger("times used", form.times_used);
- log.SetBoolean("use additional authentication",
- form.use_additional_authentication);
- log.SetBoolean("is PSL match", form.IsPublicSuffixMatch());
- LogValue(message, log);
+SavePasswordProgressLogger::StructuredLog::StructuredLog(StringID label,
+ GURL url)
+ : log_type(LOG_TYPE_GURL),
+ label(label),
+ url(url),
+ message(STRING_INVALID),
+ number(0),
+ truth_value(false) {
}
-void SavePasswordProgressLogger::LogHTMLForm(const std::string& message,
- const std::string& name_or_id,
- const std::string& method,
- const GURL& action) {
- DictionaryValue log;
- log.SetString("name_or_id", name_or_id);
- log.SetString("method", method);
- log.SetString("action", ScrubURL(action));
- LogValue(message, log);
+SavePasswordProgressLogger::StructuredLog::StructuredLog(StringID label,
+ StringID message)
+ : log_type(LOG_TYPE_MESSAGE),
+ label(label),
+ message(message),
+ number(0),
+ truth_value(false) {
}
-void SavePasswordProgressLogger::LogURL(const std::string& message,
- const GURL& url) {
- LogValue(message, StringValue(ScrubURL(url)));
+SavePasswordProgressLogger::StructuredLog::StructuredLog(StringID label,
+ int number)
+ : log_type(LOG_TYPE_NUMBER),
+ label(label),
+ message(STRING_INVALID),
+ number(number),
+ truth_value(false) {
}
-void SavePasswordProgressLogger::LogBoolean(const std::string& message,
- bool value) {
- LogValue(message, FundamentalValue(value));
+SavePasswordProgressLogger::StructuredLog::StructuredLog(StringID label,
+ bool truth_value)
+ : log_type(LOG_TYPE_BOOL),
+ label(label),
+ message(STRING_INVALID),
+ number(0),
+ truth_value(truth_value) {
}
-void SavePasswordProgressLogger::LogNumber(const std::string& message,
- int value) {
- LogValue(message, FundamentalValue(value));
+SavePasswordProgressLogger::StructuredLog::StructuredLog(
+ StringID label,
+ const base::string16& element_id)
+ : log_type(LOG_TYPE_ELEMENT_ID),
+ label(label),
+ message(STRING_INVALID),
+ number(0),
+ truth_value(false),
+ element_id(UTF16ToUTF8(element_id)) {
}
-void SavePasswordProgressLogger::LogNumber(const std::string& message,
- size_t value) {
- LogValue(message, FundamentalValue(checked_cast<int, size_t>(value)));
+SavePasswordProgressLogger::StructuredLog::StructuredLog(
+ StringID label,
+ const std::string& element_id)
+ : log_type(LOG_TYPE_ELEMENT_ID),
+ label(label),
+ message(STRING_INVALID),
+ number(0),
+ truth_value(false),
+ element_id(element_id) {
}
-void SavePasswordProgressLogger::LogFinalDecision(Decision decision) {
- LogValue("Final decision taken", DecisionToStringValue(decision));
+SavePasswordProgressLogger::StructuredLog::~StructuredLog() {
}
-void SavePasswordProgressLogger::LogMessage(const std::string& message) {
- LogValue("Message", StringValue(message));
+bool SavePasswordProgressLogger::StructuredLog::operator==(
+ const SavePasswordProgressLogger::StructuredLog& log) const {
+ if (log_type != log.log_type || label != log.label)
+ return false;
+ switch (log_type) {
+ case LOG_TYPE_LABEL:
+ return true;
+ case LOG_TYPE_GURL:
+ return url == log.url;
+ case LOG_TYPE_MESSAGE:
+ return message == log.message;
+ case LOG_TYPE_NUMBER:
+ return number == log.number;
+ case LOG_TYPE_BOOL:
+ return truth_value == log.truth_value;
+ case LOG_TYPE_ELEMENT_ID:
+ return element_id == log.element_id;
+ };
+ NOTREACHED(); // Win compilers don't believe this is unreachable.
+ return false;
}
-void SavePasswordProgressLogger::LogValue(const std::string& name,
- const Value& log) {
+bool SavePasswordProgressLogger::StructuredLog::operator!=(
+ const SavePasswordProgressLogger::StructuredLog& log) const {
+ return !operator==(log);
+}
+
+
+SavePasswordProgressLogger::SavePasswordProgressLogger() {}
+
+SavePasswordProgressLogger::~SavePasswordProgressLogger() {}
+
+// static
+std::string SavePasswordProgressLogger::SanitizeStructuredLogs(
+ const std::vector<SavePasswordProgressLogger::StructuredLog>& logs) {
+ // First, we sanitize the logs and transform them into a base::Value.
+ DictionaryValue log_dict; // Always holds a single item: the log.
+ if (logs.size() == 1) {
+ log_dict.Set(kIDsToMessages[logs[0].label],
+ GetValueFromStructuredLog(logs[0]).release());
+ } else {
+ if (logs.empty() || logs[0].log_type != StructuredLog::LOG_TYPE_LABEL) {
+ NOTREACHED(); // The logs vector looks damaged.
+ return std::string();
+ }
+ scoped_ptr<DictionaryValue> inner_dict(new DictionaryValue);
+ // Transform and add all but the first log into |inner_dict|.
+ for (size_t i = 1; i < logs.size(); ++i) {
+ inner_dict->Set(kIDsToMessages[logs[i].label],
+ GetValueFromStructuredLog(logs[i]).release());
+ }
+ log_dict.Set(kIDsToMessages[logs[0].label], inner_dict.release());
+ }
+
+ // Now we convert the base::DictionaryValue to a string.
std::string log_string;
bool conversion_to_string_successful = base::JSONWriter::WriteWithOptions(
- &log, base::JSONWriter::OPTIONS_PRETTY_PRINT, &log_string);
+ &log_dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &log_string);
DCHECK(conversion_to_string_successful);
- SendLog(name + ": " + log_string);
+ return log_string;
+}
+
+void SavePasswordProgressLogger::LogPasswordForm(
+ SavePasswordProgressLogger::StringID label,
+ const PasswordForm& form) {
+ std::vector<SavePasswordProgressLogger::StructuredLog> logs;
+ logs.reserve(15);
+ logs.push_back(StructuredLog(label));
+ logs.push_back(
+ StructuredLog(STRING_SCHEME_MESSAGE, FormSchemeToStringID(form.scheme)));
+ logs.push_back(StructuredLog(STRING_SIGNON_REALM, GURL(form.signon_realm)));
+ logs.push_back(StructuredLog(STRING_ORIGINAL_SIGNON_REALM,
+ GURL(form.original_signon_realm)));
+ logs.push_back(StructuredLog(STRING_ORIGIN, form.origin));
+ logs.push_back(StructuredLog(STRING_ACTION, form.action));
+ logs.push_back(StructuredLog(STRING_USERNAME_ELEMENT, form.username_element));
+ logs.push_back(StructuredLog(STRING_PASSWORD_ELEMENT, form.password_element));
+ logs.push_back(StructuredLog(STRING_PASSWORD_AUTOCOMPLETE_SET,
+ form.password_autocomplete_set));
+ logs.push_back(
+ StructuredLog(STRING_OLD_PASSWORD_ELEMENT, form.old_password_element));
+ logs.push_back(StructuredLog(STRING_SSL_VALID, form.ssl_valid));
+ logs.push_back(StructuredLog(STRING_PASSWORD_GENERATED,
+ form.type == PasswordForm::TYPE_GENERATED));
+ logs.push_back(StructuredLog(STRING_TIMES_USED, form.times_used));
+ logs.push_back(StructuredLog(STRING_USE_ADDITIONAL_AUTHENTICATION,
+ form.use_additional_authentication));
+ logs.push_back(StructuredLog(STRING_PSL_MATCH, form.IsPublicSuffixMatch()));
+ SendLog(logs);
+}
+
+void SavePasswordProgressLogger::LogHTMLForm(
+ SavePasswordProgressLogger::StringID label,
+ const std::string& name_or_id,
+ const std::string& method,
+ const GURL& action) {
+ std::vector<SavePasswordProgressLogger::StructuredLog> logs;
+ logs.reserve(4);
+ logs.push_back(StructuredLog(label));
+ logs.push_back(StructuredLog(STRING_NAME_OR_ID, name_or_id));
+ logs.push_back(StructuredLog(STRING_METHOD, FormMethodToStringID(method)));
+ logs.push_back(StructuredLog(STRING_ACTION, action));
+ SendLog(logs);
+}
+
+void SavePasswordProgressLogger::LogURL(
+ SavePasswordProgressLogger::StringID label,
+ const GURL& url) {
+ std::vector<SavePasswordProgressLogger::StructuredLog> logs;
+ logs.push_back(StructuredLog(label, url));
+ SendLog(logs);
+}
+
+void SavePasswordProgressLogger::LogBoolean(
+ SavePasswordProgressLogger::StringID label,
+ bool value) {
+ std::vector<SavePasswordProgressLogger::StructuredLog> logs;
+ logs.push_back(StructuredLog(label, value));
+ SendLog(logs);
+}
+
+void SavePasswordProgressLogger::LogNumber(
+ SavePasswordProgressLogger::StringID label,
+ int value) {
+ std::vector<SavePasswordProgressLogger::StructuredLog> logs;
+ logs.push_back(StructuredLog(label, value));
+ SendLog(logs);
+}
+
+void SavePasswordProgressLogger::LogNumber(
+ SavePasswordProgressLogger::StringID label,
+ size_t value) {
+ std::vector<SavePasswordProgressLogger::StructuredLog> logs;
+ logs.push_back(StructuredLog(label, checked_cast<int, size_t>(value)));
+ SendLog(logs);
+}
+
+void SavePasswordProgressLogger::LogMessage(
+ SavePasswordProgressLogger::StringID message) {
+ std::vector<SavePasswordProgressLogger::StructuredLog> logs;
+ logs.push_back(StructuredLog(STRING_MESSAGE, message));
+ SendLog(logs);
}
} // namespace autofill

Powered by Google App Engine
This is Rietveld 408576698