xref: /aosp_15_r20/system/netd/client/NetdClientTest.cpp (revision 8542734a0dd1db395a4d42aae09c37f3c3c3e7a1)
1*8542734aSAndroid Build Coastguard Worker /*
2*8542734aSAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*8542734aSAndroid Build Coastguard Worker  *
4*8542734aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8542734aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8542734aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8542734aSAndroid Build Coastguard Worker  *
8*8542734aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8542734aSAndroid Build Coastguard Worker  *
10*8542734aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8542734aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8542734aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8542734aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8542734aSAndroid Build Coastguard Worker  * limitations under the License.
15*8542734aSAndroid Build Coastguard Worker  */
16*8542734aSAndroid Build Coastguard Worker 
17*8542734aSAndroid Build Coastguard Worker #include <poll.h> /* poll */
18*8542734aSAndroid Build Coastguard Worker #include <sys/socket.h>
19*8542734aSAndroid Build Coastguard Worker 
20*8542734aSAndroid Build Coastguard Worker #include <thread>
21*8542734aSAndroid Build Coastguard Worker 
22*8542734aSAndroid Build Coastguard Worker #include <android-base/parseint.h>
23*8542734aSAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
24*8542734aSAndroid Build Coastguard Worker #include <gtest/gtest.h>
25*8542734aSAndroid Build Coastguard Worker 
26*8542734aSAndroid Build Coastguard Worker #include "NetdClient.h"
27*8542734aSAndroid Build Coastguard Worker #include "netdclient_priv.h"
28*8542734aSAndroid Build Coastguard Worker 
29*8542734aSAndroid Build Coastguard Worker namespace {
30*8542734aSAndroid Build Coastguard Worker 
31*8542734aSAndroid Build Coastguard Worker // Keep in sync with FrameworkListener.cpp (500, "Command not recognized")
32*8542734aSAndroid Build Coastguard Worker constexpr char NOT_SUPPORT_MSG[] = "500 Command not recognized";
33*8542734aSAndroid Build Coastguard Worker 
openDnsProxyFuncStub()34*8542734aSAndroid Build Coastguard Worker int openDnsProxyFuncStub() {
35*8542734aSAndroid Build Coastguard Worker     return -1;
36*8542734aSAndroid Build Coastguard Worker };
37*8542734aSAndroid Build Coastguard Worker 
38*8542734aSAndroid Build Coastguard Worker typedef int (*DnsOpenProxyType)();
39*8542734aSAndroid Build Coastguard Worker typedef int (*SocketFunctionType)(int, int, int);
40*8542734aSAndroid Build Coastguard Worker 
41*8542734aSAndroid Build Coastguard Worker DnsOpenProxyType openDnsProxyFuncPtr = openDnsProxyFuncStub;
42*8542734aSAndroid Build Coastguard Worker SocketFunctionType socketFuncPtr = socket;
43*8542734aSAndroid Build Coastguard Worker 
serverLoop(int dnsProxyFd)44*8542734aSAndroid Build Coastguard Worker void serverLoop(int dnsProxyFd) {
45*8542734aSAndroid Build Coastguard Worker     while (true) {
46*8542734aSAndroid Build Coastguard Worker         pollfd fds[1] = {{.fd = dnsProxyFd, .events = POLLIN}};
47*8542734aSAndroid Build Coastguard Worker         enum { SERVERFD = 0 };
48*8542734aSAndroid Build Coastguard Worker 
49*8542734aSAndroid Build Coastguard Worker         int poll_result = TEMP_FAILURE_RETRY(poll(fds, std::size(fds), -1));
50*8542734aSAndroid Build Coastguard Worker         ASSERT_GT(poll_result, 0);
51*8542734aSAndroid Build Coastguard Worker 
52*8542734aSAndroid Build Coastguard Worker         if (fds[SERVERFD].revents & POLLERR) return;
53*8542734aSAndroid Build Coastguard Worker         if (fds[SERVERFD].revents & POLLIN) {
54*8542734aSAndroid Build Coastguard Worker             char buf[4096];
55*8542734aSAndroid Build Coastguard Worker             TEMP_FAILURE_RETRY(read(fds[SERVERFD].fd, &buf, sizeof(buf)));
56*8542734aSAndroid Build Coastguard Worker             // TODO: verify command
57*8542734aSAndroid Build Coastguard Worker             TEMP_FAILURE_RETRY(write(fds[SERVERFD].fd, NOT_SUPPORT_MSG, sizeof(NOT_SUPPORT_MSG)));
58*8542734aSAndroid Build Coastguard Worker         }
59*8542734aSAndroid Build Coastguard Worker     }
60*8542734aSAndroid Build Coastguard Worker }
61*8542734aSAndroid Build Coastguard Worker 
expectAllowNetworkingForProcess()62*8542734aSAndroid Build Coastguard Worker void expectAllowNetworkingForProcess() {
63*8542734aSAndroid Build Coastguard Worker     // netdClientSocket
64*8542734aSAndroid Build Coastguard Worker     android::base::unique_fd ipv4(socketFuncPtr(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)),
65*8542734aSAndroid Build Coastguard Worker             ipv6(socketFuncPtr(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0));
66*8542734aSAndroid Build Coastguard Worker     EXPECT_LE(3, ipv4);
67*8542734aSAndroid Build Coastguard Worker     EXPECT_LE(3, ipv6);
68*8542734aSAndroid Build Coastguard Worker 
69*8542734aSAndroid Build Coastguard Worker     // dns_open_proxy
70*8542734aSAndroid Build Coastguard Worker     android::base::unique_fd dnsproxydSocket(openDnsProxyFuncPtr());
71*8542734aSAndroid Build Coastguard Worker     EXPECT_LE(3, dnsproxydSocket);
72*8542734aSAndroid Build Coastguard Worker }
73*8542734aSAndroid Build Coastguard Worker 
expectNotAllowNetworkingForProcess()74*8542734aSAndroid Build Coastguard Worker void expectNotAllowNetworkingForProcess() {
75*8542734aSAndroid Build Coastguard Worker     // netdClientSocket
76*8542734aSAndroid Build Coastguard Worker     android::base::unique_fd unixSocket(socketFuncPtr(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0));
77*8542734aSAndroid Build Coastguard Worker     EXPECT_LE(3, unixSocket);
78*8542734aSAndroid Build Coastguard Worker     android::base::unique_fd ipv4(socketFuncPtr(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0));
79*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(-1, ipv4);
80*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(errno, EPERM);
81*8542734aSAndroid Build Coastguard Worker     android::base::unique_fd ipv6(socketFuncPtr(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0));
82*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(-1, ipv6);
83*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(errno, EPERM);
84*8542734aSAndroid Build Coastguard Worker 
85*8542734aSAndroid Build Coastguard Worker     // dns_open_proxy
86*8542734aSAndroid Build Coastguard Worker     android::base::unique_fd dnsproxydSocket(openDnsProxyFuncPtr());
87*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(-1, dnsproxydSocket);
88*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(errno, EPERM);
89*8542734aSAndroid Build Coastguard Worker }
90*8542734aSAndroid Build Coastguard Worker 
91*8542734aSAndroid Build Coastguard Worker }  // namespace
92*8542734aSAndroid Build Coastguard Worker 
TEST(NetdClientTest,getNetworkForDnsInternal)93*8542734aSAndroid Build Coastguard Worker TEST(NetdClientTest, getNetworkForDnsInternal) {
94*8542734aSAndroid Build Coastguard Worker     // Test invalid fd
95*8542734aSAndroid Build Coastguard Worker     unsigned dnsNetId = 0;
96*8542734aSAndroid Build Coastguard Worker     const int invalidFd = -1;
97*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(-EBADF, getNetworkForDnsInternal(invalidFd, &dnsNetId));
98*8542734aSAndroid Build Coastguard Worker 
99*8542734aSAndroid Build Coastguard Worker     // Test what the client does if the resolver does not support the "getdnsnetid" command.
100*8542734aSAndroid Build Coastguard Worker     android::base::unique_fd clientFd, serverFd;
101*8542734aSAndroid Build Coastguard Worker     ASSERT_TRUE(android::base::Socketpair(AF_UNIX, &clientFd, &serverFd));
102*8542734aSAndroid Build Coastguard Worker 
103*8542734aSAndroid Build Coastguard Worker     std::thread serverThread = std::thread(serverLoop, serverFd.get());
104*8542734aSAndroid Build Coastguard Worker 
105*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(-EOPNOTSUPP, getNetworkForDnsInternal(clientFd.get(), &dnsNetId));
106*8542734aSAndroid Build Coastguard Worker 
107*8542734aSAndroid Build Coastguard Worker     clientFd.reset();  // Causes serverLoop() to exit
108*8542734aSAndroid Build Coastguard Worker     serverThread.join();
109*8542734aSAndroid Build Coastguard Worker }
110*8542734aSAndroid Build Coastguard Worker 
TEST(NetdClientTest,getNetworkForDns)111*8542734aSAndroid Build Coastguard Worker TEST(NetdClientTest, getNetworkForDns) {
112*8542734aSAndroid Build Coastguard Worker     // Test null input
113*8542734aSAndroid Build Coastguard Worker     unsigned* testNull = nullptr;
114*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(-EFAULT, getNetworkForDns(testNull));
115*8542734aSAndroid Build Coastguard Worker }
116*8542734aSAndroid Build Coastguard Worker 
TEST(NetdClientTest,protectFromVpnBadFd)117*8542734aSAndroid Build Coastguard Worker TEST(NetdClientTest, protectFromVpnBadFd) {
118*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(-EBADF, protectFromVpn(-1));
119*8542734aSAndroid Build Coastguard Worker }
120*8542734aSAndroid Build Coastguard Worker 
TEST(NetdClientTest,protectFromVpnUnixStream)121*8542734aSAndroid Build Coastguard Worker TEST(NetdClientTest, protectFromVpnUnixStream) {
122*8542734aSAndroid Build Coastguard Worker     int s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
123*8542734aSAndroid Build Coastguard Worker     ASSERT_GE(s, 3);
124*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(-EAFNOSUPPORT, protectFromVpn(s));
125*8542734aSAndroid Build Coastguard Worker     close(s);
126*8542734aSAndroid Build Coastguard Worker }
127*8542734aSAndroid Build Coastguard Worker 
TEST(NetdClientTest,protectFromVpnTcp6)128*8542734aSAndroid Build Coastguard Worker TEST(NetdClientTest, protectFromVpnTcp6) {
129*8542734aSAndroid Build Coastguard Worker     int s = socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0);
130*8542734aSAndroid Build Coastguard Worker     ASSERT_GE(s, 3);
131*8542734aSAndroid Build Coastguard Worker     EXPECT_EQ(0, protectFromVpn(s));
132*8542734aSAndroid Build Coastguard Worker     close(s);
133*8542734aSAndroid Build Coastguard Worker }
134*8542734aSAndroid Build Coastguard Worker 
TEST(NetdClientTest,setAllowNetworkingForProcess)135*8542734aSAndroid Build Coastguard Worker TEST(NetdClientTest, setAllowNetworkingForProcess) {
136*8542734aSAndroid Build Coastguard Worker     netdClientInitDnsOpenProxy(&openDnsProxyFuncPtr);
137*8542734aSAndroid Build Coastguard Worker     netdClientInitSocket(&socketFuncPtr);
138*8542734aSAndroid Build Coastguard Worker     // At the beginning, we should be able to use socket since the default setting is allowing.
139*8542734aSAndroid Build Coastguard Worker     expectAllowNetworkingForProcess();
140*8542734aSAndroid Build Coastguard Worker     // Disable
141*8542734aSAndroid Build Coastguard Worker     setAllowNetworkingForProcess(false);
142*8542734aSAndroid Build Coastguard Worker     expectNotAllowNetworkingForProcess();
143*8542734aSAndroid Build Coastguard Worker     // Reset
144*8542734aSAndroid Build Coastguard Worker     setAllowNetworkingForProcess(true);
145*8542734aSAndroid Build Coastguard Worker     expectAllowNetworkingForProcess();
146*8542734aSAndroid Build Coastguard Worker }
147