1 // Copyright 2014 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 "chromeos/cryptohome/homedir_methods.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/compiler_specific.h" 10 #include "base/memory/scoped_ptr.h" 11 #include "chromeos/dbus/cryptohome/rpc.pb.h" 12 #include "chromeos/dbus/cryptohome_client.h" 13 #include "chromeos/dbus/dbus_method_call_status.h" 14 #include "chromeos/dbus/dbus_thread_manager.h" 15 #include "chromeos/dbus/mock_cryptohome_client.h" 16 #include "testing/gmock/include/gmock/gmock.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 using testing::_; 20 using testing::Invoke; 21 using testing::WithArg; 22 23 namespace cryptohome { 24 25 namespace { 26 27 MATCHER_P(EqualsProto, expected_proto, "") { 28 std::string expected_value; 29 expected_proto.SerializeToString(&expected_value); 30 std::string actual_value; 31 arg.SerializeToString(&actual_value); 32 return actual_value == expected_value; 33 } 34 35 } // namespace 36 37 const char kUserID[] = "user (at) example.com"; 38 const char kKeyLabel[] = "key_label"; 39 40 const int64 kKeyRevision = 123; 41 const char kProviderData1Name[] = "data_1"; 42 const int64 kProviderData1Number = 12345; 43 const char kProviderData2Name[] = "data_2"; 44 const char kProviderData2Bytes[] = "data_2 bytes"; 45 46 class HomedirMethodsTest : public testing::Test { 47 public: 48 HomedirMethodsTest(); 49 virtual ~HomedirMethodsTest(); 50 51 // testing::Test: 52 virtual void SetUp() OVERRIDE; 53 virtual void TearDown() OVERRIDE; 54 55 void RunProtobufMethodCallback( 56 const chromeos::CryptohomeClient::ProtobufMethodCallback& callback); 57 58 void StoreGetKeyDataExResult( 59 bool success, 60 MountError return_code, 61 const std::vector<KeyDefinition>& key_definitions); 62 63 protected: 64 chromeos::MockCryptohomeClient* cryptohome_client_; 65 66 // The reply that |cryptohome_client_| will make. 67 cryptohome::BaseReply cryptohome_reply_; 68 69 // The results of the most recent |HomedirMethods| method call. 70 bool success_; 71 MountError return_code_; 72 std::vector<KeyDefinition> key_definitions_; 73 74 private: 75 DISALLOW_COPY_AND_ASSIGN(HomedirMethodsTest); 76 }; 77 78 HomedirMethodsTest::HomedirMethodsTest() : cryptohome_client_(NULL), 79 success_(false), 80 return_code_(MOUNT_ERROR_FATAL) { 81 } 82 83 HomedirMethodsTest::~HomedirMethodsTest() { 84 } 85 86 void HomedirMethodsTest::SetUp() { 87 scoped_ptr<chromeos::MockCryptohomeClient> cryptohome_client( 88 new chromeos::MockCryptohomeClient); 89 cryptohome_client_ = cryptohome_client.get(); 90 chromeos::DBusThreadManager::GetSetterForTesting()->SetCryptohomeClient( 91 cryptohome_client.PassAs<chromeos::CryptohomeClient>()); 92 HomedirMethods::Initialize(); 93 } 94 95 void HomedirMethodsTest::TearDown() { 96 HomedirMethods::Shutdown(); 97 chromeos::DBusThreadManager::Shutdown(); 98 } 99 100 void HomedirMethodsTest::RunProtobufMethodCallback( 101 const chromeos::CryptohomeClient::ProtobufMethodCallback& callback) { 102 callback.Run(chromeos::DBUS_METHOD_CALL_SUCCESS, 103 true, 104 cryptohome_reply_); 105 } 106 107 void HomedirMethodsTest::StoreGetKeyDataExResult( 108 bool success, 109 MountError return_code, 110 const std::vector<KeyDefinition>& key_definitions) { 111 success_ = success; 112 return_code_ = return_code; 113 key_definitions_ = key_definitions; 114 } 115 116 // Verifies that the result of a GetKeyDataEx() call is correctly parsed. 117 TEST_F(HomedirMethodsTest, GetKeyDataEx) { 118 AccountIdentifier expected_id; 119 expected_id.set_email(kUserID); 120 const cryptohome::AuthorizationRequest expected_auth; 121 cryptohome::GetKeyDataRequest expected_request; 122 expected_request.mutable_key()->mutable_data()->set_label(kKeyLabel); 123 124 EXPECT_CALL(*cryptohome_client_, 125 GetKeyDataEx(EqualsProto(expected_id), 126 EqualsProto(expected_auth), 127 EqualsProto(expected_request), 128 _)) 129 .Times(1) 130 .WillOnce(WithArg<3>(Invoke( 131 this, 132 &HomedirMethodsTest::RunProtobufMethodCallback))); 133 134 // Set up the reply that |cryptohome_client_| will make. 135 cryptohome::GetKeyDataReply* reply = 136 cryptohome_reply_.MutableExtension(cryptohome::GetKeyDataReply::reply); 137 KeyData* key_data = reply->add_key_data(); 138 key_data->set_type(KeyData::KEY_TYPE_PASSWORD); 139 key_data->set_label(kKeyLabel); 140 key_data->mutable_privileges()->set_update(false); 141 key_data->set_revision(kKeyRevision); 142 key_data->add_authorization_data()->set_type( 143 KeyAuthorizationData::KEY_AUTHORIZATION_TYPE_HMACSHA256); 144 KeyProviderData* data = key_data->mutable_provider_data(); 145 KeyProviderData::Entry* entry = data->add_entry(); 146 entry->set_name(kProviderData1Name); 147 entry->set_number(kProviderData1Number); 148 entry = data->add_entry(); 149 entry->set_name(kProviderData2Name); 150 entry->set_bytes(kProviderData2Bytes); 151 152 // Call GetKeyDataEx(). 153 HomedirMethods::GetInstance()->GetKeyDataEx( 154 Identification(kUserID), 155 kKeyLabel, 156 base::Bind(&HomedirMethodsTest::StoreGetKeyDataExResult, 157 base::Unretained(this))); 158 159 // Verify that the call was successful and the result was correctly parsed. 160 EXPECT_TRUE(success_); 161 EXPECT_EQ(MOUNT_ERROR_NONE, return_code_); 162 ASSERT_EQ(1u, key_definitions_.size()); 163 const KeyDefinition& key_definition = key_definitions_.front(); 164 EXPECT_EQ(KeyDefinition::TYPE_PASSWORD, key_definition.type); 165 EXPECT_EQ(PRIV_MOUNT | PRIV_ADD | PRIV_REMOVE, 166 key_definition.privileges); 167 EXPECT_EQ(kKeyRevision, key_definition.revision); 168 ASSERT_EQ(1u, key_definition.authorization_data.size()); 169 EXPECT_EQ(KeyDefinition::AuthorizationData::TYPE_HMACSHA256, 170 key_definition.authorization_data.front().type); 171 ASSERT_EQ(2u, key_definition.provider_data.size()); 172 const KeyDefinition::ProviderData* provider_data = 173 &key_definition.provider_data[0]; 174 EXPECT_EQ(kProviderData1Name, provider_data->name); 175 ASSERT_TRUE(provider_data->number); 176 EXPECT_EQ(kProviderData1Number, *provider_data->number.get()); 177 EXPECT_FALSE(provider_data->bytes); 178 provider_data = &key_definition.provider_data[1]; 179 EXPECT_EQ(kProviderData2Name, provider_data->name); 180 EXPECT_FALSE(provider_data->number); 181 ASSERT_TRUE(provider_data->bytes); 182 EXPECT_EQ(kProviderData2Bytes, *provider_data->bytes.get()); 183 } 184 185 } // namespace cryptohome 186