1 /* 2 * Copyright (C) 2019 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 18 #pragma once 19 20 #include <arpa/nameser.h> 21 #include <netdb.h> 22 23 #include <string> 24 #include <vector> 25 26 #include <aidl/android/net/INetd.h> 27 #include <android-base/properties.h> 28 #include <gtest/gtest.h> 29 #include <netdutils/InternetAddresses.h> 30 31 #include "dns_responder/dns_responder.h" 32 33 class ScopeBlockedUIDRule { 34 using INetd = aidl::android::net::INetd; 35 36 public: ScopeBlockedUIDRule(INetd * netSrv,uid_t testUid)37 ScopeBlockedUIDRule(INetd* netSrv, uid_t testUid) 38 : mNetSrv(netSrv), mTestUid(testUid), mSavedUid(getuid()) { 39 // Add drop rule for testUid. Also enable the standby chain because it might not be 40 // enabled. Unfortunately we cannot use FIREWALL_CHAIN_NONE, or custom iptables rules, for 41 // this purpose because netd calls fchown() on the DNS query sockets, and "iptables -m 42 // owner" matches the UID of the socket creator, not the UID set by fchown(). 43 // TODO: migrate FIREWALL_CHAIN_NONE to eBPF as well. 44 EXPECT_TRUE(mNetSrv->firewallEnableChildChain(INetd::FIREWALL_CHAIN_STANDBY, true).isOk()); 45 EXPECT_TRUE(mNetSrv->firewallSetUidRule(INetd::FIREWALL_CHAIN_STANDBY, mTestUid, 46 INetd::FIREWALL_RULE_DENY) 47 .isOk()); 48 EXPECT_TRUE(seteuid(mTestUid) == 0); 49 }; ~ScopeBlockedUIDRule()50 ~ScopeBlockedUIDRule() { 51 // Restore uid 52 EXPECT_TRUE(seteuid(mSavedUid) == 0); 53 // Remove drop rule for testUid, and disable the standby chain. 54 EXPECT_TRUE(mNetSrv->firewallSetUidRule(INetd::FIREWALL_CHAIN_STANDBY, mTestUid, 55 INetd::FIREWALL_RULE_ALLOW) 56 .isOk()); 57 EXPECT_TRUE(mNetSrv->firewallEnableChildChain(INetd::FIREWALL_CHAIN_STANDBY, false).isOk()); 58 } 59 60 private: 61 INetd* mNetSrv; 62 const uid_t mTestUid; 63 const uid_t mSavedUid; 64 }; 65 66 class ScopedChangeUID { 67 public: ScopedChangeUID(uid_t testUid)68 ScopedChangeUID(uid_t testUid) : mTestUid(testUid), mSavedUid(getuid()) { 69 EXPECT_TRUE(seteuid(mTestUid) == 0); 70 }; ~ScopedChangeUID()71 ~ScopedChangeUID() { EXPECT_TRUE(seteuid(mSavedUid) == 0); } 72 73 private: 74 const uid_t mTestUid; 75 const uid_t mSavedUid; 76 }; 77 78 class ScopedSystemProperties { 79 public: ScopedSystemProperties(const std::string & key,const std::string & value)80 ScopedSystemProperties(const std::string& key, const std::string& value) : mStoredKey(key) { 81 mStoredValue = android::base::GetProperty(key, ""); 82 android::base::SetProperty(key, value); 83 } ~ScopedSystemProperties()84 ~ScopedSystemProperties() { android::base::SetProperty(mStoredKey, mStoredValue); } 85 86 private: 87 std::string mStoredKey; 88 std::string mStoredValue; 89 }; 90 91 struct DnsRecord { 92 std::string host_name; // host name 93 ns_type type; // record type 94 std::string addr; // ipv4/v6 address 95 }; 96 97 // TODO: make this dynamic and stop depending on implementation details. 98 constexpr int TEST_NETID = 30; 99 // Use the biggest two reserved appId for applications to avoid conflict with existing uids. 100 constexpr int TEST_UID = 99999; 101 constexpr int TEST_UID2 = 99998; 102 103 static constexpr char kLocalHost[] = "localhost"; 104 static constexpr char kLocalHostAddr[] = "127.0.0.1"; 105 static constexpr char kIp6LocalHost[] = "ip6-localhost"; 106 static constexpr char kIp6LocalHostAddr[] = "::1"; 107 static constexpr char kHelloExampleCom[] = "hello.example.com."; 108 static constexpr char kHelloExampleComAddrV4[] = "1.2.3.4"; 109 static constexpr char kHelloExampleComAddrV6[] = "::1.2.3.4"; 110 static constexpr char kExampleComDomain[] = ".example.com"; 111 112 static const std::string kNat64Prefix = "64:ff9b::/96"; 113 static const std::string kNat64Prefix2 = "2001:db8:6464::/96"; 114 115 constexpr size_t kMaxmiumLabelSize = 63; // see RFC 1035 section 2.3.4. 116 117 static const std::vector<uint8_t> kHelloExampleComQueryV4 = { 118 /* Header */ 119 0x00, 0x00, /* Transaction ID: 0x0000 */ 120 0x01, 0x00, /* Flags: rd */ 121 0x00, 0x01, /* Questions: 1 */ 122 0x00, 0x00, /* Answer RRs: 0 */ 123 0x00, 0x00, /* Authority RRs: 0 */ 124 0x00, 0x00, /* Additional RRs: 0 */ 125 /* Queries */ 126 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 127 0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */ 128 0x00, 0x01, /* Type: A */ 129 0x00, 0x01 /* Class: IN */ 130 }; 131 132 static const std::vector<uint8_t> kHelloExampleComResponseV4 = { 133 /* Header */ 134 0x00, 0x00, /* Transaction ID: 0x0000 */ 135 0x81, 0x80, /* Flags: qr rd ra */ 136 0x00, 0x01, /* Questions: 1 */ 137 0x00, 0x01, /* Answer RRs: 1 */ 138 0x00, 0x00, /* Authority RRs: 0 */ 139 0x00, 0x00, /* Additional RRs: 0 */ 140 /* Queries */ 141 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 142 0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */ 143 0x00, 0x01, /* Type: A */ 144 0x00, 0x01, /* Class: IN */ 145 /* Answers */ 146 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 147 0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */ 148 0x00, 0x01, /* Type: A */ 149 0x00, 0x01, /* Class: IN */ 150 0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */ 151 0x00, 0x04, /* Data length: 4 */ 152 0x01, 0x02, 0x03, 0x04 /* Address: 1.2.3.4 */ 153 }; 154 155 // Illegal hostnames 156 static constexpr char kBadCharAfterPeriodHost[] = "hello.example.^com."; 157 static constexpr char kBadCharBeforePeriodHost[] = "hello.example^.com."; 158 static constexpr char kBadCharAtTheEndHost[] = "hello.example.com^."; 159 static constexpr char kBadCharInTheMiddleOfLabelHost[] = "hello.ex^ample.com."; 160 161 static const test::DNSHeader kDefaultDnsHeader = { 162 // Don't need to initialize the flag "id" and "rd" because DNS responder assigns them from 163 // query to response. See RFC 1035 section 4.1.1. 164 .id = 0, // unused. should be assigned from query to response 165 .ra = false, // recursive query support is not available 166 .rcode = ns_r_noerror, // no error 167 .qr = true, // message is a response 168 .opcode = QUERY, // a standard query 169 .aa = false, // answer/authority portion was not authenticated by the server 170 .tr = false, // message is not truncated 171 .rd = false, // unused. should be assigned from query to response 172 .ad = false, // non-authenticated data is unacceptable 173 }; 174 175 // The CNAME chain records for building a response message which exceeds 512 bytes. 176 // 177 // Ignoring the other fields of the message, the response message has 8 CNAMEs in 5 answer RRs 178 // and each CNAME has 77 bytes as the follows. The response message at least has 616 bytes in 179 // answer section and has already exceeded 512 bytes totally. 180 // 181 // The CNAME is presented as: 182 // 0 1 64 65 72 73 76 77 183 // +---+--........--+---+---+---+---+---+---+---+---+---+---+---+---+---+ 184 // | 63| {x, .., x} | 7 | e | x | a | m | p | l | e | 3 | c | o | m | 0 | 185 // +---+--........--+---+---+---+---+---+---+---+---+---+---+---+---+---+ 186 // ^-- x = {a, b, c, d} 187 // 188 const std::string kCnameA = std::string(kMaxmiumLabelSize, 'a') + kExampleComDomain + "."; 189 const std::string kCnameB = std::string(kMaxmiumLabelSize, 'b') + kExampleComDomain + "."; 190 const std::string kCnameC = std::string(kMaxmiumLabelSize, 'c') + kExampleComDomain + "."; 191 const std::string kCnameD = std::string(kMaxmiumLabelSize, 'd') + kExampleComDomain + "."; 192 const std::vector<DnsRecord> kLargeCnameChainRecords = { 193 {kHelloExampleCom, ns_type::ns_t_cname, kCnameA}, 194 {kCnameA, ns_type::ns_t_cname, kCnameB}, 195 {kCnameB, ns_type::ns_t_cname, kCnameC}, 196 {kCnameC, ns_type::ns_t_cname, kCnameD}, 197 {kCnameD, ns_type::ns_t_a, kHelloExampleComAddrV4}, 198 }; 199 200 // TODO: Integrate GetNumQueries relevent functions 201 size_t GetNumQueries(const test::DNSResponder& dns, const char* name); 202 size_t GetNumQueriesForProtocol(const test::DNSResponder& dns, const int protocol, 203 const char* name); 204 size_t GetNumQueriesForType(const test::DNSResponder& dns, ns_type type, const char* name); 205 std::string ToString(const hostent* he); 206 std::string ToString(const addrinfo* ai); 207 std::string ToString(const android::netdutils::ScopedAddrinfo& ai); 208 std::string ToString(const sockaddr_storage* addr); 209 std::vector<std::string> ToStrings(const hostent* he); 210 std::vector<std::string> ToStrings(const addrinfo* ai); 211 std::vector<std::string> ToStrings(const android::netdutils::ScopedAddrinfo& ai); 212 213 // Wait for |condition| to be met until |timeout|. 214 bool PollForCondition(const std::function<bool()>& condition, 215 std::chrono::milliseconds timeout = std::chrono::milliseconds(1000)); 216 217 android::netdutils::ScopedAddrinfo safe_getaddrinfo(const char* node, const char* service, 218 const struct addrinfo* hints); 219 220 void SetMdnsRoute(); 221 void RemoveMdnsRoute();