Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: trunk/src/chrome/browser/component_updater/component_unpacker.cc

Issue 17551004: Revert 207805 "Differential updates for components. We are addin..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/component_updater/component_unpacker.h" 5 #include "chrome/browser/component_updater/component_unpacker.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/file_util.h" 10 #include "base/file_util.h"
11 #include "base/json/json_file_value_serializer.h" 11 #include "base/json/json_file_value_serializer.h"
12 #include "base/memory/scoped_handle.h" 12 #include "base/memory/scoped_handle.h"
13 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/stringprintf.h" 14 #include "base/strings/stringprintf.h"
15 #include "chrome/browser/component_updater/component_patcher.h"
16 #include "chrome/browser/component_updater/component_updater_service.h" 15 #include "chrome/browser/component_updater/component_updater_service.h"
17 #include "chrome/common/extensions/extension_constants.h" 16 #include "chrome/common/extensions/extension_constants.h"
18 #include "crypto/secure_hash.h" 17 #include "crypto/secure_hash.h"
19 #include "crypto/signature_verifier.h" 18 #include "crypto/signature_verifier.h"
20 #include "extensions/common/crx_file.h" 19 #include "extensions/common/crx_file.h"
21 #include "third_party/zlib/google/zip.h" 20 #include "third_party/zlib/google/zip.h"
22 21
23 using crypto::SecureHash; 22 using crypto::SecureHash;
24 23
25 namespace { 24 namespace {
26
27 // This class makes sure that the CRX digital signature is valid 25 // This class makes sure that the CRX digital signature is valid
28 // and well formed. 26 // and well formed.
29 class CRXValidator { 27 class CRXValidator {
30 public: 28 public:
31 explicit CRXValidator(FILE* crx_file) : valid_(false), delta_(false) { 29 explicit CRXValidator(FILE* crx_file) : valid_(false) {
32 extensions::CrxFile::Header header; 30 extensions::CrxFile::Header header;
33 size_t len = fread(&header, 1, sizeof(header), crx_file); 31 size_t len = fread(&header, 1, sizeof(header), crx_file);
34 if (len < sizeof(header)) 32 if (len < sizeof(header))
35 return; 33 return;
36 34
37 extensions::CrxFile::Error error; 35 extensions::CrxFile::Error error;
38 scoped_ptr<extensions::CrxFile> crx( 36 scoped_ptr<extensions::CrxFile> crx(
39 extensions::CrxFile::Parse(header, &error)); 37 extensions::CrxFile::Parse(header, &error));
40 if (!crx.get()) 38 if (!crx.get())
41 return; 39 return;
42 delta_ = extensions::CrxFile::HeaderIsDelta(header);
43 40
44 std::vector<uint8> key(header.key_size); 41 std::vector<uint8> key(header.key_size);
45 len = fread(&key[0], sizeof(uint8), header.key_size, crx_file); 42 len = fread(&key[0], sizeof(uint8), header.key_size, crx_file);
46 if (len < header.key_size) 43 if (len < header.key_size)
47 return; 44 return;
48 45
49 std::vector<uint8> signature(header.signature_size); 46 std::vector<uint8> signature(header.signature_size);
50 len = fread(&signature[0], sizeof(uint8), header.signature_size, crx_file); 47 len = fread(&signature[0], sizeof(uint8), header.signature_size, crx_file);
51 if (len < header.signature_size) 48 if (len < header.signature_size)
52 return; 49 return;
(...skipping 15 matching lines...) Expand all
68 65
69 if (!verifier.VerifyFinal()) 66 if (!verifier.VerifyFinal())
70 return; 67 return;
71 68
72 public_key_.swap(key); 69 public_key_.swap(key);
73 valid_ = true; 70 valid_ = true;
74 } 71 }
75 72
76 bool valid() const { return valid_; } 73 bool valid() const { return valid_; }
77 74
78 bool delta() const { return delta_; }
79
80 const std::vector<uint8>& public_key() const { return public_key_; } 75 const std::vector<uint8>& public_key() const { return public_key_; }
81 76
82 private: 77 private:
83 bool valid_; 78 bool valid_;
84 bool delta_;
85 std::vector<uint8> public_key_; 79 std::vector<uint8> public_key_;
86 }; 80 };
87 81
88 // Deserialize the CRX manifest. The top level must be a dictionary. 82 // Deserialize the CRX manifest. The top level must be a dictionary.
89 // TODO(cpu): add a specific attribute check to a component json that the 83 // TODO(cpu): add a specific attribute check to a component json that the
90 // extension unpacker will reject, so that a component cannot be installed 84 // extension unpacker will reject, so that a component cannot be installed
91 // as an extension. 85 // as an extension.
92 base::DictionaryValue* ReadManifest(const base::FilePath& unpack_path) { 86 base::DictionaryValue* ReadManifest(const base::FilePath& unpack_path) {
93 base::FilePath manifest = 87 base::FilePath manifest =
94 unpack_path.Append(FILE_PATH_LITERAL("manifest.json")); 88 unpack_path.Append(FILE_PATH_LITERAL("manifest.json"));
95 if (!file_util::PathExists(manifest)) 89 if (!file_util::PathExists(manifest))
96 return NULL; 90 return NULL;
97 JSONFileValueSerializer serializer(manifest); 91 JSONFileValueSerializer serializer(manifest);
98 std::string error; 92 std::string error;
99 scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error)); 93 scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error));
100 if (!root.get()) 94 if (!root.get())
101 return NULL; 95 return NULL;
102 if (!root->IsType(base::Value::TYPE_DICTIONARY)) 96 if (!root->IsType(base::Value::TYPE_DICTIONARY))
103 return NULL; 97 return NULL;
104 return static_cast<base::DictionaryValue*>(root.release()); 98 return static_cast<base::DictionaryValue*>(root.release());
105 } 99 }
106 100
107 // Deletes a path if it exists, and then creates a directory there.
108 // Returns true if and only if these operations were successful.
109 // This method doesn't take any special steps to prevent files from
110 // being inserted into the target directory by another process or thread.
111 bool MakeEmptyDirectory(const base::FilePath& path) {
112 if (file_util::PathExists(path)) {
113 if (!file_util::Delete(path, true))
114 return false;
115 }
116 if (!file_util::CreateDirectory(path))
117 return false;
118 return true;
119 }
120
121 } // namespace. 101 } // namespace.
122 102
123 ComponentUnpacker::ComponentUnpacker(const std::vector<uint8>& pk_hash, 103 ComponentUnpacker::ComponentUnpacker(const std::vector<uint8>& pk_hash,
124 const base::FilePath& path, 104 const base::FilePath& path,
125 const std::string& fingerprint,
126 ComponentPatcher* patcher,
127 ComponentInstaller* installer) 105 ComponentInstaller* installer)
128 : error_(kNone), 106 : error_(kNone) {
129 extended_error_(0) {
130 if (pk_hash.empty() || path.empty()) { 107 if (pk_hash.empty() || path.empty()) {
131 error_ = kInvalidParams; 108 error_ = kInvalidParams;
132 return; 109 return;
133 } 110 }
134 // First, validate the CRX header and signature. As of today 111 // First, validate the CRX header and signature. As of today
135 // this is SHA1 with RSA 1024. 112 // this is SHA1 with RSA 1024.
136 ScopedStdioHandle file(file_util::OpenFile(path, "rb")); 113 ScopedStdioHandle file(file_util::OpenFile(path, "rb"));
137 if (!file.get()) { 114 if (!file.get()) {
138 error_ = kInvalidFile; 115 error_ = kInvalidFile;
139 return; 116 return;
(...skipping 11 matching lines...) Expand all
151 uint8 hash[32]; 128 uint8 hash[32];
152 scoped_ptr<SecureHash> sha256(SecureHash::Create(SecureHash::SHA256)); 129 scoped_ptr<SecureHash> sha256(SecureHash::Create(SecureHash::SHA256));
153 sha256->Update(&(validator.public_key()[0]), validator.public_key().size()); 130 sha256->Update(&(validator.public_key()[0]), validator.public_key().size());
154 sha256->Finish(hash, arraysize(hash)); 131 sha256->Finish(hash, arraysize(hash));
155 132
156 if (!std::equal(pk_hash.begin(), pk_hash.end(), hash)) { 133 if (!std::equal(pk_hash.begin(), pk_hash.end(), hash)) {
157 error_ = kInvalidId; 134 error_ = kInvalidId;
158 return; 135 return;
159 } 136 }
160 // We want the temporary directory to be unique and yet predictable, so 137 // We want the temporary directory to be unique and yet predictable, so
161 // we can easily find the package in an end user machine. 138 // we can easily find the package in a end user machine.
162 const std::string dir( 139 std::string dir(
163 base::StringPrintf("CRX_%s", base::HexEncode(hash, 6).c_str())); 140 base::StringPrintf("CRX_%s", base::HexEncode(hash, 6).c_str()));
164 unpack_path_ = path.DirName().AppendASCII(dir.c_str()); 141 unpack_path_ = path.DirName().AppendASCII(dir.c_str());
165 if (!MakeEmptyDirectory(unpack_path_)) { 142 if (file_util::DirectoryExists(unpack_path_)) {
143 if (!file_util::Delete(unpack_path_, true)) {
144 unpack_path_.clear();
145 error_ = kUzipPathError;
146 return;
147 }
148 }
149 if (!file_util::CreateDirectory(unpack_path_)) {
166 unpack_path_.clear(); 150 unpack_path_.clear();
167 error_ = kUnzipPathError; 151 error_ = kUzipPathError;
168 return; 152 return;
169 } 153 }
170 if (validator.delta()) { // Package is a diff package. 154 if (!zip::Unzip(path, unpack_path_)) {
171 // We want a different temp directory for the delta files; we'll put the 155 error_ = kUnzipFailed;
172 // patch output into unpack_path_. 156 return;
173 std::string dir(
174 base::StringPrintf("CRX_%s_diff", base::HexEncode(hash, 6).c_str()));
175 base::FilePath unpack_diff_path = path.DirName().AppendASCII(dir.c_str());
176 if (!MakeEmptyDirectory(unpack_diff_path)) {
177 error_ = kUnzipPathError;
178 return;
179 }
180 if (!zip::Unzip(path, unpack_diff_path)) {
181 error_ = kUnzipFailed;
182 return;
183 }
184 ComponentUnpacker::Error result = DifferentialUpdatePatch(unpack_diff_path,
185 unpack_path_,
186 patcher,
187 installer,
188 &extended_error_);
189 file_util::Delete(unpack_diff_path, true);
190 unpack_diff_path.clear();
191 error_ = result;
192 if (error_ != kNone) {
193 return;
194 }
195 } else {
196 // Package is a normal update/install; unzip it into unpack_path_ directly.
197 if (!zip::Unzip(path, unpack_path_)) {
198 error_ = kUnzipFailed;
199 return;
200 }
201 } 157 }
202 scoped_ptr<base::DictionaryValue> manifest(ReadManifest(unpack_path_)); 158 scoped_ptr<base::DictionaryValue> manifest(ReadManifest(unpack_path_));
203 if (!manifest.get()) { 159 if (!manifest.get()) {
204 error_ = kBadManifest; 160 error_ = kBadManifest;
205 return; 161 return;
206 } 162 }
207 // Write the fingerprint to disk.
208 if (static_cast<int>(fingerprint.size()) !=
209 file_util::WriteFile(
210 unpack_path_.Append(FILE_PATH_LITERAL("manifest.fingerprint")),
211 fingerprint.c_str(),
212 fingerprint.size())) {
213 error_ = kFingerprintWriteFailed;
214 return;
215 }
216 if (!installer->Install(*manifest, unpack_path_)) { 163 if (!installer->Install(*manifest, unpack_path_)) {
217 error_ = kInstallerError; 164 error_ = kInstallerError;
218 return; 165 return;
219 } 166 }
220 // Installation successful. The directory is not our concern now. 167 // Installation successful. The directory is not our concern now.
221 unpack_path_.clear(); 168 unpack_path_.clear();
222 } 169 }
223 170
224 ComponentUnpacker::~ComponentUnpacker() { 171 ComponentUnpacker::~ComponentUnpacker() {
225 if (!unpack_path_.empty()) 172 if (!unpack_path_.empty()) {
226 file_util::Delete(unpack_path_, true); 173 file_util::Delete(unpack_path_, true);
174 }
227 } 175 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698