blob: 7f328376ef6f70008cae96483ebd267fdda6597f [file] [log] [blame]
Andreea Costinas922fbaf2020-05-28 11:55:22 +02001// Copyright 2020 The Chromium OS 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 "system-proxy/kerberos_client.h"
6
7#include <gmock/gmock.h>
8#include <gtest/gtest.h>
9#include <utility>
10
11#include <base/bind.h>
12#include <base/bind_helpers.h>
13#include <base/callback_helpers.h>
14#include <base/files/file_util.h>
15#include <base/files/scoped_file.h>
16#include <base/memory/weak_ptr.h>
17#include <base/message_loop/message_loop.h>
18#include <base/strings/stringprintf.h>
19#include <brillo/dbus/async_event_sequencer.h>
20#include <brillo/dbus/dbus_object.h>
21#include <brillo/message_loops/base_message_loop.h>
22#include <dbus/kerberos/dbus-constants.h>
23#include <dbus/object_path.h>
24#include <dbus/message.h>
25#include <dbus/mock_bus.h>
26#include <dbus/mock_object_proxy.h>
27#include <kerberos/proto_bindings/kerberos_service.pb.h>
28
29using testing::_;
30using testing::Return;
31
32namespace system_proxy {
33namespace {
34constexpr char kKrb5ConfFile[] = "/tmp/krb5.conf";
35constexpr char kCCacheFile[] = "/tmp/ccache";
36constexpr char kPrincipalName[] = "user@TEST-REALM";
37
38const char kKrb5Settings[] =
39 "[libdefaults]\n"
40 "\tdns_canonicalize_hostname = false\n"
41 "\trdns = false\n"
42 "\tdefault_realm = TEST-REALM\n";
43
44std::string GetUpdatedConfig(const std::string& updated_config) {
45 return base::StringPrintf("%s%s", kKrb5Settings, updated_config.c_str());
46}
47
48} // namespace
49
50// Implementation of KerberosClient that fakes dbus calls to kerberosd.
51class FakeKerberosClient : public KerberosClient {
52 public:
53 explicit FakeKerberosClient(scoped_refptr<dbus::Bus> bus)
54 : KerberosClient(bus) {}
55 FakeKerberosClient(const FakeKerberosClient&) = delete;
56 FakeKerberosClient& operator=(const FakeKerberosClient&) = delete;
57 ~FakeKerberosClient() override = default;
58
59 void SetFakeGetFilesResponse(const std::string& krb5_conf_data,
60 const std::string& ccache_data) {
61 krb5_conf_data_ = krb5_conf_data;
62 ccache_file_data_ = ccache_data;
63 }
64
65 protected:
66 void GetFiles() override {
67 auto dbus_response = dbus::Response::CreateEmpty();
68 dbus::MessageWriter writer(dbus_response.get());
69
70 kerberos::GetKerberosFilesResponse response;
71 kerberos::KerberosFiles files;
72 files.set_krb5conf(krb5_conf_data_);
73 files.set_krb5cc(ccache_file_data_);
74 *response.mutable_files() = files;
75
76 writer.AppendProtoAsArrayOfBytes(response);
77
78 OnGetFilesResponse(dbus_response.get());
79 }
80
81 private:
82 // Values returned by the kerberosd service.
83 std::string krb5_conf_data_;
84 std::string ccache_file_data_;
85};
86
87class KerberosClientTest : public ::testing::Test {
88 public:
89 KerberosClientTest() {
90 mock_kerberos_proxy_ = base::MakeRefCounted<dbus::MockObjectProxy>(
91 bus_.get(), kerberos::kKerberosServiceName,
92 dbus::ObjectPath(kerberos::kKerberosServicePath));
93 EXPECT_CALL(*bus_, GetObjectProxy(kerberos::kKerberosServiceName, _))
94 .WillRepeatedly(Return(mock_kerberos_proxy_.get()));
95 kerberos_client_.reset(new FakeKerberosClient(bus_));
96
97 krb5_conf_file_path_ = base::FilePath(kKrb5ConfFile);
98 ccache_file_path_ = base::FilePath(kCCacheFile);
99
100 brillo_loop_.SetAsCurrent();
101 }
102 KerberosClientTest(const KerberosClientTest&) = delete;
103 KerberosClientTest& operator=(const KerberosClientTest&) = delete;
104 ~KerberosClientTest() override {
105 // Clean-up
106 kerberos_client_->DeleteFiles();
107 }
108
109 protected:
110 std::unique_ptr<FakeKerberosClient> kerberos_client_;
111 base::FilePath krb5_conf_file_path_;
112 base::FilePath ccache_file_path_;
113
114 scoped_refptr<dbus::MockBus> bus_ = new dbus::MockBus(dbus::Bus::Options());
115 scoped_refptr<dbus::MockObjectProxy> mock_kerberos_proxy_;
116
117 base::MessageLoopForIO loop_;
118 brillo::BaseMessageLoop brillo_loop_{&loop_};
119};
120
121// Test that the kerberos files are written and deleted correctly.
122TEST_F(KerberosClientTest, KerberosEnabled) {
123 base::DeleteFile(base::FilePath(kKrb5ConfFile), false /*recursive*/);
124 base::DeleteFile(base::FilePath(kCCacheFile), false /*recursive*/);
125 std::string actual_krb5config;
126 std::string actual_ccache;
127
128 EXPECT_FALSE(
129 base::ReadFileToString(krb5_conf_file_path_, &actual_krb5config));
130 EXPECT_FALSE(base::ReadFileToString(ccache_file_path_, &actual_ccache));
131
132 kerberos_client_->SetFakeGetFilesResponse("fake conf", "fake ccache");
133 kerberos_client_->SetKerberosEnabled(true);
134 kerberos_client_->SetPrincipalName(kPrincipalName);
135
136 ASSERT_TRUE(base::ReadFileToString(krb5_conf_file_path_, &actual_krb5config));
137 ASSERT_TRUE(base::ReadFileToString(ccache_file_path_, &actual_ccache));
138 EXPECT_EQ(GetUpdatedConfig("fake conf"), actual_krb5config);
139 EXPECT_EQ("fake ccache", actual_ccache);
140
141 kerberos_client_->SetKerberosEnabled(false);
142 EXPECT_FALSE(
143 base::ReadFileToString(krb5_conf_file_path_, &actual_krb5config));
144 EXPECT_FALSE(base::ReadFileToString(ccache_file_path_, &actual_ccache));
145}
146
147// Test that the kerberos files are requested again when the
148TEST_F(KerberosClientTest, SignalHandling) {
149 std::string actual_krb5config;
150 std::string actual_ccache;
151
152 kerberos_client_->SetFakeGetFilesResponse("fake conf 1", "fake ccache 1");
153 kerberos_client_->SetKerberosEnabled(true);
154 kerberos_client_->SetPrincipalName(kPrincipalName);
155
156 ASSERT_TRUE(base::ReadFileToString(krb5_conf_file_path_, &actual_krb5config));
157 ASSERT_TRUE(base::ReadFileToString(ccache_file_path_, &actual_ccache));
158 EXPECT_EQ(GetUpdatedConfig("fake conf 1"), actual_krb5config);
159 EXPECT_EQ("fake ccache 1", actual_ccache);
160
161 kerberos_client_->SetFakeGetFilesResponse("fake conf 2", "fake ccache 2");
162 dbus::Signal signal_to_send(kerberos::kKerberosInterface,
163 kerberos::kKerberosFilesChangedSignal);
164 kerberos_client_->OnKerberosFilesChanged(&signal_to_send);
165 ASSERT_TRUE(base::ReadFileToString(krb5_conf_file_path_, &actual_krb5config));
166 ASSERT_TRUE(base::ReadFileToString(ccache_file_path_, &actual_ccache));
167 EXPECT_EQ(GetUpdatedConfig("fake conf 2"), actual_krb5config);
168 EXPECT_EQ("fake ccache 2", actual_ccache);
169}
170
171} // namespace system_proxy