1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_log_util.h"
6
7 #include <string_view>
8
9 #include "base/strings/strcat.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "net/http/http_auth_challenge_tokenizer.h"
13 #include "net/http/http_auth_scheme.h"
14 #include "net/http/http_request_headers.h"
15 #include "net/http/http_response_headers.h"
16 #include "net/log/net_log_with_source.h"
17
18 namespace net {
19
20 namespace {
21
ShouldRedactChallenge(HttpAuthChallengeTokenizer * challenge)22 bool ShouldRedactChallenge(HttpAuthChallengeTokenizer* challenge) {
23 // Ignore lines with commas, as they may contain lists of schemes, and
24 // the information we want to hide is Base64 encoded, so has no commas.
25 if (challenge->challenge_text().find(',') != std::string::npos)
26 return false;
27
28 const std::string& scheme = challenge->auth_scheme();
29 // Invalid input.
30 if (scheme.empty())
31 return false;
32
33 // Ignore Basic and Digest authentication challenges, as they contain
34 // public information.
35 if (scheme == kBasicAuthScheme || scheme == kDigestAuthScheme)
36 return false;
37
38 return true;
39 }
40
41 } // namespace
42
ElideHeaderValueForNetLog(NetLogCaptureMode capture_mode,std::string_view header,std::string_view value)43 std::string ElideHeaderValueForNetLog(NetLogCaptureMode capture_mode,
44 std::string_view header,
45 std::string_view value) {
46 std::string_view redact;
47
48 if (!NetLogCaptureIncludesSensitive(capture_mode)) {
49 if (base::EqualsCaseInsensitiveASCII(header, "set-cookie") ||
50 base::EqualsCaseInsensitiveASCII(header, "set-cookie2") ||
51 base::EqualsCaseInsensitiveASCII(header, "cookie") ||
52 base::EqualsCaseInsensitiveASCII(header, "authorization") ||
53 base::EqualsCaseInsensitiveASCII(header, "proxy-authorization")) {
54 redact = value;
55 } else if (base::EqualsCaseInsensitiveASCII(header, "www-authenticate") ||
56 base::EqualsCaseInsensitiveASCII(header, "proxy-authenticate")) {
57 // Look for authentication information from data received from the server
58 // in multi-round Negotiate authentication.
59 HttpAuthChallengeTokenizer challenge(value);
60 if (ShouldRedactChallenge(&challenge)) {
61 redact = challenge.params();
62 }
63 }
64 }
65
66 if (redact.empty()) {
67 return std::string(value);
68 }
69
70 // Create string_views that contain the part of `value` before the `redact`
71 // substring, and the value after it. Need to use the data() field of the two
72 // string_views to figure out where `redact` appears within `value`.
73 size_t redact_offset = redact.data() - value.data();
74 std::string_view value_before_redact = value.substr(0, redact_offset);
75 std::string_view value_after_redact =
76 value.substr(redact_offset + redact.length());
77
78 return base::StrCat({value_before_redact,
79 base::StringPrintf("[%ld bytes were stripped]",
80 static_cast<long>(redact.length())),
81 value_after_redact});
82 }
83
NetLogResponseHeaders(const NetLogWithSource & net_log,NetLogEventType type,const HttpResponseHeaders * headers)84 NET_EXPORT void NetLogResponseHeaders(const NetLogWithSource& net_log,
85 NetLogEventType type,
86 const HttpResponseHeaders* headers) {
87 net_log.AddEvent(type, [&](NetLogCaptureMode capture_mode) {
88 return headers->NetLogParams(capture_mode);
89 });
90 }
91
NetLogRequestHeaders(const NetLogWithSource & net_log,NetLogEventType type,const std::string & request_line,const HttpRequestHeaders * headers)92 void NetLogRequestHeaders(const NetLogWithSource& net_log,
93 NetLogEventType type,
94 const std::string& request_line,
95 const HttpRequestHeaders* headers) {
96 net_log.AddEvent(type, [&](NetLogCaptureMode capture_mode) {
97 return headers->NetLogParams(request_line, capture_mode);
98 });
99 }
100
101 } // namespace net
102