[safe-browsing] Database full hash matches like prefix match.
[chromium-blink-merge.git] / chrome / browser / net / crl_set_fetcher.cc
blob201faf9b9371d13a0cd9d786f84a747540426c44
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.
5 #include "chrome/browser/net/crl_set_fetcher.h"
7 #include "base/bind.h"
8 #include "base/file_util.h"
9 #include "base/numerics/safe_conversions.h"
10 #include "base/path_service.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/component_updater/component_updater_service.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/common/chrome_constants.h"
17 #include "chrome/common/chrome_paths.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "net/cert/crl_set.h"
20 #include "net/ssl/ssl_config_service.h"
22 using component_updater::ComponentUpdateService;
23 using content::BrowserThread;
25 CRLSetFetcher::CRLSetFetcher() : cus_(NULL) {}
27 bool CRLSetFetcher::GetCRLSetFilePath(base::FilePath* path) const {
28 bool ok = PathService::Get(chrome::DIR_USER_DATA, path);
29 if (!ok) {
30 NOTREACHED();
31 return false;
33 *path = path->Append(chrome::kCRLSetFilename);
34 return true;
37 void CRLSetFetcher::StartInitialLoad(ComponentUpdateService* cus) {
38 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
40 cus_ = cus;
42 if (!BrowserThread::PostTask(
43 BrowserThread::FILE, FROM_HERE,
44 base::Bind(&CRLSetFetcher::DoInitialLoadFromDisk, this))) {
45 NOTREACHED();
49 void CRLSetFetcher::DoInitialLoadFromDisk() {
50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
52 base::FilePath crl_set_file_path;
53 if (!GetCRLSetFilePath(&crl_set_file_path))
54 return;
56 LoadFromDisk(crl_set_file_path, &crl_set_);
58 uint32 sequence_of_loaded_crl = 0;
59 if (crl_set_.get())
60 sequence_of_loaded_crl = crl_set_->sequence();
62 // Get updates, advertising the sequence number of the CRL set that we just
63 // loaded, if any.
64 if (!BrowserThread::PostTask(
65 BrowserThread::UI, FROM_HERE,
66 base::Bind(
67 &CRLSetFetcher::RegisterComponent,
68 this,
69 sequence_of_loaded_crl))) {
70 NOTREACHED();
74 void CRLSetFetcher::LoadFromDisk(base::FilePath path,
75 scoped_refptr<net::CRLSet>* out_crl_set) {
76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
78 std::string crl_set_bytes;
79 if (!base::ReadFileToString(path, &crl_set_bytes))
80 return;
82 if (!net::CRLSet::Parse(crl_set_bytes, out_crl_set)) {
83 LOG(WARNING) << "Failed to parse CRL set from " << path.MaybeAsASCII();
84 return;
87 VLOG(1) << "Loaded " << crl_set_bytes.size() << " bytes of CRL set from disk";
89 if (!BrowserThread::PostTask(
90 BrowserThread::IO, FROM_HERE,
91 base::Bind(
92 &CRLSetFetcher::SetCRLSetIfNewer, this, *out_crl_set))) {
93 NOTREACHED();
97 void CRLSetFetcher::SetCRLSetIfNewer(
98 scoped_refptr<net::CRLSet> crl_set) {
99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
101 scoped_refptr<net::CRLSet> old_crl_set(net::SSLConfigService::GetCRLSet());
102 if (old_crl_set.get() && old_crl_set->sequence() > crl_set->sequence()) {
103 LOG(WARNING) << "Refusing to downgrade CRL set from #"
104 << old_crl_set->sequence()
105 << "to #"
106 << crl_set->sequence();
107 } else {
108 net::SSLConfigService::SetCRLSet(crl_set);
109 VLOG(1) << "Installed CRL set #" << crl_set->sequence();
113 // kPublicKeySHA256 is the SHA256 hash of the SubjectPublicKeyInfo of the key
114 // that's used to sign generated CRL sets.
115 static const uint8 kPublicKeySHA256[32] = {
116 0x75, 0xda, 0xf8, 0xcb, 0x77, 0x68, 0x40, 0x33,
117 0x65, 0x4c, 0x97, 0xe5, 0xc5, 0x1b, 0xcd, 0x81,
118 0x7b, 0x1e, 0xeb, 0x11, 0x2c, 0xe1, 0xa4, 0x33,
119 0x8c, 0xf5, 0x72, 0x5e, 0xed, 0xb8, 0x43, 0x97,
122 void CRLSetFetcher::RegisterComponent(uint32 sequence_of_loaded_crl) {
123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
125 component_updater::CrxComponent component;
126 component.pk_hash.assign(kPublicKeySHA256,
127 kPublicKeySHA256 + sizeof(kPublicKeySHA256));
128 component.installer = this;
129 component.name = "CRLSet";
130 component.version = Version(base::UintToString(sequence_of_loaded_crl));
131 component.allow_background_download = false;
132 if (!component.version.IsValid()) {
133 NOTREACHED();
134 component.version = Version("0");
137 if (cus_->RegisterComponent(component) !=
138 ComponentUpdateService::kOk) {
139 NOTREACHED() << "RegisterComponent returned error";
143 void CRLSetFetcher::OnUpdateError(int error) {
144 LOG(WARNING) << "CRLSetFetcher got error " << error
145 << " from component installer";
148 bool CRLSetFetcher::Install(const base::DictionaryValue& manifest,
149 const base::FilePath& unpack_path) {
150 base::FilePath crl_set_file_path =
151 unpack_path.Append(FILE_PATH_LITERAL("crl-set"));
152 base::FilePath save_to;
153 if (!GetCRLSetFilePath(&save_to))
154 return true;
156 std::string crl_set_bytes;
157 if (!base::ReadFileToString(crl_set_file_path, &crl_set_bytes)) {
158 LOG(WARNING) << "Failed to find crl-set file inside CRX";
159 return false;
162 bool is_delta;
163 if (!net::CRLSet::GetIsDeltaUpdate(crl_set_bytes, &is_delta)) {
164 LOG(WARNING) << "GetIsDeltaUpdate failed on CRL set from update CRX";
165 return false;
168 if (!is_delta) {
169 if (!net::CRLSet::Parse(crl_set_bytes, &crl_set_)) {
170 LOG(WARNING) << "Failed to parse CRL set from update CRX";
171 return false;
173 int size = base::checked_cast<int>(crl_set_bytes.size());
174 if (base::WriteFile(save_to, crl_set_bytes.data(), size) != size) {
175 LOG(WARNING) << "Failed to save new CRL set to disk";
176 // We don't return false here because we can still use this CRL set. When
177 // we restart we might revert to an older version, then we'll
178 // advertise the older version to Omaha and everything will still work.
180 } else {
181 scoped_refptr<net::CRLSet> new_crl_set;
182 if (!crl_set_->ApplyDelta(crl_set_bytes, &new_crl_set)) {
183 LOG(WARNING) << "Failed to parse delta CRL set";
184 return false;
186 VLOG(1) << "Applied CRL set delta #" << crl_set_->sequence()
187 << "->#" << new_crl_set->sequence();
188 const std::string new_crl_set_bytes = new_crl_set->Serialize();
189 int size = base::checked_cast<int>(new_crl_set_bytes.size());
190 if (base::WriteFile(save_to, new_crl_set_bytes.data(), size) != size) {
191 LOG(WARNING) << "Failed to save new CRL set to disk";
192 // We don't return false here because we can still use this CRL set. When
193 // we restart we might revert to an older version, then we'll
194 // advertise the older version to Omaha and everything will still work.
196 crl_set_ = new_crl_set;
199 if (!BrowserThread::PostTask(
200 BrowserThread::IO, FROM_HERE,
201 base::Bind(
202 &CRLSetFetcher::SetCRLSetIfNewer, this, crl_set_))) {
203 NOTREACHED();
206 return true;
209 bool CRLSetFetcher::GetInstalledFile(
210 const std::string& file, base::FilePath* installed_file) {
211 return false;
214 CRLSetFetcher::~CRLSetFetcher() {}