Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / net / crl_set_fetcher.cc
1 // Copyright (c) 2012 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.
4
5 #include "chrome/browser/net/crl_set_fetcher.h"
6
7 #include "base/bind.h"
8 #include "base/debug/trace_event.h"
9 #include "base/files/file_util.h"
10 #include "base/numerics/safe_conversions.h"
11 #include "base/rand_util.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/time/time.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/chrome_constants.h"
16 #include "chrome/common/chrome_paths.h"
17 #include "components/component_updater/component_updater_service.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "net/cert/crl_set.h"
20 #include "net/cert/crl_set_storage.h"
21 #include "net/ssl/ssl_config_service.h"
22
23 using component_updater::ComponentUpdateService;
24 using content::BrowserThread;
25
26 CRLSetFetcher::CRLSetFetcher() : cus_(NULL) {}
27
28 void CRLSetFetcher::SetCRLSetFilePath(const base::FilePath& path) {
29   crl_path_ = path.Append(chrome::kCRLSetFilename);
30 }
31
32 base::FilePath CRLSetFetcher::GetCRLSetFilePath() const {
33   return crl_path_;
34 }
35
36 void CRLSetFetcher::StartInitialLoad(ComponentUpdateService* cus,
37                                      const base::FilePath& path) {
38   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
39   if (path.empty())
40     return;
41   SetCRLSetFilePath(path);
42   cus_ = cus;
43
44   if (!BrowserThread::PostTask(
45           BrowserThread::FILE, FROM_HERE,
46           base::Bind(&CRLSetFetcher::DoInitialLoadFromDisk, this))) {
47     NOTREACHED();
48   }
49 }
50
51 void CRLSetFetcher::DeleteFromDisk(const base::FilePath& path) {
52   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
53
54   if (path.empty())
55     return;
56   SetCRLSetFilePath(path);
57   if (!BrowserThread::PostTask(
58           BrowserThread::FILE, FROM_HERE,
59           base::Bind(&CRLSetFetcher::DoDeleteFromDisk, this))) {
60     NOTREACHED();
61   }
62 }
63
64 void CRLSetFetcher::DoInitialLoadFromDisk() {
65   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
66
67   LoadFromDisk(GetCRLSetFilePath(), &crl_set_);
68
69   uint32 sequence_of_loaded_crl = 0;
70   if (crl_set_.get())
71     sequence_of_loaded_crl = crl_set_->sequence();
72
73   // Get updates, advertising the sequence number of the CRL set that we just
74   // loaded, if any.
75   if (!BrowserThread::PostTask(
76           BrowserThread::UI, FROM_HERE,
77           base::Bind(
78               &CRLSetFetcher::RegisterComponent,
79               this,
80               sequence_of_loaded_crl))) {
81     NOTREACHED();
82   }
83 }
84
85 void CRLSetFetcher::LoadFromDisk(base::FilePath path,
86                                  scoped_refptr<net::CRLSet>* out_crl_set) {
87   TRACE_EVENT0("CRLSetFetcher", "LoadFromDisk");
88
89   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
90
91   std::string crl_set_bytes;
92   {
93     TRACE_EVENT0("CRLSetFetcher", "ReadFileToString");
94     if (!base::ReadFileToString(path, &crl_set_bytes))
95       return;
96   }
97
98   if (!net::CRLSetStorage::Parse(crl_set_bytes, out_crl_set)) {
99     LOG(WARNING) << "Failed to parse CRL set from " << path.MaybeAsASCII();
100     return;
101   }
102
103   VLOG(1) << "Loaded " << crl_set_bytes.size() << " bytes of CRL set from disk";
104
105   if (!BrowserThread::PostTask(
106           BrowserThread::IO, FROM_HERE,
107           base::Bind(
108               &CRLSetFetcher::SetCRLSetIfNewer, this, *out_crl_set))) {
109     NOTREACHED();
110   }
111 }
112
113 void CRLSetFetcher::SetCRLSetIfNewer(
114     scoped_refptr<net::CRLSet> crl_set) {
115   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
116
117   scoped_refptr<net::CRLSet> old_crl_set(net::SSLConfigService::GetCRLSet());
118   if (old_crl_set.get() && old_crl_set->sequence() > crl_set->sequence()) {
119     LOG(WARNING) << "Refusing to downgrade CRL set from #"
120                  << old_crl_set->sequence()
121                  << "to #"
122                  << crl_set->sequence();
123   } else {
124     net::SSLConfigService::SetCRLSet(crl_set);
125     VLOG(1) << "Installed CRL set #" << crl_set->sequence();
126   }
127 }
128
129 // kPublicKeySHA256 is the SHA256 hash of the SubjectPublicKeyInfo of the key
130 // that's used to sign generated CRL sets.
131 static const uint8 kPublicKeySHA256[32] = {
132   0x75, 0xda, 0xf8, 0xcb, 0x77, 0x68, 0x40, 0x33,
133   0x65, 0x4c, 0x97, 0xe5, 0xc5, 0x1b, 0xcd, 0x81,
134   0x7b, 0x1e, 0xeb, 0x11, 0x2c, 0xe1, 0xa4, 0x33,
135   0x8c, 0xf5, 0x72, 0x5e, 0xed, 0xb8, 0x43, 0x97,
136 };
137
138 void CRLSetFetcher::RegisterComponent(uint32 sequence_of_loaded_crl) {
139   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
140
141   component_updater::CrxComponent component;
142   component.pk_hash.assign(kPublicKeySHA256,
143                            kPublicKeySHA256 + sizeof(kPublicKeySHA256));
144   component.installer = this;
145   component.name = "CRLSet";
146   component.version = Version(base::UintToString(sequence_of_loaded_crl));
147   component.allow_background_download = false;
148   if (!component.version.IsValid()) {
149     NOTREACHED();
150     component.version = Version("0");
151   }
152
153   if (cus_->RegisterComponent(component) !=
154       ComponentUpdateService::kOk) {
155     NOTREACHED() << "RegisterComponent returned error";
156   }
157 }
158
159 void CRLSetFetcher::DoDeleteFromDisk() {
160   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
161
162   DeleteFile(GetCRLSetFilePath(), false /* not recursive */);
163 }
164
165 void CRLSetFetcher::OnUpdateError(int error) {
166   LOG(WARNING) << "CRLSetFetcher got error " << error
167                << " from component installer";
168 }
169
170 bool CRLSetFetcher::Install(const base::DictionaryValue& manifest,
171                             const base::FilePath& unpack_path) {
172   base::FilePath crl_set_file_path =
173       unpack_path.Append(FILE_PATH_LITERAL("crl-set"));
174   base::FilePath save_to = GetCRLSetFilePath();
175
176   std::string crl_set_bytes;
177   if (!base::ReadFileToString(crl_set_file_path, &crl_set_bytes)) {
178     LOG(WARNING) << "Failed to find crl-set file inside CRX";
179     return false;
180   }
181
182   bool is_delta;
183   if (!net::CRLSetStorage::GetIsDeltaUpdate(crl_set_bytes, &is_delta)) {
184     LOG(WARNING) << "GetIsDeltaUpdate failed on CRL set from update CRX";
185     return false;
186   }
187
188   if (!is_delta) {
189     if (!net::CRLSetStorage::Parse(crl_set_bytes, &crl_set_)) {
190       LOG(WARNING) << "Failed to parse CRL set from update CRX";
191       return false;
192     }
193     int size = base::checked_cast<int>(crl_set_bytes.size());
194     if (base::WriteFile(save_to, crl_set_bytes.data(), size) != size) {
195       LOG(WARNING) << "Failed to save new CRL set to disk";
196       // We don't return false here because we can still use this CRL set. When
197       // we restart we might revert to an older version, then we'll
198       // advertise the older version to Omaha and everything will still work.
199     }
200   } else {
201     scoped_refptr<net::CRLSet> new_crl_set;
202     if (!net::CRLSetStorage::ApplyDelta(
203             crl_set_.get(), crl_set_bytes, &new_crl_set)) {
204       LOG(WARNING) << "Failed to parse delta CRL set";
205       return false;
206     }
207     VLOG(1) << "Applied CRL set delta #" << crl_set_->sequence()
208             << "->#" << new_crl_set->sequence();
209     const std::string new_crl_set_bytes =
210         net::CRLSetStorage::Serialize(new_crl_set.get());
211     int size = base::checked_cast<int>(new_crl_set_bytes.size());
212     if (base::WriteFile(save_to, new_crl_set_bytes.data(), size) != size) {
213       LOG(WARNING) << "Failed to save new CRL set to disk";
214       // We don't return false here because we can still use this CRL set. When
215       // we restart we might revert to an older version, then we'll
216       // advertise the older version to Omaha and everything will still work.
217     }
218     crl_set_ = new_crl_set;
219   }
220
221   if (!BrowserThread::PostTask(
222           BrowserThread::IO, FROM_HERE,
223           base::Bind(
224               &CRLSetFetcher::SetCRLSetIfNewer, this, crl_set_))) {
225     NOTREACHED();
226   }
227
228   return true;
229 }
230
231 bool CRLSetFetcher::GetInstalledFile(
232     const std::string& file, base::FilePath* installed_file) {
233   return false;
234 }
235
236 CRLSetFetcher::~CRLSetFetcher() {}