1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "base/bind_helpers.h"
7 #include "base/command_line.h"
8 #include "base/files/file_util.h"
9 #include "base/location.h"
10 #include "base/metrics/histogram_macros.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/task_runner_util.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/chromeos/policy/system_log_uploader.h"
17 #include "chrome/browser/chromeos/policy/upload_job_impl.h"
18 #include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
19 #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "components/policy/core/browser/browser_policy_connector.h"
22 #include "components/policy/core/common/cloud/enterprise_metrics.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "net/http/http_request_headers.h"
25 #include "third_party/re2/re2/re2.h"
28 // The maximum number of successive retries.
29 const int kMaxNumRetries
= 1;
31 // String constant defining the url tail we upload system logs to.
32 const char* kSystemLogUploadUrlTail
= "/upload";
34 // The file names of the system logs to upload.
35 // Note: do not add anything to this list without checking for PII in the file.
36 const char* const kSystemLogFileNames
[] = {
37 "/var/log/bios_info.txt", "/var/log/chrome/chrome",
38 "/var/log/eventlog.txt", "/var/log/messages",
39 "/var/log/net.log", "/var/log/platform_info.txt",
40 "/var/log/ui/ui.LATEST", "/var/log/update_engine.log"};
42 const char kEmailAddress
[] =
43 "[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}\\@"
44 "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}(\\.[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25})+";
45 const char kIPAddress
[] =
46 "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])"
47 "\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2"
48 "[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
49 "[0-9]{2}|[1-9][0-9]|[0-9]))";
50 const char kIPv6Address
[] =
51 "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|"
52 "([0-9a-fA-F]{1,4}:){1,7}:|"
53 "([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|"
54 "([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|"
55 "([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|"
56 "([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|"
57 "([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|"
58 "[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|"
59 ":((:[0-9a-fA-F]{1,4}){1,7}|:)|"
60 "fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|"
61 "::(ffff(:0{1,4}){0,1}:){0,1}"
62 "((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}"
63 "(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|"
64 "([0-9a-fA-F]{1,4}:){1,4}:"
65 "((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}"
66 "(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))";
68 const char kWebUrl
[] = "(http|https|Http|Https|rtsp|Rtsp):\\/\\/";
70 // Reads the system log files as binary files, stores the files as pairs
71 // (file name, data) and returns. Called on blocking thread.
72 scoped_ptr
<policy::SystemLogUploader::SystemLogs
> ReadFiles() {
73 scoped_ptr
<policy::SystemLogUploader::SystemLogs
> system_logs(
74 new policy::SystemLogUploader::SystemLogs());
75 for (auto const file_path
: kSystemLogFileNames
) {
76 if (!base::PathExists(base::FilePath(file_path
)))
78 std::string data
= std::string();
79 if (!base::ReadFileToString(base::FilePath(file_path
), &data
)) {
80 LOG(ERROR
) << "Failed to read the system log file from the disk "
81 << file_path
<< std::endl
;
83 system_logs
->push_back(std::make_pair(
84 file_path
, policy::SystemLogUploader::RemoveSensitiveData(data
)));
86 return system_logs
.Pass();
89 // An implementation of the |SystemLogUploader::Delegate|, that is used to
90 // create an upload job and load system logs from the disk.
91 class SystemLogDelegate
: public policy::SystemLogUploader::Delegate
{
94 ~SystemLogDelegate() override
;
96 // SystemLogUploader::Delegate:
97 void LoadSystemLogs(const LogUploadCallback
& upload_callback
) override
;
99 scoped_ptr
<policy::UploadJob
> CreateUploadJob(
100 const GURL
& upload_url
,
101 policy::UploadJob::Delegate
* delegate
) override
;
104 DISALLOW_COPY_AND_ASSIGN(SystemLogDelegate
);
107 SystemLogDelegate::SystemLogDelegate() {}
109 SystemLogDelegate::~SystemLogDelegate() {}
111 void SystemLogDelegate::LoadSystemLogs(
112 const LogUploadCallback
& upload_callback
) {
113 // Run ReadFiles() in the thread that interacts with the file system and
114 // return system logs to |upload_callback| on the current thread.
115 base::PostTaskAndReplyWithResult(content::BrowserThread::GetBlockingPool(),
116 FROM_HERE
, base::Bind(&ReadFiles
),
120 scoped_ptr
<policy::UploadJob
> SystemLogDelegate::CreateUploadJob(
121 const GURL
& upload_url
,
122 policy::UploadJob::Delegate
* delegate
) {
123 chromeos::DeviceOAuth2TokenService
* device_oauth2_token_service
=
124 chromeos::DeviceOAuth2TokenServiceFactory::Get();
126 scoped_refptr
<net::URLRequestContextGetter
> system_request_context
=
127 g_browser_process
->system_request_context();
128 std::string robot_account_id
=
129 device_oauth2_token_service
->GetRobotAccountId();
130 return scoped_ptr
<policy::UploadJob
>(new policy::UploadJobImpl(
131 upload_url
, robot_account_id
, device_oauth2_token_service
,
132 system_request_context
, delegate
,
133 make_scoped_ptr(new policy::UploadJobImpl::RandomMimeBoundaryGenerator
)));
136 // Returns the system log upload frequency.
137 base::TimeDelta
GetUploadFrequency() {
138 base::TimeDelta
upload_frequency(base::TimeDelta::FromMilliseconds(
139 policy::SystemLogUploader::kDefaultUploadDelayMs
));
140 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
141 switches::kSystemLogUploadFrequency
)) {
142 std::string string_value
=
143 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
144 switches::kSystemLogUploadFrequency
);
146 if (base::StringToInt(string_value
, &frequency
)) {
147 upload_frequency
= base::TimeDelta::FromMilliseconds(frequency
);
150 return upload_frequency
;
153 void RecordSystemLogPIILeak(policy::SystemLogPIIType type
) {
154 UMA_HISTOGRAM_ENUMERATION(policy::kMetricSystemLogPII
, type
,
155 policy::SYSTEM_LOG_PII_TYPE_SIZE
);
158 std::string
GetUploadUrl() {
159 return policy::BrowserPolicyConnector::GetDeviceManagementUrl() +
160 kSystemLogUploadUrlTail
;
167 // Determines the time between log uploads.
168 const int64
SystemLogUploader::kDefaultUploadDelayMs
=
169 12 * 60 * 60 * 1000; // 12 hours
171 // Determines the time, measured from the time of last failed upload,
172 // after which the log upload is retried.
173 const int64
SystemLogUploader::kErrorUploadDelayMs
= 120 * 1000; // 120 seconds
175 // String constant identifying the header field which stores the file type.
176 const char* const SystemLogUploader::kFileTypeHeaderName
= "File-Type";
178 // String constant signalling that the data segment contains log files.
179 const char* const SystemLogUploader::kFileTypeLogFile
= "log_file";
181 // String constant signalling that the segment contains a plain text.
182 const char* const SystemLogUploader::kContentTypePlainText
= "text/plain";
184 // Template string constant for populating the name field.
185 const char* const SystemLogUploader::kNameFieldTemplate
= "file%d";
187 SystemLogUploader::SystemLogUploader(
188 scoped_ptr
<Delegate
> syslog_delegate
,
189 const scoped_refptr
<base::SequencedTaskRunner
>& task_runner
)
191 upload_frequency_(GetUploadFrequency()),
192 task_runner_(task_runner
),
193 syslog_delegate_(syslog_delegate
.Pass()),
194 upload_enabled_(false),
195 weak_factory_(this) {
196 if (!syslog_delegate_
)
197 syslog_delegate_
.reset(new SystemLogDelegate());
198 DCHECK(syslog_delegate_
);
200 // Watch for policy changes.
201 upload_enabled_observer_
= chromeos::CrosSettings::Get()->AddSettingsObserver(
202 chromeos::kLogUploadEnabled
,
203 base::Bind(&SystemLogUploader::RefreshUploadSettings
,
204 base::Unretained(this)));
206 // Fetch the current value of the policy.
207 RefreshUploadSettings();
209 // Immediately schedule the next system log upload (last_upload_attempt_ is
210 // set to the start of the epoch, so this will trigger an update upload in the
211 // immediate future).
212 ScheduleNextSystemLogUpload(upload_frequency_
);
215 SystemLogUploader::~SystemLogUploader() {}
217 void SystemLogUploader::OnSuccess() {
219 last_upload_attempt_
= base::Time::NowFromSystemTime();
222 // On successful log upload schedule the next log upload after
223 // upload_frequency_ time from now.
224 ScheduleNextSystemLogUpload(upload_frequency_
);
227 void SystemLogUploader::OnFailure(UploadJob::ErrorCode error_code
) {
229 last_upload_attempt_
= base::Time::NowFromSystemTime();
231 // If we have hit the maximum number of retries, terminate this upload
232 // attempt and schedule the next one using the normal delay. Otherwise, retry
233 // uploading after kErrorUploadDelayMs milliseconds.
234 if (retry_count_
++ < kMaxNumRetries
) {
235 ScheduleNextSystemLogUpload(
236 base::TimeDelta::FromMilliseconds(kErrorUploadDelayMs
));
240 ScheduleNextSystemLogUpload(upload_frequency_
);
245 std::string
SystemLogUploader::RemoveSensitiveData(const std::string
& data
) {
246 std::string result
= "";
247 RE2
email_pattern(kEmailAddress
), ipv4_pattern(kIPAddress
),
248 ipv6_pattern(kIPv6Address
), url_pattern(kWebUrl
);
250 for (const std::string
& line
: base::SplitString(
251 data
, "\n", base::KEEP_WHITESPACE
, base::SPLIT_WANT_ALL
)) {
253 if (RE2::PartialMatch(line
, email_pattern
)) {
254 RecordSystemLogPIILeak(SYSTEM_LOG_PII_TYPE_EMAIL_ADDRESS
);
259 if (RE2::PartialMatch(line
, ipv4_pattern
)) {
260 RecordSystemLogPIILeak(SYSTEM_LOG_PII_TYPE_IP_ADDRESS
);
265 if (RE2::PartialMatch(line
, ipv6_pattern
)) {
266 RecordSystemLogPIILeak(SYSTEM_LOG_PII_TYPE_IP_ADDRESS
);
271 if (RE2::PartialMatch(line
, url_pattern
)) {
272 RecordSystemLogPIILeak(SYSTEM_LOG_PII_TYPE_WEB_URL
);
277 if (line
.find("SSID=") != std::string::npos
) {
278 RecordSystemLogPIILeak(SYSTEM_LOG_PII_TYPE_SSID
);
282 result
+= line
+ "\n";
287 void SystemLogUploader::RefreshUploadSettings() {
288 // Attempt to fetch the current value of the reporting settings.
289 // If trusted values are not available, register this function to be called
290 // back when they are available.
291 chromeos::CrosSettings
* settings
= chromeos::CrosSettings::Get();
292 if (chromeos::CrosSettingsProvider::TRUSTED
!=
293 settings
->PrepareTrustedValues(
294 base::Bind(&SystemLogUploader::RefreshUploadSettings
,
295 weak_factory_
.GetWeakPtr()))) {
299 // CrosSettings are trusted - we want to use the last trusted values, by
300 // default do not upload system logs.
301 if (!settings
->GetBoolean(chromeos::kLogUploadEnabled
, &upload_enabled_
))
302 upload_enabled_
= false;
305 void SystemLogUploader::UploadSystemLogs(scoped_ptr
<SystemLogs
> system_logs
) {
306 // Must be called on the main thread.
307 DCHECK(thread_checker_
.CalledOnValidThread());
308 DCHECK(!upload_job_
);
310 GURL
upload_url(GetUploadUrl());
311 DCHECK(upload_url
.is_valid());
312 upload_job_
= syslog_delegate_
->CreateUploadJob(upload_url
, this);
314 // Start a system log upload.
316 for (const auto& syslog_entry
: *system_logs
) {
317 std::map
<std::string
, std::string
> header_fields
;
318 scoped_ptr
<std::string
> data
=
319 make_scoped_ptr(new std::string(syslog_entry
.second
));
320 header_fields
.insert(std::make_pair(kFileTypeHeaderName
, kFileTypeLogFile
));
321 header_fields
.insert(std::make_pair(net::HttpRequestHeaders::kContentType
,
322 kContentTypePlainText
));
323 upload_job_
->AddDataSegment(
324 base::StringPrintf(kNameFieldTemplate
, file_number
), syslog_entry
.first
,
325 header_fields
, data
.Pass());
328 upload_job_
->Start();
331 void SystemLogUploader::StartLogUpload() {
332 // Must be called on the main thread.
333 DCHECK(thread_checker_
.CalledOnValidThread());
335 if (upload_enabled_
) {
336 syslog_delegate_
->LoadSystemLogs(base::Bind(
337 &SystemLogUploader::UploadSystemLogs
, weak_factory_
.GetWeakPtr()));
339 // If upload is disabled, schedule the next attempt after 12h.
341 last_upload_attempt_
= base::Time::NowFromSystemTime();
342 ScheduleNextSystemLogUpload(upload_frequency_
);
346 void SystemLogUploader::ScheduleNextSystemLogUpload(base::TimeDelta frequency
) {
347 // Calculate when to fire off the next update.
348 base::TimeDelta delay
= std::max(
349 (last_upload_attempt_
+ frequency
) - base::Time::NowFromSystemTime(),
351 // Ensure that we never have more than one pending delayed task.
352 weak_factory_
.InvalidateWeakPtrs();
353 task_runner_
->PostDelayedTask(FROM_HERE
,
354 base::Bind(&SystemLogUploader::StartLogUpload
,
355 weak_factory_
.GetWeakPtr()),
359 } // namespace policy