blob: fa8371c9898361d4d6fee90f9d05109ce347baa5 [file] [log] [blame]
Mike Yu0ee1dc92020-11-09 14:56:54 +08001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gmock/gmock.h>
18#include <gtest/gtest.h>
19
20#include "PrivateDnsConfiguration.h"
21#include "tests/dns_responder/dns_responder.h"
22#include "tests/dns_responder/dns_tls_frontend.h"
23#include "tests/resolv_test_utils.h"
24
25namespace android::net {
26
27using namespace std::chrono_literals;
28
29class PrivateDnsConfigurationTest : public ::testing::Test {
30 public:
Mike Yuad96ef82021-02-20 18:35:14 +080031 using ServerIdentity = PrivateDnsConfiguration::ServerIdentity;
32
Mike Yu0ee1dc92020-11-09 14:56:54 +080033 static void SetUpTestSuite() {
34 // stopServer() will be called in their destructor.
35 ASSERT_TRUE(tls1.startServer());
36 ASSERT_TRUE(tls2.startServer());
37 ASSERT_TRUE(backend.startServer());
38 }
39
40 void SetUp() {
41 mPdc.setObserver(&mObserver);
42
43 // The default and sole action when the observer is notified of onValidationStateUpdate.
44 // Don't override the action. In other words, don't use WillOnce() or WillRepeatedly()
45 // when mObserver.onValidationStateUpdate is expected to be called, like:
46 //
47 // EXPECT_CALL(mObserver, onValidationStateUpdate).WillOnce(Return());
48 //
49 // This is to ensure that tests can monitor how many validation threads are running. Tests
50 // must wait until every validation thread finishes.
51 ON_CALL(mObserver, onValidationStateUpdate)
52 .WillByDefault([&](const std::string& server, Validation validation, uint32_t) {
53 if (validation == Validation::in_process) {
54 mObserver.runningThreads++;
55 } else if (validation == Validation::success ||
56 validation == Validation::fail) {
57 mObserver.runningThreads--;
58 }
59 std::lock_guard guard(mObserver.lock);
60 mObserver.serverStateMap[server] = validation;
61 });
62 }
63
64 protected:
Mike Yua6853e82020-12-11 19:47:06 +080065 class MockObserver : public PrivateDnsValidationObserver {
Mike Yu0ee1dc92020-11-09 14:56:54 +080066 public:
67 MOCK_METHOD(void, onValidationStateUpdate,
Mike Yufa985f72020-11-23 20:24:21 +080068 (const std::string& serverIp, Validation validation, uint32_t netId),
69 (override));
Mike Yu0ee1dc92020-11-09 14:56:54 +080070
71 std::map<std::string, Validation> getServerStateMap() const {
72 std::lock_guard guard(lock);
73 return serverStateMap;
74 }
75
76 void removeFromServerStateMap(const std::string& server) {
77 std::lock_guard guard(lock);
78 if (const auto it = serverStateMap.find(server); it != serverStateMap.end())
79 serverStateMap.erase(it);
80 }
81
82 // The current number of validation threads running.
83 std::atomic<int> runningThreads = 0;
84
85 mutable std::mutex lock;
86 std::map<std::string, Validation> serverStateMap GUARDED_BY(lock);
87 };
88
89 void expectPrivateDnsStatus(PrivateDnsMode mode) {
Mike Yu82ae84b2020-12-02 21:04:40 +080090 // Use PollForCondition because mObserver is notified asynchronously.
91 EXPECT_TRUE(PollForCondition([&]() { return checkPrivateDnsStatus(mode); }));
92 }
93
94 bool checkPrivateDnsStatus(PrivateDnsMode mode) {
Mike Yu0ee1dc92020-11-09 14:56:54 +080095 const PrivateDnsStatus status = mPdc.getStatus(kNetId);
Mike Yu82ae84b2020-12-02 21:04:40 +080096 if (status.mode != mode) return false;
Mike Yu0ee1dc92020-11-09 14:56:54 +080097
98 std::map<std::string, Validation> serverStateMap;
99 for (const auto& [server, validation] : status.serversMap) {
100 serverStateMap[ToString(&server.ss)] = validation;
101 }
Mike Yu82ae84b2020-12-02 21:04:40 +0800102 return (serverStateMap == mObserver.getServerStateMap());
Mike Yu0ee1dc92020-11-09 14:56:54 +0800103 }
104
Mike Yuad96ef82021-02-20 18:35:14 +0800105 bool hasPrivateDnsServer(const ServerIdentity& identity, unsigned netId) {
106 return mPdc.getPrivateDns(identity, netId).ok();
107 }
108
Mike Yu0ee1dc92020-11-09 14:56:54 +0800109 static constexpr uint32_t kNetId = 30;
110 static constexpr uint32_t kMark = 30;
111 static constexpr char kBackend[] = "127.0.2.1";
112 static constexpr char kServer1[] = "127.0.2.2";
113 static constexpr char kServer2[] = "127.0.2.3";
114
115 MockObserver mObserver;
116 PrivateDnsConfiguration mPdc;
117
118 // TODO: Because incorrect CAs result in validation failed in strict mode, have
119 // PrivateDnsConfiguration run mocked code rather than DnsTlsTransport::validate().
120 inline static test::DnsTlsFrontend tls1{kServer1, "853", kBackend, "53"};
121 inline static test::DnsTlsFrontend tls2{kServer2, "853", kBackend, "53"};
122 inline static test::DNSResponder backend{kBackend, "53"};
123};
124
125TEST_F(PrivateDnsConfigurationTest, ValidationSuccess) {
126 testing::InSequence seq;
127 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::in_process, kNetId));
128 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::success, kNetId));
129
130 EXPECT_EQ(mPdc.set(kNetId, kMark, {kServer1}, {}, {}), 0);
131 expectPrivateDnsStatus(PrivateDnsMode::OPPORTUNISTIC);
132
133 ASSERT_TRUE(PollForCondition([&]() { return mObserver.runningThreads == 0; }));
134}
135
136TEST_F(PrivateDnsConfigurationTest, ValidationFail_Opportunistic) {
137 ASSERT_TRUE(backend.stopServer());
138
139 testing::InSequence seq;
140 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::in_process, kNetId));
141 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::fail, kNetId));
142
143 EXPECT_EQ(mPdc.set(kNetId, kMark, {kServer1}, {}, {}), 0);
144 expectPrivateDnsStatus(PrivateDnsMode::OPPORTUNISTIC);
145
146 // Strictly wait for all of the validation finish; otherwise, the test can crash somehow.
147 ASSERT_TRUE(PollForCondition([&]() { return mObserver.runningThreads == 0; }));
148 ASSERT_TRUE(backend.startServer());
149}
150
151TEST_F(PrivateDnsConfigurationTest, ValidationBlock) {
152 backend.setDeferredResp(true);
153
154 // onValidationStateUpdate() is called in sequence.
155 {
156 testing::InSequence seq;
157 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::in_process, kNetId));
158 EXPECT_EQ(mPdc.set(kNetId, kMark, {kServer1}, {}, {}), 0);
159 ASSERT_TRUE(PollForCondition([&]() { return mObserver.runningThreads == 1; }));
160 expectPrivateDnsStatus(PrivateDnsMode::OPPORTUNISTIC);
161
162 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer2, Validation::in_process, kNetId));
163 EXPECT_EQ(mPdc.set(kNetId, kMark, {kServer2}, {}, {}), 0);
164 ASSERT_TRUE(PollForCondition([&]() { return mObserver.runningThreads == 2; }));
165 mObserver.removeFromServerStateMap(kServer1);
166 expectPrivateDnsStatus(PrivateDnsMode::OPPORTUNISTIC);
167
168 // No duplicate validation as long as not in OFF mode; otherwise, an unexpected
169 // onValidationStateUpdate() will be caught.
170 EXPECT_EQ(mPdc.set(kNetId, kMark, {kServer1}, {}, {}), 0);
171 EXPECT_EQ(mPdc.set(kNetId, kMark, {kServer1, kServer2}, {}, {}), 0);
172 EXPECT_EQ(mPdc.set(kNetId, kMark, {kServer2}, {}, {}), 0);
173 expectPrivateDnsStatus(PrivateDnsMode::OPPORTUNISTIC);
174
175 // The status keeps unchanged if pass invalid arguments.
176 EXPECT_EQ(mPdc.set(kNetId, kMark, {"invalid_addr"}, {}, {}), -EINVAL);
177 expectPrivateDnsStatus(PrivateDnsMode::OPPORTUNISTIC);
178 }
179
180 // The update for |kServer1| will be Validation::fail because |kServer1| is not an expected
181 // server for the network.
182 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::fail, kNetId));
183 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer2, Validation::success, kNetId));
184 backend.setDeferredResp(false);
185
186 ASSERT_TRUE(PollForCondition([&]() { return mObserver.runningThreads == 0; }));
Mike Yufa985f72020-11-23 20:24:21 +0800187
188 // kServer1 is not a present server and thus should not be available from
189 // PrivateDnsConfiguration::getStatus().
190 mObserver.removeFromServerStateMap(kServer1);
191
Mike Yu0ee1dc92020-11-09 14:56:54 +0800192 expectPrivateDnsStatus(PrivateDnsMode::OPPORTUNISTIC);
193}
194
195TEST_F(PrivateDnsConfigurationTest, Validation_NetworkDestroyedOrOffMode) {
196 for (const std::string_view config : {"OFF", "NETWORK_DESTROYED"}) {
197 SCOPED_TRACE(config);
198 backend.setDeferredResp(true);
199
200 testing::InSequence seq;
201 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::in_process, kNetId));
202 EXPECT_EQ(mPdc.set(kNetId, kMark, {kServer1}, {}, {}), 0);
203 ASSERT_TRUE(PollForCondition([&]() { return mObserver.runningThreads == 1; }));
204 expectPrivateDnsStatus(PrivateDnsMode::OPPORTUNISTIC);
205
206 if (config == "OFF") {
207 EXPECT_EQ(mPdc.set(kNetId, kMark, {}, {}, {}), 0);
208 } else if (config == "NETWORK_DESTROYED") {
209 mPdc.clear(kNetId);
210 }
211
212 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::fail, kNetId));
213 backend.setDeferredResp(false);
214
215 ASSERT_TRUE(PollForCondition([&]() { return mObserver.runningThreads == 0; }));
216 mObserver.removeFromServerStateMap(kServer1);
217 expectPrivateDnsStatus(PrivateDnsMode::OFF);
218 }
219}
220
221TEST_F(PrivateDnsConfigurationTest, NoValidation) {
222 // If onValidationStateUpdate() is called, the test will fail with uninteresting mock
223 // function calls in the end of the test.
224
225 const auto expectStatus = [&]() {
226 const PrivateDnsStatus status = mPdc.getStatus(kNetId);
227 EXPECT_EQ(status.mode, PrivateDnsMode::OFF);
228 EXPECT_THAT(status.serversMap, testing::IsEmpty());
229 };
230
231 EXPECT_EQ(mPdc.set(kNetId, kMark, {"invalid_addr"}, {}, {}), -EINVAL);
232 expectStatus();
233
234 EXPECT_EQ(mPdc.set(kNetId, kMark, {}, {}, {}), 0);
235 expectStatus();
236}
237
Mike Yufa985f72020-11-23 20:24:21 +0800238TEST_F(PrivateDnsConfigurationTest, ServerIdentity_Comparison) {
Mike Yufa985f72020-11-23 20:24:21 +0800239 DnsTlsServer server(netdutils::IPSockAddr::toIPSockAddr("127.0.0.1", 853));
240 server.name = "dns.example.com";
Mike Yufa985f72020-11-23 20:24:21 +0800241
Mike Yu453b5e42021-02-19 20:03:07 +0800242 // Different socket address.
Mike Yufa985f72020-11-23 20:24:21 +0800243 DnsTlsServer other = server;
244 EXPECT_EQ(ServerIdentity(server), ServerIdentity(other));
245 other.ss = netdutils::IPSockAddr::toIPSockAddr("127.0.0.1", 5353);
Mike Yu453b5e42021-02-19 20:03:07 +0800246 EXPECT_NE(ServerIdentity(server), ServerIdentity(other));
Mike Yufa985f72020-11-23 20:24:21 +0800247 other.ss = netdutils::IPSockAddr::toIPSockAddr("127.0.0.2", 853);
248 EXPECT_NE(ServerIdentity(server), ServerIdentity(other));
249
250 // Different provider hostname.
251 other = server;
252 EXPECT_EQ(ServerIdentity(server), ServerIdentity(other));
253 other.name = "other.example.com";
254 EXPECT_NE(ServerIdentity(server), ServerIdentity(other));
255 other.name = "";
256 EXPECT_NE(ServerIdentity(server), ServerIdentity(other));
Mike Yufa985f72020-11-23 20:24:21 +0800257}
258
Mike Yue60ab412020-12-01 17:56:12 +0800259TEST_F(PrivateDnsConfigurationTest, RequestValidation) {
260 const DnsTlsServer server(netdutils::IPSockAddr::toIPSockAddr(kServer1, 853));
Mike Yuad96ef82021-02-20 18:35:14 +0800261 const ServerIdentity identity(server);
Mike Yue60ab412020-12-01 17:56:12 +0800262
263 testing::InSequence seq;
264
265 for (const std::string_view config : {"SUCCESS", "IN_PROGRESS", "FAIL"}) {
266 SCOPED_TRACE(config);
267
268 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::in_process, kNetId));
269 if (config == "SUCCESS") {
270 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::success, kNetId));
271 } else if (config == "IN_PROGRESS") {
272 backend.setDeferredResp(true);
273 } else {
274 // config = "FAIL"
275 ASSERT_TRUE(backend.stopServer());
276 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::fail, kNetId));
277 }
278 EXPECT_EQ(mPdc.set(kNetId, kMark, {kServer1}, {}, {}), 0);
279 expectPrivateDnsStatus(PrivateDnsMode::OPPORTUNISTIC);
280
281 // Wait until the validation state is transitioned.
282 const int runningThreads = (config == "IN_PROGRESS") ? 1 : 0;
283 ASSERT_TRUE(PollForCondition([&]() { return mObserver.runningThreads == runningThreads; }));
284
Mike Yue60ab412020-12-01 17:56:12 +0800285 if (config == "SUCCESS") {
286 EXPECT_CALL(mObserver,
287 onValidationStateUpdate(kServer1, Validation::in_process, kNetId));
288 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::success, kNetId));
Mike Yuad96ef82021-02-20 18:35:14 +0800289 EXPECT_TRUE(mPdc.requestValidation(kNetId, identity, kMark).ok());
Mike Yue60ab412020-12-01 17:56:12 +0800290 } else if (config == "IN_PROGRESS") {
291 EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::success, kNetId));
Mike Yuad96ef82021-02-20 18:35:14 +0800292 EXPECT_FALSE(mPdc.requestValidation(kNetId, identity, kMark).ok());
Mike Yu82ae84b2020-12-02 21:04:40 +0800293 } else if (config == "FAIL") {
Mike Yuad96ef82021-02-20 18:35:14 +0800294 EXPECT_FALSE(mPdc.requestValidation(kNetId, identity, kMark).ok());
Mike Yue60ab412020-12-01 17:56:12 +0800295 }
296
Mike Yue60ab412020-12-01 17:56:12 +0800297 // Resending the same request or requesting nonexistent servers are denied.
Mike Yuad96ef82021-02-20 18:35:14 +0800298 EXPECT_FALSE(mPdc.requestValidation(kNetId, identity, kMark).ok());
299 EXPECT_FALSE(mPdc.requestValidation(kNetId, identity, kMark + 1).ok());
300 EXPECT_FALSE(mPdc.requestValidation(kNetId + 1, identity, kMark).ok());
Mike Yue60ab412020-12-01 17:56:12 +0800301
302 // Reset the test state.
303 backend.setDeferredResp(false);
304 backend.startServer();
Mike Yu82ae84b2020-12-02 21:04:40 +0800305
306 // Ensure the status of mObserver is synced.
307 expectPrivateDnsStatus(PrivateDnsMode::OPPORTUNISTIC);
308
Mike Yue60ab412020-12-01 17:56:12 +0800309 ASSERT_TRUE(PollForCondition([&]() { return mObserver.runningThreads == 0; }));
310 mPdc.clear(kNetId);
311 }
312}
313
Mike Yuad96ef82021-02-20 18:35:14 +0800314TEST_F(PrivateDnsConfigurationTest, GetPrivateDns) {
315 const DnsTlsServer server1(netdutils::IPSockAddr::toIPSockAddr(kServer1, 853));
316 const DnsTlsServer server2(netdutils::IPSockAddr::toIPSockAddr(kServer2, 853));
317
318 EXPECT_FALSE(hasPrivateDnsServer(ServerIdentity(server1), kNetId));
319 EXPECT_FALSE(hasPrivateDnsServer(ServerIdentity(server2), kNetId));
320
321 // Suppress the warning.
322 EXPECT_CALL(mObserver, onValidationStateUpdate).Times(2);
323
324 EXPECT_EQ(mPdc.set(kNetId, kMark, {kServer1}, {}, {}), 0);
325 expectPrivateDnsStatus(PrivateDnsMode::OPPORTUNISTIC);
326
327 EXPECT_TRUE(hasPrivateDnsServer(ServerIdentity(server1), kNetId));
328 EXPECT_FALSE(hasPrivateDnsServer(ServerIdentity(server2), kNetId));
329 EXPECT_FALSE(hasPrivateDnsServer(ServerIdentity(server1), kNetId + 1));
330
331 ASSERT_TRUE(PollForCondition([&]() { return mObserver.runningThreads == 0; }));
332}
333
Mike Yu0ee1dc92020-11-09 14:56:54 +0800334// TODO: add ValidationFail_Strict test.
335
336} // namespace android::net