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

Side by Side Diff: chrome/browser/extensions/extensions_service.cc

Issue 115682: Verify signed .crx extension installations (Closed)
Patch Set: moved extensions consts back to extensions_service (was causing compile errors on mac & linux) Created 11 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
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/extensions/extensions_service.h" 5 #include "chrome/browser/extensions/extensions_service.h"
6 6
7 #include "app/l10n_util.h" 7 #include "app/l10n_util.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/crypto/signature_verifier.h"
9 #include "base/file_util.h" 10 #include "base/file_util.h"
10 #include "base/gfx/png_encoder.h" 11 #include "base/gfx/png_encoder.h"
11 #include "base/scoped_handle.h" 12 #include "base/scoped_handle.h"
12 #include "base/scoped_temp_dir.h" 13 #include "base/scoped_temp_dir.h"
13 #include "base/string_util.h" 14 #include "base/string_util.h"
14 #include "base/third_party/nss/blapi.h" 15 #include "base/third_party/nss/blapi.h"
15 #include "base/third_party/nss/sha256.h" 16 #include "base/third_party/nss/sha256.h"
16 #include "base/thread.h" 17 #include "base/thread.h"
17 #include "base/values.h" 18 #include "base/values.h"
18 #include "net/base/file_stream.h" 19 #include "net/base/file_stream.h"
19 #include "chrome/browser/browser.h" 20 #include "chrome/browser/browser.h"
20 #include "chrome/browser/browser_list.h" 21 #include "chrome/browser/browser_list.h"
21 #include "chrome/browser/browser_process.h" 22 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/chrome_thread.h" 23 #include "chrome/browser/chrome_thread.h"
24 #include "chrome/browser/extensions/extension_creator.h"
23 #include "chrome/browser/extensions/extension_browser_event_router.h" 25 #include "chrome/browser/extensions/extension_browser_event_router.h"
24 #include "chrome/browser/extensions/extension_process_manager.h" 26 #include "chrome/browser/extensions/extension_process_manager.h"
25 #include "chrome/browser/profile.h" 27 #include "chrome/browser/profile.h"
26 #include "chrome/browser/utility_process_host.h" 28 #include "chrome/browser/utility_process_host.h"
27 #include "chrome/common/chrome_switches.h" 29 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/extensions/extension.h" 30 #include "chrome/common/extensions/extension.h"
29 #include "chrome/common/extensions/extension_error_reporter.h" 31 #include "chrome/common/extensions/extension_error_reporter.h"
30 #include "chrome/common/extensions/extension_unpacker.h" 32 #include "chrome/common/extensions/extension_unpacker.h"
31 #include "chrome/common/json_value_serializer.h" 33 #include "chrome/common/json_value_serializer.h"
32 #include "chrome/common/notification_service.h" 34 #include "chrome/common/notification_service.h"
33 #include "chrome/common/pref_names.h" 35 #include "chrome/common/pref_names.h"
34 #include "chrome/common/pref_service.h" 36 #include "chrome/common/pref_service.h"
35 #include "chrome/common/zip.h" 37 #include "chrome/common/zip.h"
36 #include "chrome/common/url_constants.h" 38 #include "chrome/common/url_constants.h"
37 #include "grit/chromium_strings.h" 39 #include "grit/chromium_strings.h"
38 #include "grit/generated_resources.h" 40 #include "grit/generated_resources.h"
41 #include "net/base/base64.h"
39 #include "third_party/skia/include/core/SkBitmap.h" 42 #include "third_party/skia/include/core/SkBitmap.h"
40 43
41 #if defined(OS_WIN) 44 #if defined(OS_WIN)
42 #include "app/win_util.h" 45 #include "app/win_util.h"
43 #include "base/registry.h" 46 #include "base/registry.h"
44 #include "base/win_util.h" 47 #include "base/win_util.h"
45 #endif 48 #endif
46 49
47 // ExtensionsService. 50 // ExtensionsService.
48 51
52 const char ExtensionsService::kExtensionHeaderMagic[] = "Cr24";
53
49 const char* ExtensionsService::kInstallDirectoryName = "Extensions"; 54 const char* ExtensionsService::kInstallDirectoryName = "Extensions";
50 const char* ExtensionsService::kCurrentVersionFileName = "Current Version"; 55 const char* ExtensionsService::kCurrentVersionFileName = "Current Version";
51 const char* ExtensionsServiceBackend::kTempExtensionName = "TEMP_INSTALL"; 56 const char* ExtensionsServiceBackend::kTempExtensionName = "TEMP_INSTALL";
52 57
53 namespace { 58 namespace {
54 59
55 // A preference that keeps track of extension settings. This is a dictionary 60 // A preference that keeps track of extension settings. This is a dictionary
56 // object read from the Preferences file, keyed off of extension id's. 61 // object read from the Preferences file, keyed off of extension id's.
57 const wchar_t kExternalExtensionsPref[] = L"extensions.settings"; 62 const wchar_t kExternalExtensionsPref[] = L"extensions.settings";
58 63
(...skipping 16 matching lines...) Expand all
75 80
76 #endif 81 #endif
77 82
78 // A marker file to indicate that an extension was installed from an external 83 // A marker file to indicate that an extension was installed from an external
79 // source. 84 // source.
80 const char kExternalInstallFile[] = "EXTERNAL_INSTALL"; 85 const char kExternalInstallFile[] = "EXTERNAL_INSTALL";
81 86
82 // A temporary subdirectory where we unpack extensions. 87 // A temporary subdirectory where we unpack extensions.
83 const char* kUnpackExtensionDir = "TEMP_UNPACK"; 88 const char* kUnpackExtensionDir = "TEMP_UNPACK";
84 89
85 // The version of the extension package that this code understands. 90 // Unpacking errors
86 const uint32 kExpectedVersion = 1; 91 const char* kBadMagicNumberError = "Bad magic number";
92 const char* kBadHeaderSizeError = "Excessively large key or signature";
93 const char* kBadVersionNumberError = "Bad version number";
94 const char* kInvalidExtensionHeaderError = "Invalid extension header";
95 const char* kInvalidPublicKeyError = "Invalid public key";
96 const char* kInvalidSignatureError = "Invalid signature";
97 const char* kSignatureVerificationFailed = "Signature verification failed";
98 const char* kSignatureVerificationInitFailed =
99 "Signature verification initialization failed. This is most likely "
100 "caused by a public key in the wrong format (should encode algorithm).";
87 } 101 }
88 102
89 // This class coordinates an extension unpack task which is run in a separate 103 // This class coordinates an extension unpack task which is run in a separate
90 // process. Results are sent back to this class, which we route to the 104 // process. Results are sent back to this class, which we route to the
91 // ExtensionServiceBackend. 105 // ExtensionServiceBackend.
92 class ExtensionsServiceBackend::UnpackerClient 106 class ExtensionsServiceBackend::UnpackerClient
93 : public UtilityProcessHost::Client { 107 : public UtilityProcessHost::Client {
94 public: 108 public:
95 UnpackerClient(ExtensionsServiceBackend* backend, 109 UnpackerClient(ExtensionsServiceBackend* backend,
96 const FilePath& extension_path, 110 const FilePath& extension_path,
111 const std::string& public_key,
97 const std::string& expected_id, 112 const std::string& expected_id,
98 bool from_external) 113 bool from_external)
99 : backend_(backend), extension_path_(extension_path), 114 : backend_(backend), extension_path_(extension_path),
100 expected_id_(expected_id), from_external_(from_external), 115 public_key_(public_key), expected_id_(expected_id),
101 got_response_(false) { 116 from_external_(from_external), got_response_(false) {
102 } 117 }
103 118
104 // Starts the unpack task. We call back to the backend when the task is done, 119 // Starts the unpack task. We call back to the backend when the task is done,
105 // or a problem occurs. 120 // or a problem occurs.
106 void Start() { 121 void Start() {
107 AddRef(); // balanced in OnUnpackExtensionReply() 122 AddRef(); // balanced in OnUnpackExtensionReply()
108 123
109 // TODO(mpcomplete): handle multiple installs 124 // TODO(mpcomplete): handle multiple installs
110 FilePath temp_dir = backend_->install_directory_.AppendASCII( 125 FilePath temp_dir = backend_->install_directory_.AppendASCII(
111 kUnpackExtensionDir); 126 kUnpackExtensionDir);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 &images)) { 171 &images)) {
157 OnUnpackExtensionFailed("Couldn't read image data from disk."); 172 OnUnpackExtensionFailed("Couldn't read image data from disk.");
158 } else { 173 } else {
159 OnUnpackExtensionSucceededImpl(manifest, images); 174 OnUnpackExtensionSucceededImpl(manifest, images);
160 } 175 }
161 } 176 }
162 177
163 void OnUnpackExtensionSucceededImpl( 178 void OnUnpackExtensionSucceededImpl(
164 const DictionaryValue& manifest, 179 const DictionaryValue& manifest,
165 const ExtensionUnpacker::DecodedImages& images) { 180 const ExtensionUnpacker::DecodedImages& images) {
181 // Add our public key into the parsed manifest. We want it to be saved so
182 // that we can later refer to it (eg for generating ids, validating
183 // signatures, etc).
184 // The const_cast is hacky, but seems like the right thing here, rather than
185 // making a full copy just to make this change.
186 const_cast<DictionaryValue*>(&manifest)->SetString(
187 Extension::kPublicKeyKey, public_key_);
188
166 // The extension was unpacked to the temp dir inside our unpacking dir. 189 // The extension was unpacked to the temp dir inside our unpacking dir.
167 FilePath extension_dir = temp_extension_path_.DirName().AppendASCII( 190 FilePath extension_dir = temp_extension_path_.DirName().AppendASCII(
168 ExtensionsServiceBackend::kTempExtensionName); 191 ExtensionsServiceBackend::kTempExtensionName);
169 backend_->OnExtensionUnpacked(extension_path_, extension_dir, 192 backend_->OnExtensionUnpacked(extension_path_, extension_dir,
170 expected_id_, from_external_, 193 expected_id_, from_external_,
171 manifest, images); 194 manifest, images);
172 Cleanup(); 195 Cleanup();
173 } 196 }
174 197
175 virtual void OnUnpackExtensionFailed(const std::string& error_message) { 198 virtual void OnUnpackExtensionFailed(const std::string& error_message) {
(...skipping 16 matching lines...) Expand all
192 MessageLoop* file_loop) { 215 MessageLoop* file_loop) {
193 UtilityProcessHost* host = new UtilityProcessHost(rdh, this, file_loop); 216 UtilityProcessHost* host = new UtilityProcessHost(rdh, this, file_loop);
194 host->StartExtensionUnpacker(temp_extension_path_); 217 host->StartExtensionUnpacker(temp_extension_path_);
195 } 218 }
196 219
197 scoped_refptr<ExtensionsServiceBackend> backend_; 220 scoped_refptr<ExtensionsServiceBackend> backend_;
198 221
199 // The path to the crx file that we're installing. 222 // The path to the crx file that we're installing.
200 FilePath extension_path_; 223 FilePath extension_path_;
201 224
225 // The public key of the extension we're installing.
226 std::string public_key_;
227
202 // The path to the copy of the crx file in the temporary directory where we're 228 // The path to the copy of the crx file in the temporary directory where we're
203 // unpacking it. 229 // unpacking it.
204 FilePath temp_extension_path_; 230 FilePath temp_extension_path_;
205 231
206 // The ID we expect this extension to have, if any. 232 // The ID we expect this extension to have, if any.
207 std::string expected_id_; 233 std::string expected_id_;
208 234
209 // True if this is being installed from an external source. 235 // True if this is being installed from an external source.
210 bool from_external_; 236 bool from_external_;
211 237
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 392
367 NotificationService::current()->Notify( 393 NotificationService::current()->Notify(
368 NotificationType::EXTENSIONS_LOADED, 394 NotificationType::EXTENSIONS_LOADED,
369 NotificationService::AllSources(), 395 NotificationService::AllSources(),
370 Details<ExtensionList>(&enabled_extensions)); 396 Details<ExtensionList>(&enabled_extensions));
371 397
372 delete new_extensions; 398 delete new_extensions;
373 } 399 }
374 400
375 void ExtensionsService::OnExtensionInstalled(Extension* extension, 401 void ExtensionsService::OnExtensionInstalled(Extension* extension,
376 bool update) { 402 Extension::InstallType install_type) {
377 UpdateExtensionPref(ASCIIToWide(extension->id()), kState, 403 UpdateExtensionPref(ASCIIToWide(extension->id()), kState,
378 Value::CreateIntegerValue(Extension::ENABLED), false); 404 Value::CreateIntegerValue(Extension::ENABLED), false);
379 UpdateExtensionPref(ASCIIToWide(extension->id()), kLocation, 405 UpdateExtensionPref(ASCIIToWide(extension->id()), kLocation,
380 Value::CreateIntegerValue(Extension::INTERNAL), true); 406 Value::CreateIntegerValue(Extension::INTERNAL), true);
381 407
382 // If the extension is a theme, tell the profile (and therefore ThemeProvider) 408 // If the extension is a theme, tell the profile (and therefore ThemeProvider)
383 // to apply it. 409 // to apply it.
384 if (extension->IsTheme()) { 410 if (extension->IsTheme()) {
385 NotificationService::current()->Notify( 411 NotificationService::current()->Notify(
386 NotificationType::THEME_INSTALLED, 412 NotificationType::THEME_INSTALLED,
387 NotificationService::AllSources(), 413 NotificationService::AllSources(),
388 Details<Extension>(extension)); 414 Details<Extension>(extension));
389 } else { 415 } else {
390 NotificationService::current()->Notify( 416 NotificationService::current()->Notify(
391 NotificationType::EXTENSION_INSTALLED, 417 NotificationType::EXTENSION_INSTALLED,
392 NotificationService::AllSources(), 418 NotificationService::AllSources(),
393 Details<Extension>(extension)); 419 Details<Extension>(extension));
394 } 420 }
395 } 421 }
396 422
397 void ExtensionsService::OnExternalExtensionInstalled( 423 void ExtensionsService::OnExternalExtensionInstalled(
398 const std::string& id, Extension::Location location) { 424 const std::string& id, Extension::Location location) {
399 DCHECK(Extension::IsExternalLocation(location)); 425 DCHECK(Extension::IsExternalLocation(location));
400 UpdateExtensionPref(ASCIIToWide(id), kState, 426 UpdateExtensionPref(ASCIIToWide(id), kState,
401 Value::CreateIntegerValue(Extension::ENABLED), false); 427 Value::CreateIntegerValue(Extension::ENABLED), false);
402 UpdateExtensionPref(ASCIIToWide(id), kLocation, 428 UpdateExtensionPref(ASCIIToWide(id), kLocation,
403 Value::CreateIntegerValue(location), true); 429 Value::CreateIntegerValue(location), true);
404 } 430 }
405 431
406 void ExtensionsService::OnExtensionVersionReinstalled(const std::string& id) { 432 void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) {
407 Extension* extension = GetExtensionByID(id); 433 Extension* extension = GetExtensionByID(id);
408 if (extension && extension->IsTheme()) { 434 if (extension && extension->IsTheme()) {
409 NotificationService::current()->Notify( 435 NotificationService::current()->Notify(
410 NotificationType::THEME_INSTALLED, 436 NotificationType::THEME_INSTALLED,
411 NotificationService::AllSources(), 437 NotificationService::AllSources(),
412 Details<Extension>(extension)); 438 Details<Extension>(extension));
413 } 439 }
414 } 440 }
415 441
416 Extension* ExtensionsService::GetExtensionByID(std::string id) { 442 Extension* ExtensionsService::GetExtensionByID(std::string id) {
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 Extension* extension = LoadExtension(extension_path, 643 Extension* extension = LoadExtension(extension_path,
618 false); // don't require ID 644 false); // don't require ID
619 if (extension) { 645 if (extension) {
620 extension->set_location(Extension::LOAD); 646 extension->set_location(Extension::LOAD);
621 ExtensionList* extensions = new ExtensionList; 647 ExtensionList* extensions = new ExtensionList;
622 extensions->push_back(extension); 648 extensions->push_back(extension);
623 ReportExtensionsLoaded(extensions); 649 ReportExtensionsLoaded(extensions);
624 } 650 }
625 } 651 }
626 652
653 DictionaryValue* ExtensionsServiceBackend::ReadManifest(FilePath manifest_path,
654 std::string* error) {
655 JSONFileValueSerializer serializer(manifest_path);
656 scoped_ptr<Value> root(serializer.Deserialize(error));
657 if (!root.get())
658 return NULL;
659
660 if (!root->IsType(Value::TYPE_DICTIONARY)) {
661 *error = Extension::kInvalidManifestError;
662 return NULL;
663 }
664
665 return static_cast<DictionaryValue*>(root.release());
666 }
667
627 Extension* ExtensionsServiceBackend::LoadExtension( 668 Extension* ExtensionsServiceBackend::LoadExtension(
628 const FilePath& extension_path, bool require_id) { 669 const FilePath& extension_path, bool require_id) {
629 FilePath manifest_path = 670 FilePath manifest_path =
630 extension_path.AppendASCII(Extension::kManifestFilename); 671 extension_path.AppendASCII(Extension::kManifestFilename);
631 if (!file_util::PathExists(manifest_path)) { 672 if (!file_util::PathExists(manifest_path)) {
632 ReportExtensionLoadError(extension_path, Extension::kInvalidManifestError); 673 ReportExtensionLoadError(extension_path, Extension::kInvalidManifestError);
633 return NULL; 674 return NULL;
634 } 675 }
635 676
636 JSONFileValueSerializer serializer(manifest_path);
637 std::string error; 677 std::string error;
638 scoped_ptr<Value> root(serializer.Deserialize(&error)); 678 scoped_ptr<DictionaryValue> root(ReadManifest(manifest_path, &error));
639 if (!root.get()) { 679 if (!root.get()) {
640 ReportExtensionLoadError(extension_path, error); 680 ReportExtensionLoadError(extension_path, error);
641 return NULL; 681 return NULL;
642 } 682 }
643 683
644 if (!root->IsType(Value::TYPE_DICTIONARY)) {
645 ReportExtensionLoadError(extension_path, Extension::kInvalidManifestError);
646 return NULL;
647 }
648
649 scoped_ptr<Extension> extension(new Extension(extension_path)); 684 scoped_ptr<Extension> extension(new Extension(extension_path));
650 if (!extension->InitFromValue(*static_cast<DictionaryValue*>(root.get()), 685 if (!extension->InitFromValue(*root.get(), require_id, &error)) {
651 require_id, &error)) {
652 ReportExtensionLoadError(extension_path, error); 686 ReportExtensionLoadError(extension_path, error);
653 return NULL; 687 return NULL;
654 } 688 }
655 689
656 FilePath external_marker = extension_path.AppendASCII(kExternalInstallFile); 690 FilePath external_marker = extension_path.AppendASCII(kExternalInstallFile);
657 if (file_util::PathExists(external_marker)) { 691 if (file_util::PathExists(external_marker)) {
658 extension->set_location( 692 extension->set_location(
659 extension->ExternalExtensionInstallType(registry_path_)); 693 extension->ExternalExtensionInstallType(registry_path_));
660 } else { 694 } else {
661 extension->set_location(Extension::INTERNAL); 695 extension->set_location(Extension::INTERNAL);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 dir.AppendASCII(ExtensionsService::kCurrentVersionFileName); 790 dir.AppendASCII(ExtensionsService::kCurrentVersionFileName);
757 if (file_util::PathExists(current_version)) { 791 if (file_util::PathExists(current_version)) {
758 if (file_util::ReadFileToString(current_version, version_string)) { 792 if (file_util::ReadFileToString(current_version, version_string)) {
759 TrimWhitespace(*version_string, TRIM_ALL, version_string); 793 TrimWhitespace(*version_string, TRIM_ALL, version_string);
760 return true; 794 return true;
761 } 795 }
762 } 796 }
763 return false; 797 return false;
764 } 798 }
765 799
766 bool ExtensionsServiceBackend::CheckCurrentVersion( 800 Extension::InstallType ExtensionsServiceBackend::CompareToInstalledVersion(
801 const std::string& id,
767 const std::string& new_version_str, 802 const std::string& new_version_str,
768 const std::string& current_version_str, 803 std::string *current_version_str) {
769 const FilePath& dest_dir) { 804 CHECK(current_version_str);
805 FilePath dir(install_directory_.AppendASCII(id.c_str()));
806 if (!ReadCurrentVersion(dir, current_version_str))
807 return Extension::NEW_INSTALL;
808
770 scoped_ptr<Version> current_version( 809 scoped_ptr<Version> current_version(
771 Version::GetVersionFromString(current_version_str)); 810 Version::GetVersionFromString(*current_version_str));
772 scoped_ptr<Version> new_version( 811 scoped_ptr<Version> new_version(
773 Version::GetVersionFromString(new_version_str)); 812 Version::GetVersionFromString(new_version_str));
774 if (current_version->CompareTo(*new_version) >= 0) { 813 int comp = new_version->CompareTo(*current_version);
775 // Verify that the directory actually exists. If it doesn't we'll return 814 if (comp > 0)
776 // true so that the install code will repair the broken installation. 815 return Extension::UPGRADE;
777 // TODO(erikkay): A further step would be to verify that the extension 816 else if (comp == 0)
778 // has actually loaded successfully. 817 return Extension::REINSTALL;
779 FilePath version_dir = dest_dir.AppendASCII(current_version_str); 818 else
780 if (file_util::PathExists(version_dir)) { 819 return Extension::DOWNGRADE;
781 std::string id = WideToASCII(dest_dir.BaseName().ToWStringHack()); 820 }
782 StringToLowerASCII(&id); 821
783 ReportExtensionVersionReinstalled(id); 822 bool ExtensionsServiceBackend::NeedsReinstall(const std::string& id,
784 return false; 823 const std::string& current_version) {
785 } 824 // Verify that the directory actually exists.
786 } 825 // TODO(erikkay): A further step would be to verify that the extension
787 return true; 826 // has actually loaded successfully.
827 FilePath dir(install_directory_.AppendASCII(id.c_str()));
828 FilePath version_dir(dir.AppendASCII(current_version));
829 return !file_util::PathExists(version_dir);
788 } 830 }
789 831
790 bool ExtensionsServiceBackend::InstallDirSafely(const FilePath& source_dir, 832 bool ExtensionsServiceBackend::InstallDirSafely(const FilePath& source_dir,
791 const FilePath& dest_dir) { 833 const FilePath& dest_dir) {
792 if (file_util::PathExists(dest_dir)) { 834 if (file_util::PathExists(dest_dir)) {
793 // By the time we get here, it should be safe to assume that this directory 835 // By the time we get here, it should be safe to assume that this directory
794 // is not currently in use (it's not the current active version). 836 // is not currently in use (it's not the current active version).
795 if (!file_util::Delete(dest_dir, true)) { 837 if (!file_util::Delete(dest_dir, true)) {
796 ReportExtensionInstallError(source_dir, 838 ReportExtensionInstallError(source_dir,
797 "Can't delete existing version directory."); 839 "Can't delete existing version directory.");
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
864 LOG(INFO) << "Installing extension " << extension_path.value(); 906 LOG(INFO) << "Installing extension " << extension_path.value();
865 907
866 frontend_ = frontend; 908 frontend_ = frontend;
867 alert_on_error_ = true; 909 alert_on_error_ = true;
868 910
869 bool from_external = false; 911 bool from_external = false;
870 InstallOrUpdateExtension(extension_path, std::string(), from_external); 912 InstallOrUpdateExtension(extension_path, std::string(), from_external);
871 } 913 }
872 914
873 void ExtensionsServiceBackend::InstallOrUpdateExtension( 915 void ExtensionsServiceBackend::InstallOrUpdateExtension(
874 const FilePath& extension_path, const std::string& expected_id, 916 const FilePath& extension_path,
917 const std::string& expected_id,
875 bool from_external) { 918 bool from_external) {
876 UnpackerClient* client = 919 std::string actual_public_key;
877 new UnpackerClient(this, extension_path, expected_id, from_external); 920 if (!ValidateSignature(extension_path, &actual_public_key))
921 return; // Failures reported within ValidateSignature().
922
923 UnpackerClient* client = new UnpackerClient(
924 this, extension_path, actual_public_key, expected_id, from_external);
878 client->Start(); 925 client->Start();
879 } 926 }
880 927
928 bool ExtensionsServiceBackend::ValidateSignature(const FilePath& extension_path,
929 std::string* key_out) {
930 ScopedStdioHandle file(file_util::OpenFile(extension_path, "rb"));
931 if (!file.get()) {
932 ReportExtensionInstallError(extension_path, "Could not open file.");
933 return NULL;
934 }
935
936 // Read and verify the header.
937 ExtensionsService::ExtensionHeader header;
938 size_t len;
939
940 // TODO(erikkay): Yuck. I'm not a big fan of this kind of code, but it
941 // appears that we don't have any endian/alignment aware serialization
942 // code in the code base. So for now, this assumes that we're running
943 // on a little endian machine with 4 byte alignment.
944 len = fread(&header, 1, sizeof(ExtensionsService::ExtensionHeader),
945 file.get());
946 if (len < sizeof(ExtensionsService::ExtensionHeader)) {
947 ReportExtensionInstallError(extension_path, kInvalidExtensionHeaderError);
948 return false;
949 }
950 if (strncmp(ExtensionsService::kExtensionHeaderMagic, header.magic,
951 sizeof(header.magic))) {
952 ReportExtensionInstallError(extension_path, kBadMagicNumberError);
953 return false;
954 }
955 if (header.version != ExtensionsService::kCurrentVersion) {
956 ReportExtensionInstallError(extension_path, kBadVersionNumberError);
957 return false;
958 }
959 if (header.key_size > ExtensionsService::kMaxPublicKeySize ||
960 header.signature_size > ExtensionsService::kMaxSignatureSize) {
961 ReportExtensionInstallError(extension_path, kBadHeaderSizeError);
962 return false;
963 }
964
965 std::vector<uint8> key;
966 key.resize(header.key_size);
967 len = fread(&key.front(), sizeof(uint8), header.key_size, file.get());
968 if (len < header.key_size) {
969 ReportExtensionInstallError(extension_path, kInvalidPublicKeyError);
970 return false;
971 }
972
973 std::vector<uint8> signature;
974 signature.resize(header.signature_size);
975 len = fread(&signature.front(), sizeof(uint8), header.signature_size,
976 file.get());
977 if (len < header.signature_size) {
978 ReportExtensionInstallError(extension_path, kInvalidSignatureError);
979 return false;
980 }
981
982 // Note: this structure is an ASN.1 which encodes the algorithm used
983 // with its parameters. This is defined in PKCS #1 v2.1 (RFC 3447).
984 // It is encoding: { OID sha1WithRSAEncryption PARAMETERS NULL }
985 // TODO(aa): This needs to be factored away someplace common.
986 const uint8 signature_algorithm[15] = {
987 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
988 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00
989 };
990
991 base::SignatureVerifier verifier;
992 if (!verifier.VerifyInit(signature_algorithm,
993 sizeof(signature_algorithm),
994 &signature.front(),
995 signature.size(),
996 &key.front(),
997 key.size())) {
998 ReportExtensionInstallError(extension_path,
999 kSignatureVerificationInitFailed);
1000 return false;
1001 }
1002
1003 unsigned char buf[1 << 12];
1004 while ((len = fread(buf, 1, sizeof(buf), file.get())) > 0)
1005 verifier.VerifyUpdate(buf, len);
1006
1007 if (!verifier.VerifyFinal()) {
1008 ReportExtensionInstallError(extension_path, kSignatureVerificationFailed);
1009 return false;
1010 }
1011
1012 net::Base64Encode(std::string(reinterpret_cast<char*>(&key.front()),
1013 key.size()), key_out);
1014 return true;
1015 }
1016
881 void ExtensionsServiceBackend::OnExtensionUnpacked( 1017 void ExtensionsServiceBackend::OnExtensionUnpacked(
882 const FilePath& extension_path, 1018 const FilePath& extension_path,
883 const FilePath& temp_extension_dir, 1019 const FilePath& temp_extension_dir,
884 const std::string expected_id, 1020 const std::string expected_id,
885 bool from_external, 1021 bool from_external,
886 const DictionaryValue& manifest, 1022 const DictionaryValue& manifest,
887 const std::vector< Tuple2<SkBitmap, FilePath> >& images) { 1023 const std::vector< Tuple2<SkBitmap, FilePath> >& images) {
888 Extension extension; 1024 Extension extension;
889 std::string error; 1025 std::string error;
890 if (!extension.InitFromValue(manifest, 1026 if (!extension.InitFromValue(manifest,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
933 error_msg += expected_id; 1069 error_msg += expected_id;
934 error_msg += ")"; 1070 error_msg += ")";
935 ReportExtensionInstallError(extension_path, error_msg); 1071 ReportExtensionInstallError(extension_path, error_msg);
936 return; 1072 return;
937 } 1073 }
938 1074
939 // <profile>/Extensions/<id> 1075 // <profile>/Extensions/<id>
940 FilePath dest_dir = install_directory_.AppendASCII(extension.id()); 1076 FilePath dest_dir = install_directory_.AppendASCII(extension.id());
941 std::string version = extension.VersionString(); 1077 std::string version = extension.VersionString();
942 std::string current_version; 1078 std::string current_version;
943 bool was_update = false; 1079 Extension::InstallType install_type =
944 if (ReadCurrentVersion(dest_dir, &current_version)) { 1080 CompareToInstalledVersion(extension.id(), version, &current_version);
945 if (!CheckCurrentVersion(version, current_version, dest_dir)) 1081
1082 // Do not allow downgrade.
1083 if (install_type == Extension::DOWNGRADE) {
1084 ReportExtensionInstallError(extension_path,
1085 "Error: Attempt to downgrade extension from more recent version.");
1086 return;
1087 }
1088
1089 if (install_type == Extension::REINSTALL) {
1090 if (NeedsReinstall(extension.id(), current_version)) {
1091 // Treat corrupted existing installation as new install case.
1092 install_type = Extension::NEW_INSTALL;
1093 } else {
1094 // The client may use this as a signal (to switch themes, for instance).
1095 ReportExtensionOverinstallAttempted(extension.id());
946 return; 1096 return;
947 was_update = true; 1097 }
948 } 1098 }
949 1099
950 // Write our parsed manifest back to disk, to ensure it doesn't contain an 1100 // Write our parsed manifest back to disk, to ensure it doesn't contain an
951 // exploitable bug that can be used to compromise the browser. 1101 // exploitable bug that can be used to compromise the browser.
952 std::string manifest_json; 1102 std::string manifest_json;
953 JSONStringValueSerializer serializer(&manifest_json); 1103 JSONStringValueSerializer serializer(&manifest_json);
954 serializer.set_pretty_print(true); 1104 serializer.set_pretty_print(true);
955 if (!serializer.Serialize(manifest)) { 1105 if (!serializer.Serialize(manifest)) {
956 ReportExtensionInstallError(extension_path, 1106 ReportExtensionInstallError(extension_path,
957 "Error serializing manifest.json."); 1107 "Error serializing manifest.json.");
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 // occurs before the normal startup so we just let startup pick them up. We 1186 // occurs before the normal startup so we just let startup pick them up. We
1037 // notify on installation of external extensions because we need to update 1187 // notify on installation of external extensions because we need to update
1038 // the preferences for these extensions to reflect that they've just been 1188 // the preferences for these extensions to reflect that they've just been
1039 // installed. 1189 // installed.
1040 if (!from_external) { 1190 if (!from_external) {
1041 Extension* extension = LoadExtension(version_dir, true); // require id 1191 Extension* extension = LoadExtension(version_dir, true); // require id
1042 CHECK(extension); 1192 CHECK(extension);
1043 1193
1044 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod( 1194 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(
1045 frontend_, &ExtensionsService::OnExtensionInstalled, extension, 1195 frontend_, &ExtensionsService::OnExtensionInstalled, extension,
1046 was_update)); 1196 install_type));
1047 1197
1048 // Only one extension, but ReportExtensionsLoaded can handle multiple, 1198 // Only one extension, but ReportExtensionsLoaded can handle multiple,
1049 // so we need to construct a list. 1199 // so we need to construct a list.
1050 scoped_ptr<ExtensionList> extensions(new ExtensionList); 1200 scoped_ptr<ExtensionList> extensions(new ExtensionList);
1051 extensions->push_back(extension); 1201 extensions->push_back(extension);
1052 LOG(INFO) << "Done."; 1202 LOG(INFO) << "Done.";
1053 // Hand off ownership of the loaded extensions to the frontend. 1203 // Hand off ownership of the loaded extensions to the frontend.
1054 ReportExtensionsLoaded(extensions.release()); 1204 ReportExtensionsLoaded(extensions.release());
1055 } else { 1205 } else {
1056 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod( 1206 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(
1057 frontend_, &ExtensionsService::OnExternalExtensionInstalled, 1207 frontend_, &ExtensionsService::OnExternalExtensionInstalled,
1058 extension.id(), 1208 extension.id(),
1059 extension.ExternalExtensionInstallType(registry_path_))); 1209 extension.ExternalExtensionInstallType(registry_path_)));
1060 } 1210 }
1061 1211
1062 scoped_version_dir.Take(); 1212 scoped_version_dir.Take();
1063 } 1213 }
1064 1214
1065 void ExtensionsServiceBackend::ReportExtensionInstallError( 1215 void ExtensionsServiceBackend::ReportExtensionInstallError(
1066 const FilePath& extension_path, const std::string &error) { 1216 const FilePath& extension_path, const std::string &error) {
1067 1217
1068 // TODO(erikkay): note that this isn't guaranteed to work properly on Linux. 1218 // TODO(erikkay): note that this isn't guaranteed to work properly on Linux.
1069 std::string path_str = WideToASCII(extension_path.ToWStringHack()); 1219 std::string path_str = WideToASCII(extension_path.ToWStringHack());
1070 std::string message = 1220 std::string message =
1071 StringPrintf("Could not install extension from '%s'. %s", 1221 StringPrintf("Could not install extension from '%s'. %s",
1072 path_str.c_str(), error.c_str()); 1222 path_str.c_str(), error.c_str());
1073 ExtensionErrorReporter::GetInstance()->ReportError(message, alert_on_error_); 1223 ExtensionErrorReporter::GetInstance()->ReportError(message, alert_on_error_);
1074 } 1224 }
1075 1225
1076 void ExtensionsServiceBackend::ReportExtensionVersionReinstalled( 1226 void ExtensionsServiceBackend::ReportExtensionOverinstallAttempted(
1077 const std::string& id) { 1227 const std::string& id) {
1078 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod( 1228 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(
1079 frontend_, &ExtensionsService::OnExtensionVersionReinstalled, id)); 1229 frontend_, &ExtensionsService::OnExtensionOverinstallAttempted, id));
1080 } 1230 }
1081 1231
1082 bool ExtensionsServiceBackend::ShouldSkipInstallingExtension( 1232 bool ExtensionsServiceBackend::ShouldSkipInstallingExtension(
1083 const std::set<std::string>& ids_to_ignore, 1233 const std::set<std::string>& ids_to_ignore,
1084 const std::string& id) { 1234 const std::string& id) {
1085 if (ids_to_ignore.find(id) != ids_to_ignore.end()) { 1235 if (ids_to_ignore.find(id) != ids_to_ignore.end()) {
1086 LOG(INFO) << "Skipping uninstalled external extension " << id; 1236 LOG(INFO) << "Skipping uninstalled external extension " << id;
1087 return true; 1237 return true;
1088 } 1238 }
1089 return false; 1239 return false;
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1255 // not a big deal though, because we'll notice next time we startup that the 1405 // not a big deal though, because we'll notice next time we startup that the
1256 // Current Version file is gone and finish the delete then. 1406 // Current Version file is gone and finish the delete then.
1257 if (!file_util::Delete(extension_directory, true)) { 1407 if (!file_util::Delete(extension_directory, true)) {
1258 LOG(WARNING) << "Could not delete directory for extension " 1408 LOG(WARNING) << "Could not delete directory for extension "
1259 << extension_id; 1409 << extension_id;
1260 } 1410 }
1261 } 1411 }
1262 1412
1263 bool ExtensionsServiceBackend::ShouldInstall(const std::string& id, 1413 bool ExtensionsServiceBackend::ShouldInstall(const std::string& id,
1264 const std::string& version) { 1414 const std::string& version) {
1265 FilePath dir(install_directory_.AppendASCII(id.c_str()));
1266 std::string current_version; 1415 std::string current_version;
1267 if (ReadCurrentVersion(dir, &current_version)) { 1416 Extension::InstallType install_type = CompareToInstalledVersion(id, version,
1268 return CheckCurrentVersion(version, current_version, dir); 1417 &current_version);
1269 } 1418
1270 return true; 1419 if (install_type == Extension::DOWNGRADE)
1420 return false;
1421
1422 return (install_type == Extension::UPGRADE ||
1423 install_type == Extension::NEW_INSTALL ||
1424 NeedsReinstall(id, current_version));
1271 } 1425 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extensions_service.h ('k') | chrome/browser/extensions/extensions_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698