blob: 949e67a78908e20a85e52465566b61b83154f53a [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
waynema37255182019-03-18 13:22:56 +080039using aidl::android::net::ResolverParamsParcel;
Luke Huang403c0442019-02-25 15:33:42 +080040using android::base::Join;
41using android::base::StringPrintf;
Luke Huang7b26b202019-03-28 14:09:24 +080042using android::netdutils::DumpWriter;
Luke Huang403c0442019-02-25 15:33:42 +080043
44namespace android {
45namespace net {
46
47namespace {
48
49#define ENFORCE_ANY_PERMISSION(...) \
50 do { \
51 ::ndk::ScopedAStatus status = checkAnyPermission({__VA_ARGS__}); \
52 if (!status.isOk()) { \
53 return status; \
54 } \
55 } while (0)
56
57#define ENFORCE_INTERNAL_PERMISSIONS() \
58 ENFORCE_ANY_PERMISSION(PERM_CONNECTIVITY_INTERNAL, PERM_MAINLINE_NETWORK_STACK)
59
60#define ENFORCE_NETWORK_STACK_PERMISSIONS() \
61 ENFORCE_ANY_PERMISSION(PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK)
62
Hungming Chena32c8c12019-01-25 10:47:40 +080063inline ::ndk::ScopedAStatus statusFromErrcode(int ret) {
64 if (ret) {
65 return ::ndk::ScopedAStatus(
66 AStatus_fromServiceSpecificErrorWithMessage(-ret, strerror(-ret)));
67 }
68 return ::ndk::ScopedAStatus(AStatus_newOk());
69}
70
Luke Huang403c0442019-02-25 15:33:42 +080071} // namespace
72
Luke Huang36796f32019-03-13 02:54:45 +080073binder_status_t DnsResolverService::start() {
Luke Huang403c0442019-02-25 15:33:42 +080074 // TODO: Add disableBackgroundScheduling(true) after libbinder_ndk support it. b/126506010
75 // NetdNativeService does call disableBackgroundScheduling currently, so it is fine now.
Luke Huang36796f32019-03-13 02:54:45 +080076 DnsResolverService* resolverService = new DnsResolverService();
Luke Huang403c0442019-02-25 15:33:42 +080077 binder_status_t status =
78 AServiceManager_addService(resolverService->asBinder().get(), getServiceName());
79 if (status != STATUS_OK) {
80 return status;
81 }
82
83 ABinderProcess_startThreadPool();
84
85 // TODO: register log callback if binder NDK backend support it. b/126501406
86
87 return STATUS_OK;
88}
89
Luke Huangc6bbbe72019-03-28 21:38:28 +080090binder_status_t DnsResolverService::dump(int fd, const char**, uint32_t) {
91 auto dump_permission = checkAnyPermission({PERM_DUMP});
92 if (!dump_permission.isOk()) {
93 return STATUS_PERMISSION_DENIED;
94 }
95
96 // This method does not grab any locks. If individual classes need locking
97 // their dump() methods MUST handle locking appropriately.
98 DumpWriter dw(fd);
99 for (auto netId : resolv_list_caches()) {
100 dw.println("NetId: %u", netId);
101 gDnsResolv->resolverCtrl.dump(dw, netId);
102 dw.blankline();
103 }
104
Luke Huang7b26b202019-03-28 14:09:24 +0800105 return STATUS_OK;
106}
107
Luke Huang403c0442019-02-25 15:33:42 +0800108::ndk::ScopedAStatus DnsResolverService::isAlive(bool* alive) {
109 ENFORCE_INTERNAL_PERMISSIONS();
110
111 *alive = true;
112
113 return ::ndk::ScopedAStatus(AStatus_newOk());
114}
115
Hungming Chena32c8c12019-01-25 10:47:40 +0800116::ndk::ScopedAStatus DnsResolverService::registerEventListener(
117 const std::shared_ptr<aidl::android::net::metrics::INetdEventListener>& listener) {
118 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800119 auto entry = gDnsResolverLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
Hungming Chena32c8c12019-01-25 10:47:40 +0800120
121 int res = ResolverEventReporter::getInstance().addListener(listener);
122
Luke Huangc6bbbe72019-03-28 21:38:28 +0800123 gResNetdCallbacks.log(entry.returns(res).withAutomaticDuration().toString().c_str());
Hungming Chena32c8c12019-01-25 10:47:40 +0800124 return statusFromErrcode(res);
125}
126
Luke Huang403c0442019-02-25 15:33:42 +0800127::ndk::ScopedAStatus DnsResolverService::checkAnyPermission(
128 const std::vector<const char*>& permissions) {
129 // TODO: Remove callback and move this to unnamed namespace after libbiner_ndk supports
130 // check_permission.
Luke Huang36796f32019-03-13 02:54:45 +0800131 if (!gResNetdCallbacks.check_calling_permission) {
Luke Huang403c0442019-02-25 15:33:42 +0800132 return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(
133 EX_NULL_POINTER, "check_calling_permission is null"));
134 }
135 pid_t pid = AIBinder_getCallingPid();
136 uid_t uid = AIBinder_getCallingUid();
137
138 // If the caller is the system UID, don't check permissions.
139 // Otherwise, if the system server's binder thread pool is full, and all the threads are
140 // blocked on a thread that's waiting for us to complete, we deadlock. http://b/69389492
141 //
142 // From a security perspective, there is currently no difference, because:
143 // 1. The only permissions we check in netd's binder interface are CONNECTIVITY_INTERNAL
144 // and NETWORK_STACK, which the system server always has (or MAINLINE_NETWORK_STACK, which
145 // is equivalent to having both CONNECTIVITY_INTERNAL and NETWORK_STACK).
146 // 2. AID_SYSTEM always has all permissions. See ActivityManager#checkComponentPermission.
147 if (uid == AID_SYSTEM) {
148 return ::ndk::ScopedAStatus(AStatus_newOk());
149 }
150
151 for (const char* permission : permissions) {
Luke Huang36796f32019-03-13 02:54:45 +0800152 if (gResNetdCallbacks.check_calling_permission(permission)) {
Luke Huang403c0442019-02-25 15:33:42 +0800153 return ::ndk::ScopedAStatus(AStatus_newOk());
154 }
155 }
156
157 auto err = StringPrintf("UID %d / PID %d does not have any of the following permissions: %s",
158 uid, pid, Join(permissions, ',').c_str());
159 return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(EX_SECURITY, err.c_str()));
160}
161
Luke Huang7b26b202019-03-28 14:09:24 +0800162namespace {
163
164// Parse a base64 encoded string into a vector of bytes.
165// On failure, return an empty vector.
166static std::vector<uint8_t> parseBase64(const std::string& input) {
167 std::vector<uint8_t> decoded;
168 size_t out_len;
169 if (EVP_DecodedLength(&out_len, input.size()) != 1) {
170 return decoded;
171 }
172 // out_len is now an upper bound on the output length.
173 decoded.resize(out_len);
174 if (EVP_DecodeBase64(decoded.data(), &out_len, decoded.size(),
175 reinterpret_cast<const uint8_t*>(input.data()), input.size()) == 1) {
176 // Possibly shrink the vector if the actual output was smaller than the bound.
177 decoded.resize(out_len);
178 } else {
179 decoded.clear();
180 }
181 if (out_len != SHA256_SIZE) {
182 decoded.clear();
183 }
184 return decoded;
185}
186
187} // namespace
188
189::ndk::ScopedAStatus DnsResolverService::setResolverConfiguration(
waynema37255182019-03-18 13:22:56 +0800190 const ResolverParamsParcel& resolverParams) {
Luke Huang7b26b202019-03-28 14:09:24 +0800191 // Locking happens in PrivateDnsConfiguration and res_* functions.
192 ENFORCE_INTERNAL_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800193 auto entry =
194 gDnsResolverLog.newEntry()
195 .prettyFunction(__PRETTY_FUNCTION__)
waynema37255182019-03-18 13:22:56 +0800196 .args(resolverParams.netId, resolverParams.servers, resolverParams.domains,
197 resolverParams.sampleValiditySeconds, resolverParams.successThreshold,
198 resolverParams.minSamples, resolverParams.maxSamples,
waynema9a530232019-04-18 19:13:26 +0800199 resolverParams.baseTimeoutMsec, resolverParams.retryCount,
200 resolverParams.tlsServers, resolverParams.tlsFingerprints);
Luke Huang7b26b202019-03-28 14:09:24 +0800201
202 std::set<std::vector<uint8_t>> decoded_fingerprints;
waynema37255182019-03-18 13:22:56 +0800203 for (const std::string& fingerprint : resolverParams.tlsFingerprints) {
Luke Huang7b26b202019-03-28 14:09:24 +0800204 std::vector<uint8_t> decoded = parseBase64(fingerprint);
205 if (decoded.empty()) {
206 return ::ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
207 EINVAL, "ResolverController error: bad fingerprint"));
208 }
209 decoded_fingerprints.emplace(decoded);
210 }
211
waynema37255182019-03-18 13:22:56 +0800212 int err =
213 gDnsResolv->resolverCtrl.setResolverConfiguration(resolverParams, decoded_fingerprints);
Luke Huangc6bbbe72019-03-28 21:38:28 +0800214
215 gResNetdCallbacks.log(entry.returns(err).withAutomaticDuration().toString().c_str());
Luke Huang7b26b202019-03-28 14:09:24 +0800216 if (err != 0) {
217 return ::ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
218 -err, StringPrintf("ResolverController error: %s", strerror(-err)).c_str()));
219 }
220 return ::ndk::ScopedAStatus(AStatus_newOk());
221}
222
223::ndk::ScopedAStatus DnsResolverService::getResolverInfo(
224 int32_t netId, std::vector<std::string>* servers, std::vector<std::string>* domains,
225 std::vector<std::string>* tlsServers, std::vector<int32_t>* params,
226 std::vector<int32_t>* stats, std::vector<int32_t>* wait_for_pending_req_timeout_count) {
227 // Locking happens in PrivateDnsConfiguration and res_* functions.
228 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800229 auto entry = gDnsResolverLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId);
Luke Huang7b26b202019-03-28 14:09:24 +0800230
231 int err = gDnsResolv->resolverCtrl.getResolverInfo(netId, servers, domains, tlsServers, params,
232 stats, wait_for_pending_req_timeout_count);
Luke Huangc6bbbe72019-03-28 21:38:28 +0800233
234 gResNetdCallbacks.log(entry.returns(err).withAutomaticDuration().toString().c_str());
Luke Huang7b26b202019-03-28 14:09:24 +0800235 if (err != 0) {
236 return ::ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
237 -err, StringPrintf("ResolverController error: %s", strerror(-err)).c_str()));
238 }
239 return ::ndk::ScopedAStatus(AStatus_newOk());
240}
241
242::ndk::ScopedAStatus DnsResolverService::startPrefix64Discovery(int32_t netId) {
243 // Locking happens in Dns64Configuration.
244 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800245 auto entry = gDnsResolverLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId);
246
Luke Huang7b26b202019-03-28 14:09:24 +0800247 gDnsResolv->resolverCtrl.startPrefix64Discovery(netId);
248
Luke Huangc6bbbe72019-03-28 21:38:28 +0800249 gResNetdCallbacks.log(entry.withAutomaticDuration().toString().c_str());
Luke Huang7b26b202019-03-28 14:09:24 +0800250 return ::ndk::ScopedAStatus(AStatus_newOk());
251}
252
253::ndk::ScopedAStatus DnsResolverService::stopPrefix64Discovery(int32_t netId) {
254 // Locking happens in Dns64Configuration.
255 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800256 auto entry = gDnsResolverLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId);
257
Luke Huang7b26b202019-03-28 14:09:24 +0800258 gDnsResolv->resolverCtrl.stopPrefix64Discovery(netId);
259
Luke Huangc6bbbe72019-03-28 21:38:28 +0800260 gResNetdCallbacks.log(entry.withAutomaticDuration().toString().c_str());
Luke Huang7b26b202019-03-28 14:09:24 +0800261 return ::ndk::ScopedAStatus(AStatus_newOk());
262}
263
264::ndk::ScopedAStatus DnsResolverService::getPrefix64(int netId, std::string* stringPrefix) {
265 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800266 auto entry = gDnsResolverLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId);
267
Luke Huang7b26b202019-03-28 14:09:24 +0800268 netdutils::IPPrefix prefix{};
269 int err = gDnsResolv->resolverCtrl.getPrefix64(netId, &prefix);
Luke Huangc6bbbe72019-03-28 21:38:28 +0800270
271 gResNetdCallbacks.log(entry.returns(err).withAutomaticDuration().toString().c_str());
Luke Huang7b26b202019-03-28 14:09:24 +0800272 if (err != 0) {
273 return ::ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
274 -err, StringPrintf("ResolverController error: %s", strerror(-err)).c_str()));
275 }
276 *stringPrefix = prefix.toString();
277
278 return ::ndk::ScopedAStatus(AStatus_newOk());
279}
280
Luke Huang9b80e6c2019-04-09 17:54:09 +0800281::ndk::ScopedAStatus DnsResolverService::destroyNetworkCache(int netId) {
282 // Locking happens in res_cache.cpp functions.
Luke Huang5bd827c2019-03-14 16:10:04 +0800283 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800284 auto entry = gDnsResolverLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId);
Luke Huang5bd827c2019-03-14 16:10:04 +0800285
Luke Huang9b80e6c2019-04-09 17:54:09 +0800286 gDnsResolv->resolverCtrl.destroyNetworkCache(netId);
Luke Huangc6bbbe72019-03-28 21:38:28 +0800287
288 gResNetdCallbacks.log(entry.withAutomaticDuration().toString().c_str());
Luke Huang5bd827c2019-03-14 16:10:04 +0800289 return ::ndk::ScopedAStatus(AStatus_newOk());
290}
291
Luke Huang9b80e6c2019-04-09 17:54:09 +0800292::ndk::ScopedAStatus DnsResolverService::createNetworkCache(int netId) {
293 // Locking happens in res_cache.cpp functions.
294 ENFORCE_NETWORK_STACK_PERMISSIONS();
295 auto entry = gDnsResolverLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId);
296
297 int res = gDnsResolv->resolverCtrl.createNetworkCache(netId);
298
299 gResNetdCallbacks.log(entry.returns(res).withAutomaticDuration().toString().c_str());
300 return statusFromErrcode(res);
301}
302
Luke Huang403c0442019-02-25 15:33:42 +0800303} // namespace net
304} // namespace android