blob: 41b7ac43f9376a1f79dfc36a6890ae916e577a5e [file] [log] [blame]
Garrick Evans5fe2a4f2021-02-03 17:04:48 +09001// Copyright 2021 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 "dns-proxy/proxy.h"
6
7#include <fcntl.h>
8#include <sys/stat.h>
9
10#include <memory>
11#include <utility>
Garrick Evans2ca050d2021-02-09 18:21:36 +090012#include <vector>
Garrick Evans5fe2a4f2021-02-03 17:04:48 +090013
14#include <chromeos/patchpanel/net_util.h>
15#include <chromeos/patchpanel/dbus/fake_client.h>
16#include <dbus/mock_bus.h>
Garrick Evans77e9a132021-05-13 10:51:13 +090017#include <dbus/mock_object_proxy.h>
Garrick Evans5fe2a4f2021-02-03 17:04:48 +090018#include <gmock/gmock.h>
19#include <gtest/gtest.h>
20#include <shill/dbus/client/fake_client.h>
21#include <shill/dbus-constants.h>
22#include <shill/dbus-proxy-mocks.h>
23
24namespace dns_proxy {
Jason Jeremy Iman1bb71c22021-01-26 21:49:55 +090025namespace {
26constexpr base::TimeDelta kRequestTimeout = base::TimeDelta::FromSeconds(10000);
Jason Jeremy Iman845f2932021-01-31 16:12:13 +090027constexpr base::TimeDelta kRequestRetryDelay =
28 base::TimeDelta::FromMilliseconds(200);
29constexpr int32_t kRequestMaxRetry = 1;
30
Jason Jeremy Iman1bb71c22021-01-26 21:49:55 +090031} // namespace
Garrick Evans5fe2a4f2021-02-03 17:04:48 +090032using org::chromium::flimflam::ManagerProxyInterface;
33using org::chromium::flimflam::ManagerProxyMock;
34using testing::_;
Garrick Evans09646fe2021-04-27 14:38:41 +090035using testing::DoAll;
Garrick Evansd41fdbf2021-03-03 09:15:48 +090036using testing::IsEmpty;
Garrick Evans5fe2a4f2021-02-03 17:04:48 +090037using testing::Return;
Garrick Evansadde9852021-02-15 20:16:53 +090038using testing::SetArgPointee;
Garrick Evans2ca050d2021-02-09 18:21:36 +090039using testing::StrEq;
Garrick Evans5fe2a4f2021-02-03 17:04:48 +090040
41class FakeShillClient : public shill::FakeClient {
42 public:
43 FakeShillClient(scoped_refptr<dbus::Bus> bus,
44 ManagerProxyInterface* manager_proxy)
45 : shill::FakeClient(bus), manager_proxy_(manager_proxy) {}
46
47 std::unique_ptr<shill::Client::ManagerPropertyAccessor> ManagerProperties(
48 const base::TimeDelta& timeout) const override {
49 return std::make_unique<shill::Client::ManagerPropertyAccessor>(
50 manager_proxy_);
51 }
52
Garrick Evansadde9852021-02-15 20:16:53 +090053 std::unique_ptr<shill::Client::Device> DefaultDevice(
54 bool exclude_vpn) override {
55 return std::move(default_device_);
56 }
57
Garrick Evans5fe2a4f2021-02-03 17:04:48 +090058 bool IsInitialized() const { return init_; }
59
Garrick Evansadde9852021-02-15 20:16:53 +090060 std::unique_ptr<shill::Client::Device> default_device_;
61
Garrick Evans5fe2a4f2021-02-03 17:04:48 +090062 private:
63 ManagerProxyInterface* manager_proxy_;
64};
65
66class FakePatchpanelClient : public patchpanel::FakeClient {
67 public:
68 FakePatchpanelClient() = default;
69 ~FakePatchpanelClient() = default;
70
71 void SetConnectNamespaceResult(
72 int fd, const patchpanel::ConnectNamespaceResponse& resp) {
73 ns_fd_ = fd;
74 ns_resp_ = resp;
75 }
76
77 std::pair<base::ScopedFD, patchpanel::ConnectNamespaceResponse>
78 ConnectNamespace(pid_t pid,
79 const std::string& outbound_ifname,
80 bool forward_user_traffic,
81 bool route_on_vpn,
82 patchpanel::TrafficCounter::Source traffic_source) override {
83 ns_ifname_ = outbound_ifname;
84 ns_rvpn_ = route_on_vpn;
85 ns_ts_ = traffic_source;
86 return {base::ScopedFD(ns_fd_), ns_resp_};
87 }
88
89 std::string ns_ifname_;
90 bool ns_rvpn_;
91 patchpanel::TrafficCounter::Source ns_ts_;
92 int ns_fd_;
93 patchpanel::ConnectNamespaceResponse ns_resp_;
94};
95
Garrick Evans77e9a132021-05-13 10:51:13 +090096class FakeFeaturesClient : public ChromeFeaturesServiceClient {
97 public:
98 explicit FakeFeaturesClient(bool enabled)
99 : ChromeFeaturesServiceClient(nullptr), enabled_(enabled) {}
100 void IsDNSProxyEnabled(
101 ChromeFeaturesServiceClient::IsFeatureEnabledCallback callback) override {
102 is_dnsproxy_enabled_called = true;
103 std::move(callback).Run(enabled_);
104 }
105
106 bool is_dnsproxy_enabled_called{false};
107
108 private:
109 bool enabled_;
110};
111
112class FakeSessionMonitor : public SessionMonitor {
113 public:
114 explicit FakeSessionMonitor(scoped_refptr<dbus::Bus> bus)
115 : SessionMonitor(bus) {}
116
117 void Login() { OnSessionStateChanged("started"); }
118
119 void Logout() { OnSessionStateChanged("stopping"); }
120};
121
Garrick Evans2ca050d2021-02-09 18:21:36 +0900122class MockResolver : public Resolver {
123 public:
Jason Jeremy Iman845f2932021-01-31 16:12:13 +0900124 MockResolver()
125 : Resolver(kRequestTimeout, kRequestRetryDelay, kRequestMaxRetry) {}
Garrick Evans2ca050d2021-02-09 18:21:36 +0900126 ~MockResolver() = default;
127
Jason Jeremy Iman6fd98552021-01-27 04:19:07 +0900128 MOCK_METHOD(bool, ListenUDP, (struct sockaddr*), (override));
129 MOCK_METHOD(bool, ListenTCP, (struct sockaddr*), (override));
Garrick Evans2ca050d2021-02-09 18:21:36 +0900130 MOCK_METHOD(void,
131 SetNameServers,
132 (const std::vector<std::string>&),
133 (override));
134 MOCK_METHOD(void,
135 SetDoHProviders,
136 (const std::vector<std::string>&, bool),
137 (override));
138};
139
140class TestProxy : public Proxy {
141 public:
142 TestProxy(const Options& opts,
143 std::unique_ptr<patchpanel::Client> patchpanel,
144 std::unique_ptr<shill::Client> shill)
145 : Proxy(opts, std::move(patchpanel), std::move(shill)) {}
146
147 std::unique_ptr<Resolver> resolver;
Jason Jeremy Iman845f2932021-01-31 16:12:13 +0900148 std::unique_ptr<Resolver> NewResolver(base::TimeDelta timeout,
149 base::TimeDelta retry_delay,
150 int max_num_retries) override {
Garrick Evans2ca050d2021-02-09 18:21:36 +0900151 return std::move(resolver);
152 }
153};
154
Garrick Evans5fe2a4f2021-02-03 17:04:48 +0900155class ProxyTest : public ::testing::Test {
156 protected:
157 ProxyTest() : mock_bus_(new dbus::MockBus{dbus::Bus::Options{}}) {}
158 ~ProxyTest() { mock_bus_->ShutdownAndBlock(); }
159
160 std::unique_ptr<FakePatchpanelClient> PatchpanelClient() const {
161 return std::make_unique<FakePatchpanelClient>();
162 }
163
164 std::unique_ptr<FakeShillClient> ShillClient() const {
165 return std::make_unique<FakeShillClient>(
166 mock_bus_, reinterpret_cast<ManagerProxyInterface*>(
167 const_cast<ManagerProxyMock*>(&mock_manager_)));
168 }
169
170 int make_fd() const {
171 std::string fn(
172 ::testing::UnitTest::GetInstance()->current_test_info()->name());
173 fn = "/tmp/" + fn;
174 return open(fn.c_str(), O_CREAT, 0600);
175 }
176
177 protected:
178 scoped_refptr<dbus::MockBus> mock_bus_;
179 ManagerProxyMock mock_manager_;
180};
181
182TEST_F(ProxyTest, SystemProxy_OnShutdownClearsAddressPropertyOnShill) {
183 EXPECT_CALL(mock_manager_, SetProperty(shill::kDNSProxyIPv4AddressProperty,
184 brillo::Any(std::string()), _, _))
185 .WillOnce(Return(true));
186 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
187 ShillClient());
188 int unused;
189 proxy.OnShutdown(&unused);
190}
191
192TEST_F(ProxyTest, NonSystemProxy_OnShutdownDoesNotCallShill) {
193 EXPECT_CALL(mock_manager_, SetProperty(_, _, _, _)).Times(0);
194 Proxy proxy(Proxy::Options{.type = Proxy::Type::kDefault}, PatchpanelClient(),
195 ShillClient());
196 int unused;
197 proxy.OnShutdown(&unused);
198}
199
200TEST_F(ProxyTest, SystemProxy_SetShillPropertyWithNoRetriesCrashes) {
201 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
202 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
203 ShillClient());
204 EXPECT_DEATH(proxy.SetShillProperty("10.10.10.10", true, 0), "");
205}
206
207TEST_F(ProxyTest, SystemProxy_SetShillPropertyDoesntCrashIfDieFalse) {
208 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
209 EXPECT_CALL(mock_manager_, SetProperty(_, _, _, _)).Times(0);
210 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
211 ShillClient());
212 proxy.SetShillProperty("10.10.10.10", false, 0);
213}
214
Garrick Evansab03c462021-02-15 20:54:20 +0900215TEST_F(ProxyTest, ShillInitializedWhenReady) {
Garrick Evans5fe2a4f2021-02-03 17:04:48 +0900216 auto shill = ShillClient();
217 auto* shill_ptr = shill.get();
218 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
219 std::move(shill));
Garrick Evansab03c462021-02-15 20:54:20 +0900220 proxy.OnShillReady(true);
Garrick Evans5fe2a4f2021-02-03 17:04:48 +0900221 EXPECT_TRUE(shill_ptr->IsInitialized());
222}
223
224TEST_F(ProxyTest, SystemProxy_ConnectedNamedspace) {
225 auto pp = PatchpanelClient();
226 auto* pp_ptr = pp.get();
227 pp->SetConnectNamespaceResult(make_fd(),
228 patchpanel::ConnectNamespaceResponse());
229 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, std::move(pp),
230 ShillClient());
231 proxy.OnPatchpanelReady(true);
232 EXPECT_TRUE(pp_ptr->ns_ifname_.empty());
233 EXPECT_FALSE(pp_ptr->ns_rvpn_);
234 EXPECT_EQ(pp_ptr->ns_ts_, patchpanel::TrafficCounter::SYSTEM);
235}
236
237TEST_F(ProxyTest, DefaultProxy_ConnectedNamedspace) {
238 auto pp = PatchpanelClient();
239 auto* pp_ptr = pp.get();
240 pp->SetConnectNamespaceResult(make_fd(),
241 patchpanel::ConnectNamespaceResponse());
242 Proxy proxy(Proxy::Options{.type = Proxy::Type::kDefault}, std::move(pp),
243 ShillClient());
244 proxy.OnPatchpanelReady(true);
245 EXPECT_TRUE(pp_ptr->ns_ifname_.empty());
246 EXPECT_TRUE(pp_ptr->ns_rvpn_);
247 EXPECT_EQ(pp_ptr->ns_ts_, patchpanel::TrafficCounter::USER);
248}
249
250TEST_F(ProxyTest, ArcProxy_ConnectedNamedspace) {
251 auto pp = PatchpanelClient();
252 auto* pp_ptr = pp.get();
253 pp->SetConnectNamespaceResult(make_fd(),
254 patchpanel::ConnectNamespaceResponse());
255 Proxy proxy(Proxy::Options{.type = Proxy::Type::kARC, .ifname = "eth0"},
256 std::move(pp), ShillClient());
257 proxy.OnPatchpanelReady(true);
258 EXPECT_EQ(pp_ptr->ns_ifname_, "eth0");
259 EXPECT_FALSE(pp_ptr->ns_rvpn_);
260 EXPECT_EQ(pp_ptr->ns_ts_, patchpanel::TrafficCounter::ARC);
261}
262
263TEST_F(ProxyTest, CrashOnConnectNamespaceFailure) {
Garrick Evans2ca050d2021-02-09 18:21:36 +0900264 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
Garrick Evans5fe2a4f2021-02-03 17:04:48 +0900265 auto pp = PatchpanelClient();
266 pp->SetConnectNamespaceResult(-1 /* invalid fd */,
267 patchpanel::ConnectNamespaceResponse());
268 Proxy proxy(Proxy::Options{.type = Proxy::Type::kARC, .ifname = "eth0"},
269 std::move(pp), ShillClient());
270 EXPECT_DEATH(proxy.OnPatchpanelReady(true), "namespace");
271}
272
273TEST_F(ProxyTest, CrashOnPatchpanelNotReady) {
Garrick Evans2ca050d2021-02-09 18:21:36 +0900274 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
Garrick Evans5fe2a4f2021-02-03 17:04:48 +0900275 Proxy proxy(Proxy::Options{.type = Proxy::Type::kARC, .ifname = "eth0"},
276 PatchpanelClient(), ShillClient());
277 EXPECT_DEATH(proxy.OnPatchpanelReady(false), "patchpanel");
278}
279
280TEST_F(ProxyTest, ShillResetRestoresAddressProperty) {
281 auto pp = PatchpanelClient();
282 patchpanel::ConnectNamespaceResponse resp;
Garrick Evansab03c462021-02-15 20:54:20 +0900283 resp.set_peer_ipv4_address(patchpanel::Ipv4Addr(10, 10, 10, 10));
Garrick Evans5fe2a4f2021-02-03 17:04:48 +0900284 pp->SetConnectNamespaceResult(make_fd(), resp);
285 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, std::move(pp),
286 ShillClient());
287 proxy.OnPatchpanelReady(true);
288 EXPECT_CALL(mock_manager_,
289 SetProperty(shill::kDNSProxyIPv4AddressProperty,
290 brillo::Any(std::string("10.10.10.10")), _, _))
291 .WillOnce(Return(true));
292 proxy.OnShillReset(true);
293}
294
Garrick Evans2ca050d2021-02-09 18:21:36 +0900295TEST_F(ProxyTest, StateClearedIfDefaultServiceDrops) {
296 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
297 ShillClient());
298 proxy.device_ = std::make_unique<shill::Client::Device>();
299 proxy.resolver_ = std::make_unique<MockResolver>();
300 proxy.OnDefaultDeviceChanged(nullptr /* no service */);
301 EXPECT_FALSE(proxy.device_);
302 EXPECT_FALSE(proxy.resolver_);
303}
304
305TEST_F(ProxyTest, ArcProxy_IgnoredIfDefaultServiceDrops) {
306 Proxy proxy(Proxy::Options{.type = Proxy::Type::kARC}, PatchpanelClient(),
307 ShillClient());
308 proxy.device_ = std::make_unique<shill::Client::Device>();
309 proxy.resolver_ = std::make_unique<MockResolver>();
310 proxy.OnDefaultDeviceChanged(nullptr /* no service */);
311 EXPECT_TRUE(proxy.device_);
312 EXPECT_TRUE(proxy.resolver_);
313}
314
315TEST_F(ProxyTest, StateClearedIfDefaultServiceIsNotOnline) {
316 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
317 ShillClient());
318 proxy.device_ = std::make_unique<shill::Client::Device>();
319 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
320 proxy.resolver_ = std::make_unique<MockResolver>();
321 shill::Client::Device dev;
322 dev.state = shill::Client::Device::ConnectionState::kReady;
323 proxy.OnDefaultDeviceChanged(&dev);
324 EXPECT_FALSE(proxy.device_);
325 EXPECT_FALSE(proxy.resolver_);
326}
327
328TEST_F(ProxyTest, NewResolverStartsListeningOnDefaultServiceComesOnline) {
329 TestProxy proxy(Proxy::Options{.type = Proxy::Type::kDefault},
330 PatchpanelClient(), ShillClient());
331 proxy.device_ = std::make_unique<shill::Client::Device>();
332 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
333 auto resolver = std::make_unique<MockResolver>();
334 MockResolver* mock_resolver = resolver.get();
335 proxy.resolver = std::move(resolver);
336 shill::Client::Device dev;
337 dev.state = shill::Client::Device::ConnectionState::kOnline;
Jason Jeremy Iman6fd98552021-01-27 04:19:07 +0900338 EXPECT_CALL(*mock_resolver, ListenUDP(_)).WillOnce(Return(true));
339 EXPECT_CALL(*mock_resolver, ListenTCP(_)).WillOnce(Return(true));
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900340 brillo::VariantDictionary props;
341 EXPECT_CALL(mock_manager_, GetProperties(_, _, _))
342 .WillOnce(DoAll(SetArgPointee<0>(props), Return(true)));
Garrick Evans2ca050d2021-02-09 18:21:36 +0900343 proxy.OnDefaultDeviceChanged(&dev);
344 EXPECT_TRUE(proxy.resolver_);
345}
346
347TEST_F(ProxyTest, CrashOnListenFailure) {
348 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
349 TestProxy proxy(Proxy::Options{.type = Proxy::Type::kSystem},
350 PatchpanelClient(), ShillClient());
351 proxy.device_ = std::make_unique<shill::Client::Device>();
352 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
353 auto resolver = std::make_unique<MockResolver>();
354 MockResolver* mock_resolver = resolver.get();
355 proxy.resolver = std::move(resolver);
356 shill::Client::Device dev;
357 dev.state = shill::Client::Device::ConnectionState::kOnline;
Jason Jeremy Iman6fd98552021-01-27 04:19:07 +0900358 ON_CALL(*mock_resolver, ListenUDP(_)).WillByDefault(Return(false));
359 ON_CALL(*mock_resolver, ListenTCP(_)).WillByDefault(Return(false));
Garrick Evans2ca050d2021-02-09 18:21:36 +0900360 EXPECT_DEATH(proxy.OnDefaultDeviceChanged(&dev), "relay loop");
361}
362
363TEST_F(ProxyTest, NameServersUpdatedOnDefaultServiceComesOnline) {
364 Proxy proxy(Proxy::Options{.type = Proxy::Type::kDefault}, PatchpanelClient(),
365 ShillClient());
366 proxy.device_ = std::make_unique<shill::Client::Device>();
367 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
368 auto resolver = std::make_unique<MockResolver>();
369 MockResolver* mock_resolver = resolver.get();
370 proxy.resolver_ = std::move(resolver);
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900371 proxy.doh_config_.set_resolver(mock_resolver);
Garrick Evans2ca050d2021-02-09 18:21:36 +0900372 shill::Client::Device dev;
373 dev.state = shill::Client::Device::ConnectionState::kOnline;
374 dev.ipconfig.ipv4_dns_addresses = {"a", "b"};
375 dev.ipconfig.ipv6_dns_addresses = {"c", "d"};
376 // Doesn't call listen since the resolver already exists.
Jason Jeremy Iman6fd98552021-01-27 04:19:07 +0900377 EXPECT_CALL(*mock_resolver, ListenUDP(_)).Times(0);
378 EXPECT_CALL(*mock_resolver, ListenTCP(_)).Times(0);
Garrick Evans2ca050d2021-02-09 18:21:36 +0900379 EXPECT_CALL(*mock_resolver,
380 SetNameServers(
381 ElementsAre(StrEq("a"), StrEq("b"), StrEq("c"), StrEq("d"))));
382 proxy.OnDefaultDeviceChanged(&dev);
383}
384
385TEST_F(ProxyTest, SystemProxy_ShillPropertyUpdatedOnDefaultServiceComesOnline) {
386 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
387 ShillClient());
388 proxy.device_ = std::make_unique<shill::Client::Device>();
389 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
390 auto resolver = std::make_unique<MockResolver>();
391 MockResolver* mock_resolver = resolver.get();
392 proxy.resolver_ = std::move(resolver);
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900393 proxy.doh_config_.set_resolver(mock_resolver);
Garrick Evans2ca050d2021-02-09 18:21:36 +0900394 shill::Client::Device dev;
395 dev.state = shill::Client::Device::ConnectionState::kOnline;
396 EXPECT_CALL(*mock_resolver, SetNameServers(_));
397 EXPECT_CALL(mock_manager_,
398 SetProperty(shill::kDNSProxyIPv4AddressProperty, _, _, _))
399 .WillOnce(Return(true));
400 proxy.OnDefaultDeviceChanged(&dev);
401}
402
Garrick Evansadde9852021-02-15 20:16:53 +0900403TEST_F(ProxyTest, SystemProxy_IgnoresVPN) {
404 TestProxy proxy(Proxy::Options{.type = Proxy::Type::kSystem},
405 PatchpanelClient(), ShillClient());
406 auto resolver = std::make_unique<MockResolver>();
407 MockResolver* mock_resolver = resolver.get();
408 ON_CALL(*mock_resolver, ListenUDP(_)).WillByDefault(Return(true));
409 ON_CALL(*mock_resolver, ListenTCP(_)).WillByDefault(Return(true));
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900410 brillo::VariantDictionary props;
411 EXPECT_CALL(mock_manager_, GetProperties(_, _, _))
412 .WillOnce(DoAll(SetArgPointee<0>(props), Return(true)));
Garrick Evansadde9852021-02-15 20:16:53 +0900413 EXPECT_CALL(mock_manager_,
414 SetProperty(shill::kDNSProxyIPv4AddressProperty, _, _, _))
415 .WillOnce(Return(true));
416 proxy.resolver = std::move(resolver);
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900417 proxy.doh_config_.set_resolver(mock_resolver);
Garrick Evansadde9852021-02-15 20:16:53 +0900418 shill::Client::Device dev;
419 dev.type = shill::Client::Device::Type::kWifi;
420 dev.state = shill::Client::Device::ConnectionState::kOnline;
421 proxy.OnDefaultDeviceChanged(&dev);
422 EXPECT_TRUE(proxy.device_);
423 EXPECT_EQ(proxy.device_->type, shill::Client::Device::Type::kWifi);
424 dev.type = shill::Client::Device::Type::kVPN;
425 proxy.OnDefaultDeviceChanged(&dev);
426 EXPECT_TRUE(proxy.device_);
427 EXPECT_EQ(proxy.device_->type, shill::Client::Device::Type::kWifi);
428}
429
430TEST_F(ProxyTest, SystemProxy_GetsPhysicalDeviceOnInitialVPN) {
431 auto shill = ShillClient();
432 auto* shill_ptr = shill.get();
433 TestProxy proxy(Proxy::Options{.type = Proxy::Type::kSystem},
434 PatchpanelClient(), std::move(shill));
435 auto resolver = std::make_unique<MockResolver>();
436 MockResolver* mock_resolver = resolver.get();
437 ON_CALL(*mock_resolver, ListenUDP(_)).WillByDefault(Return(true));
438 ON_CALL(*mock_resolver, ListenTCP(_)).WillByDefault(Return(true));
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900439 brillo::VariantDictionary props;
440 EXPECT_CALL(mock_manager_, GetProperties(_, _, _))
441 .WillOnce(DoAll(SetArgPointee<0>(props), Return(true)));
Garrick Evansadde9852021-02-15 20:16:53 +0900442 EXPECT_CALL(mock_manager_,
443 SetProperty(shill::kDNSProxyIPv4AddressProperty, _, _, _))
444 .WillOnce(Return(true));
445 proxy.resolver = std::move(resolver);
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900446 proxy.doh_config_.set_resolver(mock_resolver);
Garrick Evansadde9852021-02-15 20:16:53 +0900447 shill::Client::Device vpn;
448 vpn.type = shill::Client::Device::Type::kVPN;
449 vpn.state = shill::Client::Device::ConnectionState::kOnline;
450 shill_ptr->default_device_ = std::make_unique<shill::Client::Device>();
451 shill_ptr->default_device_->type = shill::Client::Device::Type::kWifi;
452 shill_ptr->default_device_->state =
453 shill::Client::Device::ConnectionState::kOnline;
454 proxy.OnDefaultDeviceChanged(&vpn);
455 EXPECT_TRUE(proxy.device_);
456 EXPECT_EQ(proxy.device_->type, shill::Client::Device::Type::kWifi);
457}
458
459TEST_F(ProxyTest, DefaultProxy_UsesVPN) {
460 TestProxy proxy(Proxy::Options{.type = Proxy::Type::kDefault},
461 PatchpanelClient(), ShillClient());
462 auto resolver = std::make_unique<MockResolver>();
463 MockResolver* mock_resolver = resolver.get();
464 ON_CALL(*mock_resolver, ListenUDP(_)).WillByDefault(Return(true));
465 ON_CALL(*mock_resolver, ListenTCP(_)).WillByDefault(Return(true));
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900466 brillo::VariantDictionary props;
467 EXPECT_CALL(mock_manager_, GetProperties(_, _, _))
468 .WillOnce(DoAll(SetArgPointee<0>(props), Return(true)));
Garrick Evansadde9852021-02-15 20:16:53 +0900469 proxy.resolver = std::move(resolver);
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900470 proxy.doh_config_.set_resolver(mock_resolver);
Garrick Evansadde9852021-02-15 20:16:53 +0900471 shill::Client::Device dev;
472 dev.type = shill::Client::Device::Type::kWifi;
473 dev.state = shill::Client::Device::ConnectionState::kOnline;
474 proxy.OnDefaultDeviceChanged(&dev);
475 EXPECT_TRUE(proxy.device_);
476 EXPECT_EQ(proxy.device_->type, shill::Client::Device::Type::kWifi);
477 dev.type = shill::Client::Device::Type::kVPN;
478 proxy.OnDefaultDeviceChanged(&dev);
479 EXPECT_TRUE(proxy.device_);
480 EXPECT_EQ(proxy.device_->type, shill::Client::Device::Type::kVPN);
481}
482
Garrick Evans73e8e5e2021-04-27 10:16:26 +0900483TEST_F(ProxyTest, ArcProxy_NameServersUpdatedOnDeviceChangeEvent) {
484 Proxy proxy(Proxy::Options{.type = Proxy::Type::kARC, .ifname = "wlan0"},
485 PatchpanelClient(), ShillClient());
486 auto resolver = std::make_unique<MockResolver>();
487 MockResolver* mock_resolver = resolver.get();
488 proxy.resolver_ = std::move(resolver);
489 proxy.doh_config_.set_resolver(mock_resolver);
490 shill::Client::Device dev;
491 dev.ifname = "wlan0";
492 dev.state = shill::Client::Device::ConnectionState::kOnline;
493 dev.ipconfig.ipv4_dns_addresses = {"a", "b"};
494 dev.ipconfig.ipv6_dns_addresses = {"c", "d"};
495 // Doesn't call listen since the resolver already exists.
496 EXPECT_CALL(*mock_resolver, ListenUDP(_)).Times(0);
497 EXPECT_CALL(*mock_resolver, ListenTCP(_)).Times(0);
498 EXPECT_CALL(*mock_resolver,
499 SetNameServers(
500 ElementsAre(StrEq("a"), StrEq("b"), StrEq("c"), StrEq("d"))));
501 proxy.OnDeviceChanged(&dev);
502
503 // Verify it only applies changes for the correct interface.
504 dev.ifname = "eth0";
505 dev.ipconfig.ipv4_dns_addresses = {"X", "Y", "Z"};
506 EXPECT_CALL(*mock_resolver, SetNameServers(_)).Times(0);
507 proxy.OnDeviceChanged(&dev);
508
509 dev.ifname = "wlan0";
510 dev.ipconfig.ipv4_dns_addresses = {"X", "Y", "Z"};
511 dev.ipconfig.ipv6_dns_addresses.clear();
512 EXPECT_CALL(*mock_resolver,
513 SetNameServers(ElementsAre(StrEq("X"), StrEq("Y"), StrEq("Z"))));
514 proxy.OnDeviceChanged(&dev);
515}
516
517TEST_F(ProxyTest, SystemProxy_NameServersUpdatedOnDeviceChangeEvent) {
Garrick Evansa8c12be2021-02-17 16:06:45 +0900518 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
519 ShillClient());
520 proxy.device_ = std::make_unique<shill::Client::Device>();
521 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
522 auto resolver = std::make_unique<MockResolver>();
523 MockResolver* mock_resolver = resolver.get();
524 proxy.resolver_ = std::move(resolver);
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900525 proxy.doh_config_.set_resolver(mock_resolver);
Garrick Evansa8c12be2021-02-17 16:06:45 +0900526 shill::Client::Device dev;
527 dev.state = shill::Client::Device::ConnectionState::kOnline;
528 dev.ipconfig.ipv4_dns_addresses = {"a", "b"};
529 dev.ipconfig.ipv6_dns_addresses = {"c", "d"};
530 // Doesn't call listen since the resolver already exists.
531 EXPECT_CALL(mock_manager_,
532 SetProperty(shill::kDNSProxyIPv4AddressProperty, _, _, _))
533 .WillOnce(Return(true));
534 EXPECT_CALL(*mock_resolver, ListenUDP(_)).Times(0);
535 EXPECT_CALL(*mock_resolver, ListenTCP(_)).Times(0);
536 EXPECT_CALL(*mock_resolver,
537 SetNameServers(
538 ElementsAre(StrEq("a"), StrEq("b"), StrEq("c"), StrEq("d"))));
539 proxy.OnDefaultDeviceChanged(&dev);
540
541 // Now trigger an ipconfig change.
542 dev.ipconfig.ipv4_dns_addresses = {"X"};
543 EXPECT_CALL(*mock_resolver,
544 SetNameServers(ElementsAre(StrEq("X"), StrEq("c"), StrEq("d"))));
545 proxy.OnDeviceChanged(&dev);
546}
547
548TEST_F(ProxyTest, DeviceChangeEventIgnored) {
549 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
550 ShillClient());
551 proxy.device_ = std::make_unique<shill::Client::Device>();
552 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
553 auto resolver = std::make_unique<MockResolver>();
554 MockResolver* mock_resolver = resolver.get();
555 proxy.resolver_ = std::move(resolver);
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900556 proxy.doh_config_.set_resolver(mock_resolver);
Garrick Evansa8c12be2021-02-17 16:06:45 +0900557 shill::Client::Device dev;
558 dev.ifname = "eth0";
559 dev.state = shill::Client::Device::ConnectionState::kOnline;
560 dev.ipconfig.ipv4_dns_addresses = {"a", "b"};
561 dev.ipconfig.ipv6_dns_addresses = {"c", "d"};
562 // Doesn't call listen since the resolver already exists.
563 EXPECT_CALL(mock_manager_,
564 SetProperty(shill::kDNSProxyIPv4AddressProperty, _, _, _))
565 .WillOnce(Return(true));
566 EXPECT_CALL(*mock_resolver, ListenUDP(_)).Times(0);
567 EXPECT_CALL(*mock_resolver, ListenTCP(_)).Times(0);
568 EXPECT_CALL(*mock_resolver,
569 SetNameServers(
570 ElementsAre(StrEq("a"), StrEq("b"), StrEq("c"), StrEq("d"))));
571 proxy.OnDefaultDeviceChanged(&dev);
572
573 // No change to ipconfig, no call to SetNameServers
574 proxy.OnDeviceChanged(&dev);
575
576 // Different ifname, no call to SetNameServers
577 dev.ifname = "wlan0";
578 proxy.OnDeviceChanged(&dev);
579}
580
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900581TEST_F(ProxyTest, BasicDoHDisable) {
582 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
583 ShillClient());
584 proxy.device_ = std::make_unique<shill::Client::Device>();
585 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
586 auto resolver = std::make_unique<MockResolver>();
587 MockResolver* mock_resolver = resolver.get();
588 proxy.resolver_ = std::move(resolver);
589 proxy.doh_config_.set_resolver(mock_resolver);
590 EXPECT_CALL(*mock_resolver, SetDoHProviders(IsEmpty(), false));
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900591 brillo::VariantDictionary props;
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900592 proxy.OnDoHProvidersChanged(props);
593}
594
595TEST_F(ProxyTest, BasicDoHAlwaysOn) {
596 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
597 ShillClient());
598 proxy.device_ = std::make_unique<shill::Client::Device>();
599 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
600 auto resolver = std::make_unique<MockResolver>();
601 MockResolver* mock_resolver = resolver.get();
602 proxy.resolver_ = std::move(resolver);
603 proxy.doh_config_.set_resolver(mock_resolver);
604 EXPECT_CALL(
605 *mock_resolver,
606 SetDoHProviders(ElementsAre(StrEq("https://dns.google.com")), true));
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900607 brillo::VariantDictionary props;
608 props["https://dns.google.com"] = std::string("");
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900609 proxy.OnDoHProvidersChanged(props);
610}
611
612TEST_F(ProxyTest, BasicDoHAutomatic) {
613 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
614 ShillClient());
615 proxy.device_ = std::make_unique<shill::Client::Device>();
616 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
617 auto resolver = std::make_unique<MockResolver>();
618 MockResolver* mock_resolver = resolver.get();
619 proxy.resolver_ = std::move(resolver);
620 proxy.doh_config_.set_resolver(mock_resolver);
621 shill::Client::IPConfig ipconfig;
622 ipconfig.ipv4_dns_addresses = {"8.8.4.4"};
623 proxy.UpdateNameServers(ipconfig);
624
625 EXPECT_CALL(
626 *mock_resolver,
627 SetDoHProviders(ElementsAre(StrEq("https://dns.google.com")), false));
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900628 brillo::VariantDictionary props;
629 props["https://dns.google.com"] = std::string("8.8.8.8, 8.8.4.4");
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900630 proxy.OnDoHProvidersChanged(props);
631}
632
Garrick Evans4e1fc312021-05-10 14:47:31 +0900633TEST_F(ProxyTest, RemovesDNSQueryParameterTemplate_AlwaysOn) {
634 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
635 ShillClient());
636 proxy.device_ = std::make_unique<shill::Client::Device>();
637 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
638 auto resolver = std::make_unique<MockResolver>();
639 MockResolver* mock_resolver = resolver.get();
640 proxy.resolver_ = std::move(resolver);
641 proxy.doh_config_.set_resolver(mock_resolver);
642 EXPECT_CALL(
643 *mock_resolver,
644 SetDoHProviders(ElementsAre(StrEq("https://dns.google.com")), true));
645 brillo::VariantDictionary props;
646 props["https://dns.google.com{?dns}"] = std::string("");
647 proxy.OnDoHProvidersChanged(props);
648}
649
650TEST_F(ProxyTest, RemovesDNSQueryParameterTemplate_Automatic) {
651 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
652 ShillClient());
653 proxy.device_ = std::make_unique<shill::Client::Device>();
654 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
655 auto resolver = std::make_unique<MockResolver>();
656 MockResolver* mock_resolver = resolver.get();
657 proxy.resolver_ = std::move(resolver);
658 proxy.doh_config_.set_resolver(mock_resolver);
659 shill::Client::IPConfig ipconfig;
660 ipconfig.ipv4_dns_addresses = {"8.8.4.4"};
661 proxy.UpdateNameServers(ipconfig);
662
663 EXPECT_CALL(
664 *mock_resolver,
665 SetDoHProviders(ElementsAre(StrEq("https://dns.google.com")), false));
666 brillo::VariantDictionary props;
667 props["https://dns.google.com{?dns}"] = std::string("8.8.8.8, 8.8.4.4");
668 proxy.OnDoHProvidersChanged(props);
669}
670
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900671TEST_F(ProxyTest, NewResolverConfiguredWhenSet) {
672 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
673 ShillClient());
674 proxy.device_ = std::make_unique<shill::Client::Device>();
675 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900676 brillo::VariantDictionary props;
677 props["https://dns.google.com"] = std::string("8.8.8.8, 8.8.4.4");
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900678 props["https://chrome.cloudflare-dns.com/dns-query"] =
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900679 std::string("1.1.1.1,2606:4700:4700::1111");
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900680 proxy.OnDoHProvidersChanged(props);
681 shill::Client::IPConfig ipconfig;
682 ipconfig.ipv4_dns_addresses = {"1.0.0.1", "1.1.1.1"};
683 proxy.UpdateNameServers(ipconfig);
684
685 auto resolver = std::make_unique<MockResolver>();
686 MockResolver* mock_resolver = resolver.get();
687 proxy.resolver_ = std::move(resolver);
688 EXPECT_CALL(*mock_resolver, SetNameServers(UnorderedElementsAre(
689 StrEq("1.1.1.1"), StrEq("1.0.0.1"))));
690 EXPECT_CALL(
691 *mock_resolver,
692 SetDoHProviders(
693 ElementsAre(StrEq("https://chrome.cloudflare-dns.com/dns-query")),
694 false));
695 proxy.doh_config_.set_resolver(mock_resolver);
696}
697
698TEST_F(ProxyTest, DoHModeChangingFixedNameServers) {
699 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
700 ShillClient());
701 proxy.device_ = std::make_unique<shill::Client::Device>();
702 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
703 auto resolver = std::make_unique<MockResolver>();
704 MockResolver* mock_resolver = resolver.get();
705 proxy.resolver_ = std::move(resolver);
706 proxy.doh_config_.set_resolver(mock_resolver);
707
708 // Initially off.
709 EXPECT_CALL(*mock_resolver, SetDoHProviders(IsEmpty(), false));
710 shill::Client::IPConfig ipconfig;
711 ipconfig.ipv4_dns_addresses = {"1.1.1.1", "9.9.9.9"};
712 proxy.UpdateNameServers(ipconfig);
713
714 // Automatic mode - matched cloudflare.
715 EXPECT_CALL(
716 *mock_resolver,
717 SetDoHProviders(
718 ElementsAre(StrEq("https://chrome.cloudflare-dns.com/dns-query")),
719 false));
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900720 brillo::VariantDictionary props;
721 props["https://dns.google.com"] = std::string("8.8.8.8, 8.8.4.4");
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900722 props["https://chrome.cloudflare-dns.com/dns-query"] =
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900723 std::string("1.1.1.1,2606:4700:4700::1111");
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900724 proxy.OnDoHProvidersChanged(props);
725
726 // Automatic mode - no match.
727 EXPECT_CALL(*mock_resolver, SetDoHProviders(IsEmpty(), false));
728 ipconfig.ipv4_dns_addresses = {"10.10.10.1"};
729 proxy.UpdateNameServers(ipconfig);
730
731 // Automatic mode - matched google.
732 EXPECT_CALL(
733 *mock_resolver,
734 SetDoHProviders(ElementsAre(StrEq("https://dns.google.com")), false));
735 ipconfig.ipv4_dns_addresses = {"8.8.4.4", "10.10.10.1", "8.8.8.8"};
736 proxy.UpdateNameServers(ipconfig);
737
738 // Explicitly turned off.
739 EXPECT_CALL(*mock_resolver, SetDoHProviders(IsEmpty(), false));
740 props.clear();
741 proxy.OnDoHProvidersChanged(props);
742
743 // Still off - even switching ns back.
744 EXPECT_CALL(*mock_resolver, SetDoHProviders(IsEmpty(), false));
745 ipconfig.ipv4_dns_addresses = {"8.8.4.4", "10.10.10.1", "8.8.8.8"};
746 proxy.UpdateNameServers(ipconfig);
747
748 // Always-on mode.
749 EXPECT_CALL(
750 *mock_resolver,
751 SetDoHProviders(ElementsAre(StrEq("https://doh.opendns.com/dns-query")),
752 true));
753 props.clear();
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900754 props["https://doh.opendns.com/dns-query"] = std::string("");
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900755 proxy.OnDoHProvidersChanged(props);
756
757 // Back to automatic mode, though no matching ns.
758 EXPECT_CALL(*mock_resolver, SetDoHProviders(IsEmpty(), false));
759 props.clear();
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900760 props["https://doh.opendns.com/dns-query"] = std::string(
761 "208.67.222.222,208.67.220.220,2620:119:35::35, 2620:119:53::53");
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900762 proxy.OnDoHProvidersChanged(props);
763
764 // Automatic mode working on ns update.
765 EXPECT_CALL(
766 *mock_resolver,
767 SetDoHProviders(ElementsAre(StrEq("https://doh.opendns.com/dns-query")),
768 false));
769 ipconfig.ipv4_dns_addresses = {"8.8.8.8", "2620:119:35::35"};
770 proxy.UpdateNameServers(ipconfig);
771}
772
773TEST_F(ProxyTest, MultipleDoHProvidersForAlwaysOnMode) {
774 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
775 ShillClient());
776 proxy.device_ = std::make_unique<shill::Client::Device>();
777 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
778 auto resolver = std::make_unique<MockResolver>();
779 MockResolver* mock_resolver = resolver.get();
780 proxy.resolver_ = std::move(resolver);
781 proxy.doh_config_.set_resolver(mock_resolver);
782 EXPECT_CALL(
783 *mock_resolver,
784 SetDoHProviders(UnorderedElementsAre(StrEq("https://dns.google.com"),
785 StrEq("https://doh.opendns.com")),
786 true));
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900787 brillo::VariantDictionary props;
788 props["https://dns.google.com"] = std::string("");
789 props["https://doh.opendns.com"] = std::string("");
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900790 proxy.OnDoHProvidersChanged(props);
791}
792
793TEST_F(ProxyTest, MultipleDoHProvidersForAutomaticMode) {
794 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
795 ShillClient());
796 proxy.device_ = std::make_unique<shill::Client::Device>();
797 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
798 auto resolver = std::make_unique<MockResolver>();
799 MockResolver* mock_resolver = resolver.get();
800 proxy.resolver_ = std::move(resolver);
801 proxy.doh_config_.set_resolver(mock_resolver);
802 shill::Client::IPConfig ipconfig;
803 ipconfig.ipv4_dns_addresses = {"1.1.1.1", "10.10.10.10"};
804 proxy.UpdateNameServers(ipconfig);
805
806 EXPECT_CALL(
807 *mock_resolver,
808 SetDoHProviders(
809 ElementsAre(StrEq("https://chrome.cloudflare-dns.com/dns-query")),
810 false));
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900811 brillo::VariantDictionary props;
812 props["https://dns.google.com"] = std::string("8.8.8.8, 8.8.4.4");
813 props["https://dns.quad9.net/dns-query"] = std::string("9.9.9.9,2620:fe::9");
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900814 props["https://chrome.cloudflare-dns.com/dns-query"] =
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900815 std::string("1.1.1.1,2606:4700:4700::1111");
816 props["https://doh.opendns.com/dns-query"] = std::string(
817 "208.67.222.222,208.67.220.220,2620:119:35::35, 2620:119:53::53");
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900818 proxy.OnDoHProvidersChanged(props);
819
820 EXPECT_CALL(*mock_resolver,
821 SetDoHProviders(UnorderedElementsAre(
822 StrEq("https://dns.google.com"),
823 StrEq("https://doh.opendns.com/dns-query"),
824 StrEq("https://dns.quad9.net/dns-query")),
825 false));
826 ipconfig.ipv4_dns_addresses = {"8.8.8.8", "10.10.10.10"};
827 ipconfig.ipv6_dns_addresses = {"2620:fe::9", "2620:119:53::53"};
828 proxy.UpdateNameServers(ipconfig);
829}
830
831TEST_F(ProxyTest, DoHBadAlwaysOnConfigSetsAutomaticMode) {
832 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
833 ShillClient());
834 proxy.device_ = std::make_unique<shill::Client::Device>();
835 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
836 auto resolver = std::make_unique<MockResolver>();
837 MockResolver* mock_resolver = resolver.get();
838 proxy.resolver_ = std::move(resolver);
839 proxy.doh_config_.set_resolver(mock_resolver);
840 shill::Client::IPConfig ipconfig;
841 ipconfig.ipv4_dns_addresses = {"1.1.1.1", "10.10.10.10"};
842 proxy.UpdateNameServers(ipconfig);
843
844 EXPECT_CALL(
845 *mock_resolver,
846 SetDoHProviders(
847 ElementsAre(StrEq("https://chrome.cloudflare-dns.com/dns-query")),
848 false));
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900849 brillo::VariantDictionary props;
850 props["https://dns.opendns.com"] = std::string("");
851 props["https://dns.google.com"] = std::string("8.8.8.8, 8.8.4.4");
852 props["https://dns.quad9.net/dns-query"] = std::string("9.9.9.9,2620:fe::9");
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900853 props["https://chrome.cloudflare-dns.com/dns-query"] =
Garrick Evans9e5cd1e2021-03-11 22:07:44 +0900854 std::string("1.1.1.1,2606:4700:4700::1111");
855 props["https://doh.opendns.com/dns-query"] = std::string(
856 "208.67.222.222,208.67.220.220,2620:119:35::35, 2620:119:53::53");
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900857 proxy.OnDoHProvidersChanged(props);
858
859 EXPECT_CALL(*mock_resolver,
860 SetDoHProviders(UnorderedElementsAre(
861 StrEq("https://dns.google.com"),
862 StrEq("https://doh.opendns.com/dns-query"),
863 StrEq("https://dns.quad9.net/dns-query")),
864 false));
865 ipconfig.ipv4_dns_addresses = {"8.8.8.8", "10.10.10.10"};
866 ipconfig.ipv6_dns_addresses = {"2620:fe::9", "2620:119:53::53"};
867 proxy.UpdateNameServers(ipconfig);
868}
869
Garrick Evans77e9a132021-05-13 10:51:13 +0900870TEST_F(ProxyTest, FeatureEnablementCheckedOnSetup) {
871 scoped_refptr<dbus::MockObjectProxy> mock = new dbus::MockObjectProxy(
872 mock_bus_.get(), shill::kFlimflamServiceName, dbus::ObjectPath("/"));
873 EXPECT_CALL(*mock_bus_, GetObjectProxy(_, _))
874 .WillRepeatedly(Return(mock.get()));
875
876 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
877 ShillClient());
878 proxy.session_.reset(new FakeSessionMonitor(mock_bus_));
879 auto features = std::make_unique<FakeFeaturesClient>(true);
880 auto* features_ptr = features.get();
881 proxy.features_ = std::move(features);
882 ASSERT_FALSE(features_ptr->is_dnsproxy_enabled_called);
883 proxy.Setup();
884 EXPECT_TRUE(features_ptr->is_dnsproxy_enabled_called);
885}
886
887TEST_F(ProxyTest, LoginEventTriggersFeatureCheck) {
888 scoped_refptr<dbus::MockObjectProxy> mock = new dbus::MockObjectProxy(
889 mock_bus_.get(), shill::kFlimflamServiceName, dbus::ObjectPath("/"));
890 EXPECT_CALL(*mock_bus_, GetObjectProxy(_, _))
891 .WillRepeatedly(Return(mock.get()));
892
893 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
894 ShillClient());
895 auto session = std::make_unique<FakeSessionMonitor>(mock_bus_);
896 auto* session_ptr = session.get();
897 proxy.session_ = std::move(session);
898 auto features = std::make_unique<FakeFeaturesClient>(true);
899 auto* features_ptr = features.get();
900 proxy.features_ = std::move(features);
901 proxy.Setup();
902 features_ptr->is_dnsproxy_enabled_called = false;
903 session_ptr->Login();
904 EXPECT_TRUE(features_ptr->is_dnsproxy_enabled_called);
905}
906
907TEST_F(ProxyTest, LogoutEventTriggersDisable) {
908 scoped_refptr<dbus::MockObjectProxy> mock = new dbus::MockObjectProxy(
909 mock_bus_.get(), shill::kFlimflamServiceName, dbus::ObjectPath("/"));
910 EXPECT_CALL(*mock_bus_, GetObjectProxy(_, _))
911 .WillRepeatedly(Return(mock.get()));
912
913 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
914 ShillClient());
915 auto session = std::make_unique<FakeSessionMonitor>(mock_bus_);
916 auto* session_ptr = session.get();
917 proxy.session_ = std::move(session);
918 proxy.features_.reset(new FakeFeaturesClient(true));
919 proxy.Setup();
920 ASSERT_TRUE(proxy.feature_enabled_);
921 session_ptr->Logout();
922 EXPECT_FALSE(proxy.feature_enabled_);
923}
924
925TEST_F(ProxyTest, FeatureEnabled_LoginAfterLogout) {
926 scoped_refptr<dbus::MockObjectProxy> mock = new dbus::MockObjectProxy(
927 mock_bus_.get(), shill::kFlimflamServiceName, dbus::ObjectPath("/"));
928 EXPECT_CALL(*mock_bus_, GetObjectProxy(_, _))
929 .WillRepeatedly(Return(mock.get()));
930
931 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
932 ShillClient());
933 auto session = std::make_unique<FakeSessionMonitor>(mock_bus_);
934 auto* session_ptr = session.get();
935 proxy.session_ = std::move(session);
936 proxy.features_.reset(new FakeFeaturesClient(true));
937 proxy.Setup();
938 session_ptr->Login();
939 EXPECT_TRUE(proxy.feature_enabled_);
940 session_ptr->Logout();
941 EXPECT_FALSE(proxy.feature_enabled_);
942 session_ptr->Login();
943 EXPECT_TRUE(proxy.feature_enabled_);
944}
945
946TEST_F(ProxyTest, FeatureDisabled_LoginAfterLogout) {
947 scoped_refptr<dbus::MockObjectProxy> mock = new dbus::MockObjectProxy(
948 mock_bus_.get(), shill::kFlimflamServiceName, dbus::ObjectPath("/"));
949 EXPECT_CALL(*mock_bus_, GetObjectProxy(_, _))
950 .WillRepeatedly(Return(mock.get()));
951
952 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
953 ShillClient());
954 auto session = std::make_unique<FakeSessionMonitor>(mock_bus_);
955 auto* session_ptr = session.get();
956 proxy.session_ = std::move(session);
957 proxy.features_.reset(new FakeFeaturesClient(false));
958 proxy.Setup();
959 session_ptr->Login();
960 EXPECT_FALSE(proxy.feature_enabled_);
961 session_ptr->Logout();
962 EXPECT_FALSE(proxy.feature_enabled_);
963 session_ptr->Login();
964 EXPECT_FALSE(proxy.feature_enabled_);
965}
966
967TEST_F(ProxyTest, SystemProxy_ShillPropertyNotUpdatedIfFeatureDisabled) {
968 scoped_refptr<dbus::MockObjectProxy> mock = new dbus::MockObjectProxy(
969 mock_bus_.get(), shill::kFlimflamServiceName, dbus::ObjectPath("/"));
970 EXPECT_CALL(*mock_bus_, GetObjectProxy(_, _))
971 .WillRepeatedly(Return(mock.get()));
972
973 Proxy proxy(Proxy::Options{.type = Proxy::Type::kSystem}, PatchpanelClient(),
974 ShillClient());
975 proxy.session_.reset(new FakeSessionMonitor(mock_bus_));
976 proxy.features_.reset(new FakeFeaturesClient(false));
977 proxy.Setup();
978
979 proxy.device_ = std::make_unique<shill::Client::Device>();
980 proxy.device_->state = shill::Client::Device::ConnectionState::kOnline;
981 auto resolver = std::make_unique<MockResolver>();
982 MockResolver* mock_resolver = resolver.get();
983 proxy.resolver_ = std::move(resolver);
984 proxy.doh_config_.set_resolver(mock_resolver);
985 shill::Client::Device dev;
986 dev.state = shill::Client::Device::ConnectionState::kOnline;
987 EXPECT_CALL(*mock_resolver, SetNameServers(_));
988 EXPECT_CALL(mock_manager_,
989 SetProperty(shill::kDNSProxyIPv4AddressProperty, _, _, _))
990 .Times(0);
991 proxy.OnDefaultDeviceChanged(&dev);
992}
993
Garrick Evans5fe2a4f2021-02-03 17:04:48 +0900994} // namespace dns_proxy