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