blob: a1efb822e8e45510e250549cd64ce90140fce245 [file] [log] [blame]
Luke Huang403c0442019-02-25 15:33:42 +08001/**
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
Ken Chen5471dca2019-04-15 15:25:35 +080017#define LOG_TAG "resolv"
Luke Huang403c0442019-02-25 15:33:42 +080018
Luke Huang36796f32019-03-13 02:54:45 +080019#include "DnsResolverService.h"
20
Luke Huang403c0442019-02-25 15:33:42 +080021#include <set>
22#include <vector>
23
24#include <android-base/stringprintf.h>
25#include <android-base/strings.h>
26#include <android/binder_manager.h>
27#include <android/binder_process.h>
28#include <log/log.h>
Luke Huang7b26b202019-03-28 14:09:24 +080029#include <openssl/base64.h>
Luke Huang403c0442019-02-25 15:33:42 +080030#include <private/android_filesystem_config.h> // AID_SYSTEM
31
Luke Huang36796f32019-03-13 02:54:45 +080032#include "DnsResolver.h"
Luke Huang7b26b202019-03-28 14:09:24 +080033#include "NetdConstants.h" // SHA256_SIZE
Luke Huang403c0442019-02-25 15:33:42 +080034#include "NetdPermissions.h" // PERM_*
Hungming Chena32c8c12019-01-25 10:47:40 +080035#include "ResolverEventReporter.h"
Luke Huang7b26b202019-03-28 14:09:24 +080036#include "netdutils/DumpWriter.h"
Luke Huangc6bbbe72019-03-28 21:38:28 +080037#include "resolv_cache.h"
Luke Huang403c0442019-02-25 15:33:42 +080038
39using android::base::Join;
40using android::base::StringPrintf;
Luke Huang7b26b202019-03-28 14:09:24 +080041using android::netdutils::DumpWriter;
Luke Huang403c0442019-02-25 15:33:42 +080042
43namespace android {
44namespace net {
45
46namespace {
47
48#define ENFORCE_ANY_PERMISSION(...) \
49 do { \
50 ::ndk::ScopedAStatus status = checkAnyPermission({__VA_ARGS__}); \
51 if (!status.isOk()) { \
52 return status; \
53 } \
54 } while (0)
55
56#define ENFORCE_INTERNAL_PERMISSIONS() \
57 ENFORCE_ANY_PERMISSION(PERM_CONNECTIVITY_INTERNAL, PERM_MAINLINE_NETWORK_STACK)
58
59#define ENFORCE_NETWORK_STACK_PERMISSIONS() \
60 ENFORCE_ANY_PERMISSION(PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK)
61
Hungming Chena32c8c12019-01-25 10:47:40 +080062inline ::ndk::ScopedAStatus statusFromErrcode(int ret) {
63 if (ret) {
64 return ::ndk::ScopedAStatus(
65 AStatus_fromServiceSpecificErrorWithMessage(-ret, strerror(-ret)));
66 }
67 return ::ndk::ScopedAStatus(AStatus_newOk());
68}
69
Luke Huang403c0442019-02-25 15:33:42 +080070} // namespace
71
Luke Huang36796f32019-03-13 02:54:45 +080072binder_status_t DnsResolverService::start() {
Luke Huang403c0442019-02-25 15:33:42 +080073 // TODO: Add disableBackgroundScheduling(true) after libbinder_ndk support it. b/126506010
74 // NetdNativeService does call disableBackgroundScheduling currently, so it is fine now.
Luke Huang36796f32019-03-13 02:54:45 +080075 DnsResolverService* resolverService = new DnsResolverService();
Luke Huang403c0442019-02-25 15:33:42 +080076 binder_status_t status =
77 AServiceManager_addService(resolverService->asBinder().get(), getServiceName());
78 if (status != STATUS_OK) {
79 return status;
80 }
81
82 ABinderProcess_startThreadPool();
83
84 // TODO: register log callback if binder NDK backend support it. b/126501406
85
86 return STATUS_OK;
87}
88
Luke Huangc6bbbe72019-03-28 21:38:28 +080089binder_status_t DnsResolverService::dump(int fd, const char**, uint32_t) {
90 auto dump_permission = checkAnyPermission({PERM_DUMP});
91 if (!dump_permission.isOk()) {
92 return STATUS_PERMISSION_DENIED;
93 }
94
95 // This method does not grab any locks. If individual classes need locking
96 // their dump() methods MUST handle locking appropriately.
97 DumpWriter dw(fd);
98 for (auto netId : resolv_list_caches()) {
99 dw.println("NetId: %u", netId);
100 gDnsResolv->resolverCtrl.dump(dw, netId);
101 dw.blankline();
102 }
103
Luke Huang7b26b202019-03-28 14:09:24 +0800104 return STATUS_OK;
105}
106
Luke Huang403c0442019-02-25 15:33:42 +0800107::ndk::ScopedAStatus DnsResolverService::isAlive(bool* alive) {
108 ENFORCE_INTERNAL_PERMISSIONS();
109
110 *alive = true;
111
112 return ::ndk::ScopedAStatus(AStatus_newOk());
113}
114
Hungming Chena32c8c12019-01-25 10:47:40 +0800115::ndk::ScopedAStatus DnsResolverService::registerEventListener(
116 const std::shared_ptr<aidl::android::net::metrics::INetdEventListener>& listener) {
117 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800118 auto entry = gDnsResolverLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
Hungming Chena32c8c12019-01-25 10:47:40 +0800119
120 int res = ResolverEventReporter::getInstance().addListener(listener);
121
Luke Huangc6bbbe72019-03-28 21:38:28 +0800122 gResNetdCallbacks.log(entry.returns(res).withAutomaticDuration().toString().c_str());
Hungming Chena32c8c12019-01-25 10:47:40 +0800123 return statusFromErrcode(res);
124}
125
Luke Huang403c0442019-02-25 15:33:42 +0800126::ndk::ScopedAStatus DnsResolverService::checkAnyPermission(
127 const std::vector<const char*>& permissions) {
128 // TODO: Remove callback and move this to unnamed namespace after libbiner_ndk supports
129 // check_permission.
Luke Huang36796f32019-03-13 02:54:45 +0800130 if (!gResNetdCallbacks.check_calling_permission) {
Luke Huang403c0442019-02-25 15:33:42 +0800131 return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(
132 EX_NULL_POINTER, "check_calling_permission is null"));
133 }
134 pid_t pid = AIBinder_getCallingPid();
135 uid_t uid = AIBinder_getCallingUid();
136
137 // If the caller is the system UID, don't check permissions.
138 // Otherwise, if the system server's binder thread pool is full, and all the threads are
139 // blocked on a thread that's waiting for us to complete, we deadlock. http://b/69389492
140 //
141 // From a security perspective, there is currently no difference, because:
142 // 1. The only permissions we check in netd's binder interface are CONNECTIVITY_INTERNAL
143 // and NETWORK_STACK, which the system server always has (or MAINLINE_NETWORK_STACK, which
144 // is equivalent to having both CONNECTIVITY_INTERNAL and NETWORK_STACK).
145 // 2. AID_SYSTEM always has all permissions. See ActivityManager#checkComponentPermission.
146 if (uid == AID_SYSTEM) {
147 return ::ndk::ScopedAStatus(AStatus_newOk());
148 }
149
150 for (const char* permission : permissions) {
Luke Huang36796f32019-03-13 02:54:45 +0800151 if (gResNetdCallbacks.check_calling_permission(permission)) {
Luke Huang403c0442019-02-25 15:33:42 +0800152 return ::ndk::ScopedAStatus(AStatus_newOk());
153 }
154 }
155
156 auto err = StringPrintf("UID %d / PID %d does not have any of the following permissions: %s",
157 uid, pid, Join(permissions, ',').c_str());
158 return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(EX_SECURITY, err.c_str()));
159}
160
Luke Huang7b26b202019-03-28 14:09:24 +0800161namespace {
162
163// Parse a base64 encoded string into a vector of bytes.
164// On failure, return an empty vector.
165static std::vector<uint8_t> parseBase64(const std::string& input) {
166 std::vector<uint8_t> decoded;
167 size_t out_len;
168 if (EVP_DecodedLength(&out_len, input.size()) != 1) {
169 return decoded;
170 }
171 // out_len is now an upper bound on the output length.
172 decoded.resize(out_len);
173 if (EVP_DecodeBase64(decoded.data(), &out_len, decoded.size(),
174 reinterpret_cast<const uint8_t*>(input.data()), input.size()) == 1) {
175 // Possibly shrink the vector if the actual output was smaller than the bound.
176 decoded.resize(out_len);
177 } else {
178 decoded.clear();
179 }
180 if (out_len != SHA256_SIZE) {
181 decoded.clear();
182 }
183 return decoded;
184}
185
186} // namespace
187
188::ndk::ScopedAStatus DnsResolverService::setResolverConfiguration(
189 int32_t netId, const std::vector<std::string>& servers,
190 const std::vector<std::string>& domains, const std::vector<int32_t>& params,
191 const std::string& tlsName, const std::vector<std::string>& tlsServers,
192 const std::vector<std::string>& tlsFingerprints) {
193 // Locking happens in PrivateDnsConfiguration and res_* functions.
194 ENFORCE_INTERNAL_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800195 auto entry =
196 gDnsResolverLog.newEntry()
197 .prettyFunction(__PRETTY_FUNCTION__)
198 .args(netId, servers, domains, params, tlsName, tlsServers, tlsFingerprints);
Luke Huang7b26b202019-03-28 14:09:24 +0800199
200 std::set<std::vector<uint8_t>> decoded_fingerprints;
201 for (const std::string& fingerprint : tlsFingerprints) {
202 std::vector<uint8_t> decoded = parseBase64(fingerprint);
203 if (decoded.empty()) {
204 return ::ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
205 EINVAL, "ResolverController error: bad fingerprint"));
206 }
207 decoded_fingerprints.emplace(decoded);
208 }
209
210 int err = gDnsResolv->resolverCtrl.setResolverConfiguration(
211 netId, servers, domains, params, tlsName, tlsServers, decoded_fingerprints);
Luke Huangc6bbbe72019-03-28 21:38:28 +0800212
213 gResNetdCallbacks.log(entry.returns(err).withAutomaticDuration().toString().c_str());
Luke Huang7b26b202019-03-28 14:09:24 +0800214 if (err != 0) {
215 return ::ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
216 -err, StringPrintf("ResolverController error: %s", strerror(-err)).c_str()));
217 }
218 return ::ndk::ScopedAStatus(AStatus_newOk());
219}
220
221::ndk::ScopedAStatus DnsResolverService::getResolverInfo(
222 int32_t netId, std::vector<std::string>* servers, std::vector<std::string>* domains,
223 std::vector<std::string>* tlsServers, std::vector<int32_t>* params,
224 std::vector<int32_t>* stats, std::vector<int32_t>* wait_for_pending_req_timeout_count) {
225 // Locking happens in PrivateDnsConfiguration and res_* functions.
226 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800227 auto entry = gDnsResolverLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId);
Luke Huang7b26b202019-03-28 14:09:24 +0800228
229 int err = gDnsResolv->resolverCtrl.getResolverInfo(netId, servers, domains, tlsServers, params,
230 stats, wait_for_pending_req_timeout_count);
Luke Huangc6bbbe72019-03-28 21:38:28 +0800231
232 gResNetdCallbacks.log(entry.returns(err).withAutomaticDuration().toString().c_str());
Luke Huang7b26b202019-03-28 14:09:24 +0800233 if (err != 0) {
234 return ::ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
235 -err, StringPrintf("ResolverController error: %s", strerror(-err)).c_str()));
236 }
237 return ::ndk::ScopedAStatus(AStatus_newOk());
238}
239
240::ndk::ScopedAStatus DnsResolverService::startPrefix64Discovery(int32_t netId) {
241 // Locking happens in Dns64Configuration.
242 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800243 auto entry = gDnsResolverLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId);
244
Luke Huang7b26b202019-03-28 14:09:24 +0800245 gDnsResolv->resolverCtrl.startPrefix64Discovery(netId);
246
Luke Huangc6bbbe72019-03-28 21:38:28 +0800247 gResNetdCallbacks.log(entry.withAutomaticDuration().toString().c_str());
Luke Huang7b26b202019-03-28 14:09:24 +0800248 return ::ndk::ScopedAStatus(AStatus_newOk());
249}
250
251::ndk::ScopedAStatus DnsResolverService::stopPrefix64Discovery(int32_t netId) {
252 // Locking happens in Dns64Configuration.
253 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800254 auto entry = gDnsResolverLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId);
255
Luke Huang7b26b202019-03-28 14:09:24 +0800256 gDnsResolv->resolverCtrl.stopPrefix64Discovery(netId);
257
Luke Huangc6bbbe72019-03-28 21:38:28 +0800258 gResNetdCallbacks.log(entry.withAutomaticDuration().toString().c_str());
Luke Huang7b26b202019-03-28 14:09:24 +0800259 return ::ndk::ScopedAStatus(AStatus_newOk());
260}
261
262::ndk::ScopedAStatus DnsResolverService::getPrefix64(int netId, std::string* stringPrefix) {
263 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800264 auto entry = gDnsResolverLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId);
265
Luke Huang7b26b202019-03-28 14:09:24 +0800266 netdutils::IPPrefix prefix{};
267 int err = gDnsResolv->resolverCtrl.getPrefix64(netId, &prefix);
Luke Huangc6bbbe72019-03-28 21:38:28 +0800268
269 gResNetdCallbacks.log(entry.returns(err).withAutomaticDuration().toString().c_str());
Luke Huang7b26b202019-03-28 14:09:24 +0800270 if (err != 0) {
271 return ::ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
272 -err, StringPrintf("ResolverController error: %s", strerror(-err)).c_str()));
273 }
274 *stringPrefix = prefix.toString();
275
276 return ::ndk::ScopedAStatus(AStatus_newOk());
277}
278
Luke Huang5bd827c2019-03-14 16:10:04 +0800279::ndk::ScopedAStatus DnsResolverService::clearResolverConfiguration(int netId) {
280 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800281 auto entry = gDnsResolverLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId);
Luke Huang5bd827c2019-03-14 16:10:04 +0800282
283 gDnsResolv->resolverCtrl.clearDnsServers(netId);
Luke Huangc6bbbe72019-03-28 21:38:28 +0800284
285 gResNetdCallbacks.log(entry.withAutomaticDuration().toString().c_str());
Luke Huang5bd827c2019-03-14 16:10:04 +0800286 return ::ndk::ScopedAStatus(AStatus_newOk());
287}
288
Luke Huang403c0442019-02-25 15:33:42 +0800289} // namespace net
290} // namespace android