Home | History | Annotate | Download | only in cloud
      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 <vector>
      6 
      7 #include "base/bind.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/strings/string_util.h"
     11 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
     12 #include "chrome/browser/policy/cloud/cloud_policy_validator.h"
     13 #include "chrome/browser/policy/cloud/policy_builder.h"
     14 #include "content/public/test/test_browser_thread.h"
     15 #include "crypto/rsa_private_key.h"
     16 #include "testing/gmock/include/gmock/gmock.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 
     19 namespace em = enterprise_management;
     20 
     21 using testing::Invoke;
     22 using testing::Mock;
     23 
     24 namespace policy {
     25 
     26 namespace {
     27 
     28 ACTION_P(CheckStatus, expected_status) {
     29   EXPECT_EQ(expected_status, arg0->status());
     30 };
     31 
     32 class CloudPolicyValidatorTest : public testing::Test {
     33  public:
     34   CloudPolicyValidatorTest()
     35       : loop_(base::MessageLoop::TYPE_UI),
     36         timestamp_(base::Time::UnixEpoch() +
     37                    base::TimeDelta::FromMilliseconds(
     38                        PolicyBuilder::kFakeTimestamp)),
     39         ignore_missing_timestamp_(CloudPolicyValidatorBase::TIMESTAMP_REQUIRED),
     40         ignore_missing_dm_token_(CloudPolicyValidatorBase::DM_TOKEN_REQUIRED),
     41         allow_key_rotation_(true),
     42         existing_dm_token_(PolicyBuilder::kFakeToken),
     43         file_thread_(content::BrowserThread::FILE, &loop_) {
     44     policy_.SetDefaultNewSigningKey();
     45   }
     46 
     47   void Validate(testing::Action<void(UserCloudPolicyValidator*)> check_action) {
     48     // Create a validator.
     49     scoped_ptr<UserCloudPolicyValidator> validator = CreateValidator();
     50 
     51     // Run validation and check the result.
     52     EXPECT_CALL(*this, ValidationCompletion(validator.get())).WillOnce(
     53         check_action);
     54     validator.release()->StartValidation(
     55         base::Bind(&CloudPolicyValidatorTest::ValidationCompletion,
     56                    base::Unretained(this)));
     57     loop_.RunUntilIdle();
     58     Mock::VerifyAndClearExpectations(this);
     59   }
     60 
     61   scoped_ptr<UserCloudPolicyValidator> CreateValidator() {
     62     std::vector<uint8> public_key;
     63     EXPECT_TRUE(
     64         PolicyBuilder::CreateTestSigningKey()->ExportPublicKey(&public_key));
     65     policy_.Build();
     66 
     67     UserCloudPolicyValidator* validator =
     68         UserCloudPolicyValidator::Create(policy_.GetCopy());
     69     validator->ValidateTimestamp(timestamp_, timestamp_,
     70                                  ignore_missing_timestamp_);
     71     validator->ValidateUsername(PolicyBuilder::kFakeUsername);
     72     validator->ValidateDomain(PolicyBuilder::kFakeDomain);
     73     validator->ValidateDMToken(existing_dm_token_, ignore_missing_dm_token_);
     74     validator->ValidatePolicyType(dm_protocol::kChromeUserPolicyType);
     75     validator->ValidatePayload();
     76     validator->ValidateSignature(public_key, allow_key_rotation_);
     77     if (allow_key_rotation_)
     78       validator->ValidateInitialKey();
     79     return make_scoped_ptr(validator);
     80   }
     81 
     82 
     83   void CheckSuccessfulValidation(UserCloudPolicyValidator* validator) {
     84     EXPECT_TRUE(validator->success());
     85     EXPECT_EQ(policy_.policy().SerializeAsString(),
     86               validator->policy()->SerializeAsString());
     87     EXPECT_EQ(policy_.policy_data().SerializeAsString(),
     88               validator->policy_data()->SerializeAsString());
     89     EXPECT_EQ(policy_.payload().SerializeAsString(),
     90               validator->payload()->SerializeAsString());
     91   }
     92 
     93   base::MessageLoop loop_;
     94   base::Time timestamp_;
     95   CloudPolicyValidatorBase::ValidateTimestampOption ignore_missing_timestamp_;
     96   CloudPolicyValidatorBase::ValidateDMTokenOption ignore_missing_dm_token_;
     97   std::string signing_key_;
     98   bool allow_key_rotation_;
     99   std::string existing_dm_token_;
    100 
    101   UserPolicyBuilder policy_;
    102 
    103  private:
    104   MOCK_METHOD1(ValidationCompletion, void(UserCloudPolicyValidator* validator));
    105 
    106   content::TestBrowserThread file_thread_;
    107 
    108   DISALLOW_COPY_AND_ASSIGN(CloudPolicyValidatorTest);
    109 };
    110 
    111 TEST_F(CloudPolicyValidatorTest, SuccessfulValidation) {
    112   Validate(Invoke(this, &CloudPolicyValidatorTest::CheckSuccessfulValidation));
    113 }
    114 
    115 TEST_F(CloudPolicyValidatorTest, SuccessfulRunValidation) {
    116   scoped_ptr<UserCloudPolicyValidator> validator = CreateValidator();
    117   // Run validation immediately (no background tasks).
    118   validator->RunValidation();
    119   CheckSuccessfulValidation(validator.get());
    120 }
    121 
    122 TEST_F(CloudPolicyValidatorTest, SuccessfulRunValidationWithNoExistingDMToken) {
    123   existing_dm_token_.clear();
    124   Validate(Invoke(this, &CloudPolicyValidatorTest::CheckSuccessfulValidation));
    125 }
    126 
    127 TEST_F(CloudPolicyValidatorTest, SuccessfulRunValidationWithNoDMTokens) {
    128   existing_dm_token_.clear();
    129   policy_.policy_data().clear_request_token();
    130   ignore_missing_dm_token_ = CloudPolicyValidatorBase::DM_TOKEN_NOT_REQUIRED;
    131   Validate(Invoke(this, &CloudPolicyValidatorTest::CheckSuccessfulValidation));
    132 }
    133 
    134 TEST_F(CloudPolicyValidatorTest, UsernameCanonicalization) {
    135   policy_.policy_data().set_username(
    136       StringToUpperASCII(std::string(PolicyBuilder::kFakeUsername)));
    137   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_OK));
    138 }
    139 
    140 TEST_F(CloudPolicyValidatorTest, ErrorNoPolicyType) {
    141   policy_.policy_data().clear_policy_type();
    142   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_WRONG_POLICY_TYPE));
    143 }
    144 
    145 TEST_F(CloudPolicyValidatorTest, ErrorWrongPolicyType) {
    146   policy_.policy_data().set_policy_type("invalid");
    147   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_WRONG_POLICY_TYPE));
    148 }
    149 
    150 TEST_F(CloudPolicyValidatorTest, ErrorNoTimestamp) {
    151   policy_.policy_data().clear_timestamp();
    152   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_BAD_TIMESTAMP));
    153 }
    154 
    155 TEST_F(CloudPolicyValidatorTest, IgnoreMissingTimestamp) {
    156   ignore_missing_timestamp_ = CloudPolicyValidatorBase::TIMESTAMP_NOT_REQUIRED;
    157   policy_.policy_data().clear_timestamp();
    158   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_OK));
    159 }
    160 
    161 TEST_F(CloudPolicyValidatorTest, ErrorOldTimestamp) {
    162   base::Time timestamp(timestamp_ - base::TimeDelta::FromMinutes(5));
    163   policy_.policy_data().set_timestamp(
    164       (timestamp - base::Time::UnixEpoch()).InMilliseconds());
    165   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_BAD_TIMESTAMP));
    166 }
    167 
    168 TEST_F(CloudPolicyValidatorTest, ErrorTimestampFromTheFuture) {
    169   base::Time timestamp(timestamp_ + base::TimeDelta::FromMinutes(5));
    170   policy_.policy_data().set_timestamp(
    171       (timestamp - base::Time::UnixEpoch()).InMilliseconds());
    172   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_BAD_TIMESTAMP));
    173 }
    174 
    175 TEST_F(CloudPolicyValidatorTest, ErrorNoRequestToken) {
    176   policy_.policy_data().clear_request_token();
    177   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_WRONG_TOKEN));
    178 }
    179 
    180 TEST_F(CloudPolicyValidatorTest, ErrorNoRequestTokenNotRequired) {
    181   // Even though DMTokens are not required, if the existing policy has a token,
    182   // we should still generate an error if the new policy has none.
    183   policy_.policy_data().clear_request_token();
    184   ignore_missing_dm_token_ = CloudPolicyValidatorBase::DM_TOKEN_NOT_REQUIRED;
    185   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_WRONG_TOKEN));
    186 }
    187 
    188 TEST_F(CloudPolicyValidatorTest, ErrorNoRequestTokenNoTokenPassed) {
    189   // Mimic the first fetch of policy (no existing DM token) - should still
    190   // complain about not having any DMToken.
    191   existing_dm_token_.clear();
    192   policy_.policy_data().clear_request_token();
    193   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_WRONG_TOKEN));
    194 }
    195 
    196 TEST_F(CloudPolicyValidatorTest, ErrorInvalidRequestToken) {
    197   policy_.policy_data().set_request_token("invalid");
    198   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_WRONG_TOKEN));
    199 }
    200 
    201 TEST_F(CloudPolicyValidatorTest, ErrorNoPolicyValue) {
    202   policy_.clear_payload();
    203   Validate(
    204       CheckStatus(CloudPolicyValidatorBase::VALIDATION_POLICY_PARSE_ERROR));
    205 }
    206 
    207 TEST_F(CloudPolicyValidatorTest, ErrorInvalidPolicyValue) {
    208   policy_.clear_payload();
    209   policy_.policy_data().set_policy_value("invalid");
    210   Validate(
    211       CheckStatus(CloudPolicyValidatorBase::VALIDATION_POLICY_PARSE_ERROR));
    212 }
    213 
    214 TEST_F(CloudPolicyValidatorTest, ErrorNoUsername) {
    215   policy_.policy_data().clear_username();
    216   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_BAD_USERNAME));
    217 }
    218 
    219 TEST_F(CloudPolicyValidatorTest, ErrorInvalidUsername) {
    220   policy_.policy_data().set_username("invalid");
    221   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_BAD_USERNAME));
    222 }
    223 
    224 TEST_F(CloudPolicyValidatorTest, ErrorErrorMessage) {
    225   policy_.policy().set_error_message("error");
    226   Validate(
    227       CheckStatus(CloudPolicyValidatorBase::VALIDATION_ERROR_CODE_PRESENT));
    228 }
    229 
    230 TEST_F(CloudPolicyValidatorTest, ErrorErrorCode) {
    231   policy_.policy().set_error_code(42);
    232   Validate(
    233       CheckStatus(CloudPolicyValidatorBase::VALIDATION_ERROR_CODE_PRESENT));
    234 }
    235 
    236 TEST_F(CloudPolicyValidatorTest, ErrorNoSignature) {
    237   policy_.UnsetSigningKey();
    238   policy_.UnsetNewSigningKey();
    239   policy_.policy().clear_policy_data_signature();
    240   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_BAD_SIGNATURE));
    241 }
    242 
    243 TEST_F(CloudPolicyValidatorTest, ErrorInvalidSignature) {
    244   policy_.UnsetSigningKey();
    245   policy_.UnsetNewSigningKey();
    246   policy_.policy().set_policy_data_signature("invalid");
    247   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_BAD_SIGNATURE));
    248 }
    249 
    250 TEST_F(CloudPolicyValidatorTest, ErrorNoPublicKey) {
    251   policy_.UnsetSigningKey();
    252   policy_.UnsetNewSigningKey();
    253   policy_.policy().clear_new_public_key();
    254   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_BAD_SIGNATURE));
    255 }
    256 
    257 TEST_F(CloudPolicyValidatorTest, ErrorInvalidPublicKey) {
    258   policy_.UnsetSigningKey();
    259   policy_.UnsetNewSigningKey();
    260   policy_.policy().set_new_public_key("invalid");
    261   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_BAD_SIGNATURE));
    262 }
    263 
    264 TEST_F(CloudPolicyValidatorTest, ErrorNoPublicKeySignature) {
    265   policy_.UnsetSigningKey();
    266   policy_.UnsetNewSigningKey();
    267   policy_.policy().clear_new_public_key_signature();
    268   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_BAD_SIGNATURE));
    269 }
    270 
    271 TEST_F(CloudPolicyValidatorTest, ErrorInvalidPublicKeySignature) {
    272   policy_.UnsetSigningKey();
    273   policy_.UnsetNewSigningKey();
    274   policy_.policy().set_new_public_key_signature("invalid");
    275   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_BAD_SIGNATURE));
    276 }
    277 
    278 TEST_F(CloudPolicyValidatorTest, ErrorNoRotationAllowed) {
    279   allow_key_rotation_ = false;
    280   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_BAD_SIGNATURE));
    281 }
    282 
    283 TEST_F(CloudPolicyValidatorTest, NoRotation) {
    284   allow_key_rotation_ = false;
    285   policy_.UnsetNewSigningKey();
    286   Validate(CheckStatus(CloudPolicyValidatorBase::VALIDATION_OK));
    287 }
    288 
    289 }  // namespace
    290 
    291 }  // namespace policy
    292