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