1 // Copyright 2016 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 #include "chromeos/dbus/authpolicy/authpolicy_client.h"
5
6 #include <utility>
7
8 #include "base/bind.h"
9 #include "base/callback_helpers.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/threading/thread_task_runner_handle.h"
14 #include "chromeos/dbus/authpolicy/fake_authpolicy_client.h"
15 #include "components/account_id/account_id.h"
16 #include "dbus/bus.h"
17 #include "dbus/message.h"
18 #include "dbus/object_proxy.h"
19
20 namespace chromeos {
21
22 namespace {
23
24 // Policy fetch may take up to 300 seconds. To ensure that a second policy
25 // fetch queuing after the first one can succeed (e.g. user policy following
26 // device policy), the D-Bus timeout needs to be at least twice that value.
27 // JoinADDomain() is an exception since it's always guaranteed to be the first
28 // call.
29 constexpr int kSlowDbusTimeoutMilliseconds = 630 * 1000;
30
31 AuthPolicyClient* g_instance = nullptr;
32
GetErrorFromReader(dbus::MessageReader * reader)33 authpolicy::ErrorType GetErrorFromReader(dbus::MessageReader* reader) {
34 int32_t int_error;
35 if (!reader->PopInt32(&int_error)) {
36 DLOG(ERROR) << "AuthPolicyClient: Failed to get an error from the response";
37 return authpolicy::ERROR_DBUS_FAILURE;
38 }
39 if (int_error < 0 || int_error >= authpolicy::ERROR_COUNT)
40 return authpolicy::ERROR_UNKNOWN;
41 return static_cast<authpolicy::ErrorType>(int_error);
42 }
43
GetErrorAndProto(dbus::Response * response,google::protobuf::MessageLite * protobuf)44 authpolicy::ErrorType GetErrorAndProto(
45 dbus::Response* response,
46 google::protobuf::MessageLite* protobuf) {
47 if (!response) {
48 DLOG(ERROR) << "Auth: Failed to call to authpolicy";
49 return authpolicy::ERROR_DBUS_FAILURE;
50 }
51 dbus::MessageReader reader(response);
52 const authpolicy::ErrorType error(GetErrorFromReader(&reader));
53
54 if (error != authpolicy::ERROR_NONE)
55 return error;
56
57 if (!reader.PopArrayOfBytesAsProto(protobuf)) {
58 DLOG(ERROR) << "Failed to parse protobuf.";
59 return authpolicy::ERROR_DBUS_FAILURE;
60 }
61 return authpolicy::ERROR_NONE;
62 }
63
64 class AuthPolicyClientImpl : public AuthPolicyClient {
65 public:
AuthPolicyClientImpl()66 AuthPolicyClientImpl() {}
67
68 ~AuthPolicyClientImpl() override = default;
69
70 // AuthPolicyClient override.
JoinAdDomain(const authpolicy::JoinDomainRequest & request,int password_fd,JoinCallback callback)71 void JoinAdDomain(const authpolicy::JoinDomainRequest& request,
72 int password_fd,
73 JoinCallback callback) override {
74 dbus::MethodCall method_call(authpolicy::kAuthPolicyInterface,
75 authpolicy::kJoinADDomainMethod);
76 dbus::MessageWriter writer(&method_call);
77 if (!writer.AppendProtoAsArrayOfBytes(request)) {
78 base::ThreadTaskRunnerHandle::Get()->PostTask(
79 FROM_HERE,
80 base::BindOnce(std::move(callback), authpolicy::ERROR_DBUS_FAILURE,
81 std::string()));
82 return;
83 }
84 writer.AppendFileDescriptor(password_fd);
85 proxy_->CallMethod(
86 &method_call, kSlowDbusTimeoutMilliseconds,
87 base::BindOnce(&AuthPolicyClientImpl::HandleJoinCallback,
88 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
89 }
90
AuthenticateUser(const authpolicy::AuthenticateUserRequest & request,int password_fd,AuthCallback callback)91 void AuthenticateUser(const authpolicy::AuthenticateUserRequest& request,
92 int password_fd,
93 AuthCallback callback) override {
94 dbus::MethodCall method_call(authpolicy::kAuthPolicyInterface,
95 authpolicy::kAuthenticateUserMethod);
96 dbus::MessageWriter writer(&method_call);
97 if (!writer.AppendProtoAsArrayOfBytes(request)) {
98 base::ThreadTaskRunnerHandle::Get()->PostTask(
99 FROM_HERE,
100 base::BindOnce(std::move(callback), authpolicy::ERROR_DBUS_FAILURE,
101 authpolicy::ActiveDirectoryAccountInfo()));
102 return;
103 }
104 writer.AppendFileDescriptor(password_fd);
105 proxy_->CallMethod(
106 &method_call, kSlowDbusTimeoutMilliseconds,
107 base::BindOnce(&AuthPolicyClientImpl::HandleCallback<
108 authpolicy::ActiveDirectoryAccountInfo>,
109 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
110 }
111
GetUserStatus(const authpolicy::GetUserStatusRequest & request,GetUserStatusCallback callback)112 void GetUserStatus(const authpolicy::GetUserStatusRequest& request,
113 GetUserStatusCallback callback) override {
114 dbus::MethodCall method_call(authpolicy::kAuthPolicyInterface,
115 authpolicy::kGetUserStatusMethod);
116 dbus::MessageWriter writer(&method_call);
117 if (!writer.AppendProtoAsArrayOfBytes(request)) {
118 base::ThreadTaskRunnerHandle::Get()->PostTask(
119 FROM_HERE,
120 base::BindOnce(std::move(callback), authpolicy::ERROR_DBUS_FAILURE,
121 authpolicy::ActiveDirectoryUserStatus()));
122 return;
123 }
124 proxy_->CallMethod(
125 &method_call, kSlowDbusTimeoutMilliseconds,
126 base::BindOnce(&AuthPolicyClientImpl::HandleCallback<
127 authpolicy::ActiveDirectoryUserStatus>,
128 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
129 }
130
GetUserKerberosFiles(const std::string & object_guid,GetUserKerberosFilesCallback callback)131 void GetUserKerberosFiles(const std::string& object_guid,
132 GetUserKerberosFilesCallback callback) override {
133 dbus::MethodCall method_call(authpolicy::kAuthPolicyInterface,
134 authpolicy::kGetUserKerberosFilesMethod);
135 dbus::MessageWriter writer(&method_call);
136 writer.AppendString(object_guid);
137 proxy_->CallMethod(
138 &method_call, kSlowDbusTimeoutMilliseconds,
139 base::BindOnce(
140 &AuthPolicyClientImpl::HandleCallback<authpolicy::KerberosFiles>,
141 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
142 }
143
RefreshDevicePolicy(RefreshPolicyCallback callback)144 void RefreshDevicePolicy(RefreshPolicyCallback callback) override {
145 dbus::MethodCall method_call(authpolicy::kAuthPolicyInterface,
146 authpolicy::kRefreshDevicePolicyMethod);
147 proxy_->CallMethod(
148 &method_call, kSlowDbusTimeoutMilliseconds,
149 base::BindOnce(&AuthPolicyClientImpl::HandleRefreshPolicyCallback,
150 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
151 }
152
RefreshUserPolicy(const AccountId & account_id,RefreshPolicyCallback callback)153 void RefreshUserPolicy(const AccountId& account_id,
154 RefreshPolicyCallback callback) override {
155 DCHECK(account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY);
156 dbus::MethodCall method_call(authpolicy::kAuthPolicyInterface,
157 authpolicy::kRefreshUserPolicyMethod);
158 dbus::MessageWriter writer(&method_call);
159 writer.AppendString(account_id.GetObjGuid());
160 proxy_->CallMethod(
161 &method_call, kSlowDbusTimeoutMilliseconds,
162 base::BindOnce(&AuthPolicyClientImpl::HandleRefreshPolicyCallback,
163 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
164 }
165
ConnectToSignal(const std::string & signal_name,dbus::ObjectProxy::SignalCallback signal_callback,dbus::ObjectProxy::OnConnectedCallback on_connected_callback)166 void ConnectToSignal(
167 const std::string& signal_name,
168 dbus::ObjectProxy::SignalCallback signal_callback,
169 dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
170 proxy_->ConnectToSignal(authpolicy::kAuthPolicyInterface, signal_name,
171 std::move(signal_callback),
172 std::move(on_connected_callback));
173 }
174
WaitForServiceToBeAvailable(dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback)175 void WaitForServiceToBeAvailable(
176 dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback)
177 override {
178 proxy_->WaitForServiceToBeAvailable(std::move(callback));
179 }
180
Init(dbus::Bus * bus)181 void Init(dbus::Bus* bus) {
182 bus_ = bus;
183 proxy_ = bus_->GetObjectProxy(
184 authpolicy::kAuthPolicyServiceName,
185 dbus::ObjectPath(authpolicy::kAuthPolicyServicePath));
186 }
187
188 private:
HandleRefreshPolicyCallback(RefreshPolicyCallback callback,dbus::Response * response)189 void HandleRefreshPolicyCallback(RefreshPolicyCallback callback,
190 dbus::Response* response) {
191 if (!response) {
192 DLOG(ERROR) << "RefreshDevicePolicy: failed to call to authpolicy";
193 std::move(callback).Run(authpolicy::ERROR_DBUS_FAILURE);
194 return;
195 }
196 dbus::MessageReader reader(response);
197 std::move(callback).Run(GetErrorFromReader(&reader));
198 }
199
HandleJoinCallback(JoinCallback callback,dbus::Response * response)200 void HandleJoinCallback(JoinCallback callback, dbus::Response* response) {
201 if (!response) {
202 DLOG(ERROR) << "Join: Couldn't call to authpolicy";
203 std::move(callback).Run(authpolicy::ERROR_DBUS_FAILURE, std::string());
204 return;
205 }
206
207 dbus::MessageReader reader(response);
208 authpolicy::ErrorType error = GetErrorFromReader(&reader);
209 std::string machine_domain;
210 if (error == authpolicy::ERROR_NONE) {
211 if (!reader.PopString(&machine_domain))
212 error = authpolicy::ERROR_DBUS_FAILURE;
213 }
214 std::move(callback).Run(error, machine_domain);
215 }
216
217 template <class T>
HandleCallback(base::OnceCallback<void (authpolicy::ErrorType error,const T & response)> callback,dbus::Response * response)218 void HandleCallback(base::OnceCallback<void(authpolicy::ErrorType error,
219 const T& response)> callback,
220 dbus::Response* response) {
221 T proto;
222 authpolicy::ErrorType error(GetErrorAndProto(response, &proto));
223 std::move(callback).Run(error, proto);
224 }
225
226 dbus::Bus* bus_ = nullptr;
227 dbus::ObjectProxy* proxy_ = nullptr;
228
229 // Note: This should remain the last member so it'll be destroyed and
230 // invalidate its weak pointers before any other members are destroyed.
231 base::WeakPtrFactory<AuthPolicyClientImpl> weak_ptr_factory_{this};
232
233 DISALLOW_COPY_AND_ASSIGN(AuthPolicyClientImpl);
234 };
235
236 } // namespace
237
AuthPolicyClient()238 AuthPolicyClient::AuthPolicyClient() {
239 DCHECK(!g_instance);
240 g_instance = this;
241 }
242
~AuthPolicyClient()243 AuthPolicyClient::~AuthPolicyClient() {
244 DCHECK_EQ(this, g_instance);
245 g_instance = nullptr;
246 }
247
248 // static
Initialize(dbus::Bus * bus)249 void AuthPolicyClient::Initialize(dbus::Bus* bus) {
250 DCHECK(bus);
251 (new AuthPolicyClientImpl)->Init(bus);
252 }
253
254 // static
InitializeFake()255 void AuthPolicyClient::InitializeFake() {
256 if (!FakeAuthPolicyClient::Get())
257 new FakeAuthPolicyClient();
258 }
259
260 // static
Shutdown()261 void AuthPolicyClient::Shutdown() {
262 DCHECK(g_instance);
263 delete g_instance;
264 }
265
266 // static
Get()267 AuthPolicyClient* AuthPolicyClient::Get() {
268 return g_instance;
269 }
270
271 } // namespace chromeos
272