diff options
author | rafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-12 20:45:45 +0000 |
---|---|---|
committer | rafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-12 20:45:45 +0000 |
commit | fbcc4030655802213aab5b731f1180062d232f2d (patch) | |
tree | 41da9d881467d61d9ecde52306f5aacebdcf9d33 /chrome/common/extensions/extension.cc | |
parent | cdb4266b62202b44eb1fb36877398c2cb5504917 (diff) | |
download | chromium_src-fbcc4030655802213aab5b731f1180062d232f2d.zip chromium_src-fbcc4030655802213aab5b731f1180062d232f2d.tar.gz chromium_src-fbcc4030655802213aab5b731f1180062d232f2d.tar.bz2 |
Verify signed .crx extension installations
This is second try of:
http://codereview.chromium.org/115682
that was comitted in in 18189 and reverted.
BUG=12114
R=erikkay,wtc,aa
Review URL: http://codereview.chromium.org/126014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18316 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/extensions/extension.cc')
-rw-r--r-- | chrome/common/extensions/extension.cc | 78 |
1 files changed, 48 insertions, 30 deletions
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index bf7d3a5..73eb417 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -5,10 +5,14 @@ #include "chrome/common/extensions/extension.h" #include "app/resource_bundle.h" +#include "base/basictypes.h" #include "base/file_path.h" #include "base/file_util.h" #include "base/logging.h" #include "base/string_util.h" +#include "base/third_party/nss/blapi.h" +#include "base/third_party/nss/sha256.h" +#include "net/base/base64.h" #include "net/base/net_util.h" #include "chrome/common/extensions/extension_error_reporter.h" #include "chrome/common/extensions/extension_error_utils.h" @@ -33,6 +37,8 @@ namespace { const int kRSAKeySize = 1024; }; +int Extension::id_counter_ = 0; + const char Extension::kManifestFilename[] = "manifest.json"; const wchar_t* Extension::kBackgroundKey = L"background_page"; @@ -40,10 +46,10 @@ const wchar_t* Extension::kContentScriptsKey = L"content_scripts"; const wchar_t* Extension::kCssKey = L"css"; const wchar_t* Extension::kDescriptionKey = L"description"; const wchar_t* Extension::kIconPathKey = L"icon"; -const wchar_t* Extension::kIdKey = L"id"; const wchar_t* Extension::kJsKey = L"js"; const wchar_t* Extension::kMatchesKey = L"matches"; const wchar_t* Extension::kNameKey = L"name"; +const wchar_t* Extension::kPageActionIdKey = L"id"; const wchar_t* Extension::kPageActionsKey = L"page_actions"; const wchar_t* Extension::kPermissionsKey = L"permissions"; const wchar_t* Extension::kPluginsKey = L"plugins"; @@ -71,7 +77,6 @@ const char* Extension::kPageActionTypePermanent = "permanent"; static const wchar_t* kValidThemeKeys[] = { Extension::kDescriptionKey, Extension::kIconPathKey, - Extension::kIdKey, Extension::kNameKey, Extension::kPublicKeyKey, Extension::kSignatureKey, @@ -93,12 +98,12 @@ const char* Extension::kInvalidCssListError = "Required value 'content_scripts[*].css is invalid."; const char* Extension::kInvalidDescriptionError = "Invalid value for 'description'."; -const char* Extension::kInvalidIdError = - "Required value 'id' is missing or invalid."; const char* Extension::kInvalidJsError = "Invalid value for 'content_scripts[*].js[*]'."; const char* Extension::kInvalidJsListError = "Required value 'content_scripts[*].js is invalid."; +const char* Extension::kInvalidKeyError = + "Value 'key' is missing or invalid."; const char* Extension::kInvalidManifestError = "Manifest is missing or invalid."; const char* Extension::kInvalidMatchCountError = @@ -116,6 +121,8 @@ const char* Extension::kInvalidPageActionsListError = "Invalid value for 'page_actions'."; const char* Extension::kInvalidPageActionIconPathError = "Invalid value for 'page_actions[*].icon'."; +const char* Extension::kInvalidPageActionIdError = + "Required value 'id' is missing or invalid."; const char* Extension::kInvalidPageActionTooltipError = "Invalid value for 'page_actions[*].tooltip'."; const char* Extension::kInvalidPageActionTypeValueError = @@ -139,6 +146,8 @@ const char* Extension::kInvalidBackgroundError = "Invalid value for 'background'."; const char* Extension::kInvalidRunAtError = "Invalid value for 'content_scripts[*].run_at'."; +const char* Extension::kInvalidSignatureError = + "Value 'signature' is missing or invalid."; const char* Extension::kInvalidToolstripError = "Invalid value for 'toolstrips[*]'"; const char* Extension::kInvalidToolstripsError = @@ -167,7 +176,8 @@ const char* Extension::kExtensionRegistryPath = "Software\\Google\\Chrome\\Extensions"; #endif -const size_t Extension::kIdSize = 20; // SHA1 (160 bits) == 20 bytes +// first 20 bytes of SHA256 hashed public key. +const size_t Extension::kIdSize = 20; Extension::~Extension() { for (PageActionMap::iterator i = page_actions_.begin(); @@ -230,6 +240,23 @@ Extension::Location Extension::ExternalExtensionInstallType( return Extension::EXTERNAL_PREF; } +bool Extension::GenerateIdFromPublicKey(const std::string& input, + std::string* output) { + CHECK(output); + if (input.length() == 0) + return false; + + const uint8* ubuf = reinterpret_cast<const unsigned char*>(input.data()); + SHA256Context ctx; + SHA256_Begin(&ctx); + SHA256_Update(&ctx, ubuf, input.length()); + uint8 hash[Extension::kIdSize]; + SHA256_End(&ctx, hash, NULL, sizeof(hash)); + *output = StringToLowerASCII(HexEncode(hash, sizeof(hash))); + + return true; +} + // Helper method that loads a UserScript object from a dictionary in the // content_script list of the manifest. bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script, @@ -367,8 +394,8 @@ PageAction* Extension::LoadPageActionHelper( // Read the page action |id|. std::string id; - if (!page_action->GetString(kIdKey, &id)) { - *error = ExtensionErrorUtils::FormatErrorMessage(kInvalidIdError, + if (!page_action->GetString(kPageActionIdKey, &id)) { + *error = ExtensionErrorUtils::FormatErrorMessage(kInvalidPageActionIdError, IntToString(definition_index)); return NULL; } @@ -492,13 +519,14 @@ Extension::Extension(const FilePath& path) { #endif } - // TODO(rafaelw): Move ParsePEMKeyBytes, ProducePEM & FormatPEMForOutput to a // util class in base: // http://code.google.com/p/chromium/issues/detail?id=13572 bool Extension::ParsePEMKeyBytes(const std::string& input, std::string* output) { - CHECK(output); + DCHECK(output); + if (!output) + return false; if (input.length() == 0) return false; @@ -564,33 +592,23 @@ bool Extension::FormatPEMForFileOutput(const std::string input, bool Extension::InitFromValue(const DictionaryValue& source, bool require_id, std::string* error) { - // Initialize id. - if (source.HasKey(kIdKey)) { - if (!source.GetString(kIdKey, &id_)) { - *error = kInvalidIdError; - return false; - } - - // Normalize the string to lowercase, so it can be used as an URL component - // (where GURL will lowercase it). - StringToLowerASCII(&id_); - - // Verify that the id is legal. - if (!IdIsValid(id_)) { - *error = kInvalidIdError; - return false; + if (source.HasKey(kPublicKeyKey)) { + std::string public_key_bytes; + if (!source.GetString(kPublicKeyKey, &public_key_) || + !ParsePEMKeyBytes(public_key_, &public_key_bytes) || + !GenerateIdFromPublicKey(public_key_bytes, &id_)) { + *error = kInvalidKeyError; + return false; } } else if (require_id) { - *error = kInvalidIdError; + *error = kInvalidKeyError; return false; } else { // Generate a random ID - static int counter = 0; - id_ = StringPrintf("%x", counter); - ++counter; + id_ = StringPrintf("%x", NextGeneratedId()); - // pad the string out to 40 chars with zeroes. - id_.insert(0, 40 - id_.length(), '0'); + // pad the string out to kIdSize*2 chars with zeroes. + id_.insert(0, Extension::kIdSize*2 - id_.length(), '0'); } // Initialize the URL. |