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

Side by Side 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: Pass a string16 by a const ref 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "components/autofill/core/common/save_password_progress_logger.h" 5 #include "components/autofill/core/common/save_password_progress_logger.h"
6 6
7 #include <algorithm>
8
7 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
8 #include "base/logging.h" 10 #include "base/logging.h"
9 #include "base/numerics/safe_conversions.h" 11 #include "base/numerics/safe_conversions.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h" 15 #include "base/values.h"
11 #include "components/autofill/core/common/password_form.h" 16 #include "components/autofill/core/common/password_form.h"
12 17
13 using base::checked_cast; 18 using base::checked_cast;
14 using base::Value; 19 using base::Value;
15 using base::DictionaryValue; 20 using base::DictionaryValue;
16 using base::FundamentalValue; 21 using base::FundamentalValue;
17 using base::StringValue; 22 using base::StringValue;
18 23
19 namespace autofill { 24 namespace autofill {
20 25
21 namespace { 26 namespace {
22 27
28 // Note 1: Caching the ID->string map in an array would be probably faster, but
29 // the switch statement is (a) robust against re-ordering, and (b) checks in
30 // compile-time, that all IDs get a string assigned. The expected frequency of
31 // calls is low enough (in particular, zero if password manager internals page
32 // is not open), that optimizing for code robustness is preferred against speed.
33 // Note 2: The messages can be used as dictionary keys. Do not use '.' in them.
34 std::string GetStringFromID(SavePasswordProgressLogger::StringID id) {
35 switch (id) {
36 case SavePasswordProgressLogger::STRING_DECISION_ASK:
37 return "Decision: ASK the user";
38 case SavePasswordProgressLogger::STRING_DECISION_DROP:
39 return "Decision: DROP the password";
40 case SavePasswordProgressLogger::STRING_DECISION_SAVE:
41 return "Decision: SAVE the password";
42 case SavePasswordProgressLogger::STRING_METHOD:
43 return "Form method";
44 case SavePasswordProgressLogger::STRING_METHOD_GET:
45 return "GET";
46 case SavePasswordProgressLogger::STRING_METHOD_POST:
47 return "POST";
48 case SavePasswordProgressLogger::STRING_METHOD_EMPTY:
49 return "(empty)";
50 case SavePasswordProgressLogger::STRING_OTHER:
51 return "(other)";
52 case SavePasswordProgressLogger::STRING_SCHEME_HTML:
53 return "HTML";
54 case SavePasswordProgressLogger::STRING_SCHEME_BASIC:
55 return "Basic";
56 case SavePasswordProgressLogger::STRING_SCHEME_DIGEST:
57 return "Digest";
58 case SavePasswordProgressLogger::STRING_SCHEME_MESSAGE:
59 return "Scheme";
60 case SavePasswordProgressLogger::STRING_SIGNON_REALM:
61 return "Signon realm";
62 case SavePasswordProgressLogger::STRING_ORIGINAL_SIGNON_REALM:
63 return "Original signon realm";
64 case SavePasswordProgressLogger::STRING_ORIGIN:
65 return "Origin";
66 case SavePasswordProgressLogger::STRING_ACTION:
67 return "Action";
68 case SavePasswordProgressLogger::STRING_USERNAME_ELEMENT:
69 return "Username element";
70 case SavePasswordProgressLogger::STRING_PASSWORD_ELEMENT:
71 return "Password element";
72 case SavePasswordProgressLogger::STRING_PASSWORD_AUTOCOMPLETE_SET:
73 return "Password autocomplete set";
74 case SavePasswordProgressLogger::STRING_OLD_PASSWORD_ELEMENT:
75 return "Old password element";
76 case SavePasswordProgressLogger::STRING_SSL_VALID:
77 return "SSL valid";
78 case SavePasswordProgressLogger::STRING_PASSWORD_GENERATED:
79 return "Password generated";
80 case SavePasswordProgressLogger::STRING_TIMES_USED:
81 return "Times used";
82 case SavePasswordProgressLogger::STRING_USE_ADDITIONAL_AUTHENTICATION:
83 return "Use additional authentication";
84 case SavePasswordProgressLogger::STRING_PSL_MATCH:
85 return "PSL match";
86 case SavePasswordProgressLogger::STRING_NAME_OR_ID:
87 return "Form name or ID";
88 case SavePasswordProgressLogger::STRING_MESSAGE:
89 return "Message";
90 case SavePasswordProgressLogger::STRING_INVALID:
91 return "INVALID";
92 // Intentionally no default: clause here -- all IDs need to get covered.
93 }
94 NOTREACHED(); // Win compilers don't believe this is unreachable.
95 return std::string();
96 };
97
23 // Removes privacy sensitive parts of |url| (currently all but host and scheme). 98 // Removes privacy sensitive parts of |url| (currently all but host and scheme).
24 std::string ScrubURL(const GURL& url) { 99 std::string ScrubURL(const GURL& url) {
25 if (url.is_valid()) 100 if (url.is_valid())
26 return url.GetWithEmptyPath().spec(); 101 return url.GetWithEmptyPath().spec();
27 return std::string(); 102 return std::string();
28 } 103 }
29 104
105 // Returns true for all characters which we don't want to see in the logged IDs
106 // or names of HTML elements.
107 bool IsUnwantedInElementID(char c) {
108 return !(c == '_' || c == '-' || IsAsciiAlpha(c) || IsAsciiDigit(c));
109 }
110
111 // Replaces all characters satisfying IsUnwantedInElementID by a ' ', and turns
112 // all characters to lowercase. This damages some valid HTML element IDs or
113 // names, but it is likely that it will be still possible to match the scrubbed
114 // string to the original ID or name in the HTML doc. That's good enough for the
115 // logging purposes, and provides some security benefits.
116 std::string ScrubElementID(std::string element_id) {
117 std::replace_if(
118 element_id.begin(), element_id.end(), IsUnwantedInElementID, ' ');
119 return StringToLowerASCII(element_id);
120 }
121
122 std::string ScrubElementID(const base::string16& element_id) {
123 return ScrubElementID(base::UTF16ToUTF8(element_id));
124 }
125
30 std::string FormSchemeToString(PasswordForm::Scheme scheme) { 126 std::string FormSchemeToString(PasswordForm::Scheme scheme) {
127 SavePasswordProgressLogger::StringID result_id =
128 SavePasswordProgressLogger::STRING_INVALID;
31 switch (scheme) { 129 switch (scheme) {
32 case PasswordForm::SCHEME_HTML: 130 case PasswordForm::SCHEME_HTML:
33 return "HTML"; 131 result_id = SavePasswordProgressLogger::STRING_SCHEME_HTML;
132 break;
34 case PasswordForm::SCHEME_BASIC: 133 case PasswordForm::SCHEME_BASIC:
35 return "BASIC"; 134 result_id = SavePasswordProgressLogger::STRING_SCHEME_BASIC;
135 break;
36 case PasswordForm::SCHEME_DIGEST: 136 case PasswordForm::SCHEME_DIGEST:
37 return "DIGEST"; 137 result_id = SavePasswordProgressLogger::STRING_SCHEME_DIGEST;
138 break;
38 case PasswordForm::SCHEME_OTHER: 139 case PasswordForm::SCHEME_OTHER:
39 return "OTHER"; 140 result_id = SavePasswordProgressLogger::STRING_OTHER;
141 break;
40 } 142 }
41 NOTREACHED(); // Win compilers don't believe this is unreachable. 143 return GetStringFromID(result_id);
42 return std::string();
43 } 144 }
44 145
45 StringValue DecisionToStringValue( 146 std::string FormMethodToString(const std::string& method) {
46 SavePasswordProgressLogger::Decision decision) { 147 std::string method_processed;
47 switch (decision) { 148 base::TrimWhitespaceASCII(
48 case SavePasswordProgressLogger::DECISION_SAVE: 149 StringToLowerASCII(method), base::TRIM_ALL, &method_processed);
49 return StringValue("SAVE the password"); 150 SavePasswordProgressLogger::StringID result_id =
50 case SavePasswordProgressLogger::DECISION_ASK: 151 SavePasswordProgressLogger::STRING_OTHER;
51 return StringValue("ASK the user whether to save the password"); 152 if (method_processed.empty())
52 case SavePasswordProgressLogger::DECISION_DROP: 153 result_id = SavePasswordProgressLogger::STRING_METHOD_EMPTY;
53 return StringValue("DROP the password"); 154 else if (method_processed == "get")
54 } 155 result_id = SavePasswordProgressLogger::STRING_METHOD_GET;
55 NOTREACHED(); // Win compilers don't believe this is unreachable. 156 else if (method_processed == "post")
56 return StringValue(std::string()); 157 result_id = SavePasswordProgressLogger::STRING_METHOD_POST;
158 return GetStringFromID(result_id);
57 } 159 }
58 160
59 } // namespace 161 } // namespace
60 162
61 SavePasswordProgressLogger::SavePasswordProgressLogger() {} 163 SavePasswordProgressLogger::SavePasswordProgressLogger() {
62
63 SavePasswordProgressLogger::~SavePasswordProgressLogger() {}
64
65 void SavePasswordProgressLogger::LogPasswordForm(const std::string& message,
66 const PasswordForm& form) {
67 DictionaryValue log;
68 // Do not use the "<<" operator for PasswordForms, because it also prints
69 // passwords. Also, that operator is only for testing.
70 log.SetString("scheme", FormSchemeToString(form.scheme));
71 log.SetString("signon realm", ScrubURL(GURL(form.signon_realm)));
72 log.SetString("original signon realm",
73 ScrubURL(GURL(form.original_signon_realm)));
74 log.SetString("origin", ScrubURL(form.origin));
75 log.SetString("action", ScrubURL(form.action));
76 log.SetString("username element", form.username_element);
77 log.SetString("password element", form.password_element);
78 log.SetBoolean("password autocomplete set", form.password_autocomplete_set);
79 log.SetString("old password element", form.old_password_element);
80 log.SetBoolean("ssl valid", form.ssl_valid);
81 log.SetBoolean("password generated",
82 form.type == PasswordForm::TYPE_GENERATED);
83 log.SetInteger("times used", form.times_used);
84 log.SetBoolean("use additional authentication",
85 form.use_additional_authentication);
86 log.SetBoolean("is PSL match", form.IsPublicSuffixMatch());
87 LogValue(message, log);
88 } 164 }
89 165
90 void SavePasswordProgressLogger::LogHTMLForm(const std::string& message, 166 SavePasswordProgressLogger::~SavePasswordProgressLogger() {
91 const std::string& name_or_id,
92 const std::string& method,
93 const GURL& action) {
94 DictionaryValue log;
95 log.SetString("name_or_id", name_or_id);
96 log.SetString("method", method);
97 log.SetString("action", ScrubURL(action));
98 LogValue(message, log);
99 } 167 }
100 168
101 void SavePasswordProgressLogger::LogURL(const std::string& message, 169 void SavePasswordProgressLogger::LogPasswordForm(
102 const GURL& url) { 170 SavePasswordProgressLogger::StringID label,
103 LogValue(message, StringValue(ScrubURL(url))); 171 const PasswordForm& form) {
172 DictionaryValue log;
173 log.SetString(GetStringFromID(STRING_SCHEME_MESSAGE),
174 FormSchemeToString(form.scheme));
175 log.SetString(GetStringFromID(STRING_SCHEME_MESSAGE),
176 FormSchemeToString(form.scheme));
177 log.SetString(GetStringFromID(STRING_SIGNON_REALM),
178 ScrubURL(GURL(form.signon_realm)));
179 log.SetString(GetStringFromID(STRING_ORIGINAL_SIGNON_REALM),
180 ScrubURL(GURL(form.original_signon_realm)));
181 log.SetString(GetStringFromID(STRING_ORIGIN), ScrubURL(form.origin));
182 log.SetString(GetStringFromID(STRING_ACTION), ScrubURL(form.action));
183 log.SetString(GetStringFromID(STRING_USERNAME_ELEMENT),
184 ScrubElementID(form.username_element));
185 log.SetString(GetStringFromID(STRING_PASSWORD_ELEMENT),
186 ScrubElementID(form.password_element));
187 log.SetBoolean(GetStringFromID(STRING_PASSWORD_AUTOCOMPLETE_SET),
188 form.password_autocomplete_set);
189 log.SetString(GetStringFromID(STRING_OLD_PASSWORD_ELEMENT),
190 ScrubElementID(form.old_password_element));
191 log.SetBoolean(GetStringFromID(STRING_SSL_VALID), form.ssl_valid);
192 log.SetBoolean(GetStringFromID(STRING_PASSWORD_GENERATED),
193 form.type == PasswordForm::TYPE_GENERATED);
194 log.SetInteger(GetStringFromID(STRING_TIMES_USED), form.times_used);
195 log.SetBoolean(GetStringFromID(STRING_USE_ADDITIONAL_AUTHENTICATION),
196 form.use_additional_authentication);
197 log.SetBoolean(GetStringFromID(STRING_PSL_MATCH), form.IsPublicSuffixMatch());
198 LogValue(label, log);
104 } 199 }
105 200
106 void SavePasswordProgressLogger::LogBoolean(const std::string& message, 201 void SavePasswordProgressLogger::LogHTMLForm(
107 bool value) { 202 SavePasswordProgressLogger::StringID label,
108 LogValue(message, FundamentalValue(value)); 203 const std::string& name_or_id,
204 const std::string& method,
205 const GURL& action) {
206 DictionaryValue log;
207 log.SetString(GetStringFromID(STRING_NAME_OR_ID), ScrubElementID(name_or_id));
208 log.SetString(GetStringFromID(STRING_METHOD), FormMethodToString(method));
209 log.SetString(GetStringFromID(STRING_ACTION), ScrubURL(action));
210 LogValue(label, log);
109 } 211 }
110 212
111 void SavePasswordProgressLogger::LogNumber(const std::string& message, 213 void SavePasswordProgressLogger::LogURL(
112 int value) { 214 SavePasswordProgressLogger::StringID label,
113 LogValue(message, FundamentalValue(value)); 215 const GURL& url) {
216 LogValue(label, StringValue(ScrubURL(url)));
114 } 217 }
115 218
116 void SavePasswordProgressLogger::LogNumber(const std::string& message, 219 void SavePasswordProgressLogger::LogBoolean(
117 size_t value) { 220 SavePasswordProgressLogger::StringID label,
118 LogValue(message, FundamentalValue(checked_cast<int, size_t>(value))); 221 bool truth_value) {
222 LogValue(label, FundamentalValue(truth_value));
119 } 223 }
120 224
121 void SavePasswordProgressLogger::LogFinalDecision(Decision decision) { 225 void SavePasswordProgressLogger::LogNumber(
122 LogValue("Final decision taken", DecisionToStringValue(decision)); 226 SavePasswordProgressLogger::StringID label,
227 int signed_number) {
228 LogValue(label, FundamentalValue(signed_number));
123 } 229 }
124 230
125 void SavePasswordProgressLogger::LogMessage(const std::string& message) { 231 void SavePasswordProgressLogger::LogNumber(
126 LogValue("Message", StringValue(message)); 232 SavePasswordProgressLogger::StringID label,
233 size_t unsigned_number) {
234 int signed_number = checked_cast<int, size_t>(unsigned_number);
235 LogNumber(label, signed_number);
127 } 236 }
128 237
129 void SavePasswordProgressLogger::LogValue(const std::string& name, 238 void SavePasswordProgressLogger::LogMessage(
130 const Value& log) { 239 SavePasswordProgressLogger::StringID message) {
240 LogValue(STRING_MESSAGE, StringValue(GetStringFromID(message)));
241 }
242
243 void SavePasswordProgressLogger::LogValue(StringID label, const Value& log) {
131 std::string log_string; 244 std::string log_string;
132 bool conversion_to_string_successful = base::JSONWriter::WriteWithOptions( 245 bool conversion_to_string_successful = base::JSONWriter::WriteWithOptions(
133 &log, base::JSONWriter::OPTIONS_PRETTY_PRINT, &log_string); 246 &log, base::JSONWriter::OPTIONS_PRETTY_PRINT, &log_string);
134 DCHECK(conversion_to_string_successful); 247 DCHECK(conversion_to_string_successful);
135 SendLog(name + ": " + log_string); 248 SendLog(GetStringFromID(label) + ": " + log_string);
136 } 249 }
137 250
138 } // namespace autofill 251 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698