1 /*
2 * Copyright (C) 2016 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 #include "mdns.h"
18
19 #include "adb_mdns.h"
20 #include "adb_trace.h"
21 #include "sysdeps.h"
22
23 #include <dns_sd.h>
24 #include <endian.h>
25 #include <unistd.h>
26
27 #include <chrono>
28 #include <mutex>
29 #include <random>
30 #include <thread>
31
32 #include <android-base/logging.h>
33 #include <android-base/properties.h>
34 #include <android-base/thread_annotations.h>
35
36 using namespace std::chrono_literals;
37
38 static std::mutex& mdns_lock = *new std::mutex();
39
40 // TCP socket port ADBd is listening for incoming connections
41 static int tcp_port;
42
43 static DNSServiceRef mdns_refs[kNumADBDNSServices] GUARDED_BY(mdns_lock);
44 static bool mdns_registered[kNumADBDNSServices] GUARDED_BY(mdns_lock);
45
start_mdnsd()46 void start_mdnsd() {
47 if (android::base::GetProperty("init.svc.mdnsd", "") == "running") {
48 return;
49 }
50
51 android::base::SetProperty("ctl.start", "mdnsd");
52
53 if (! android::base::WaitForProperty("init.svc.mdnsd", "running", 5s)) {
54 LOG(ERROR) << "Could not start mdnsd.";
55 }
56 }
57
mdns_callback(DNSServiceRef,DNSServiceFlags,DNSServiceErrorType errorCode,const char *,const char *,const char *,void *)58 static void mdns_callback(DNSServiceRef /*ref*/,
59 DNSServiceFlags /*flags*/,
60 DNSServiceErrorType errorCode,
61 const char* /*name*/,
62 const char* /*regtype*/,
63 const char* /*domain*/,
64 void* /*context*/) {
65 if (errorCode != kDNSServiceErr_NoError) {
66 LOG(ERROR) << "Encountered mDNS registration error ("
67 << errorCode << ").";
68 }
69 }
70
buildTxtRecord()71 static std::vector<char> buildTxtRecord() {
72 std::map<std::string, std::string> attributes;
73 attributes["v"] = std::to_string(ADB_SECURE_SERVICE_VERSION);
74 attributes["name"] = android::base::GetProperty("ro.product.model", "");
75 attributes["api"] = android::base::GetProperty("ro.build.version.sdk", "");
76
77 // See https://tools.ietf.org/html/rfc6763 for the format of DNS TXT record.
78 std::vector<char> record;
79 for (auto const& [key, val] : attributes) {
80 size_t length = key.size() + val.size() + 1;
81 if (length > 255) {
82 LOG(INFO) << "DNS TXT Record property " << key << "='" << val << "' is too large.";
83 continue;
84 }
85 record.emplace_back(length);
86 std::copy(key.begin(), key.end(), std::back_inserter(record));
87 record.emplace_back('=');
88 std::copy(val.begin(), val.end(), std::back_inserter(record));
89 }
90
91 return record;
92 }
93
register_mdns_service(int index,int port,const std::string & service_name)94 static void register_mdns_service(int index, int port, const std::string& service_name) {
95 std::lock_guard<std::mutex> lock(mdns_lock);
96
97 auto txtRecord = buildTxtRecord();
98 auto error = DNSServiceRegister(
99 &mdns_refs[index], 0, 0, service_name.c_str(), kADBDNSServices[index], nullptr, nullptr,
100 htobe16((uint16_t)port), (uint16_t)txtRecord.size(),
101 txtRecord.empty() ? nullptr : txtRecord.data(), mdns_callback, nullptr);
102
103 if (error != kDNSServiceErr_NoError) {
104 LOG(ERROR) << "Could not register mDNS service " << kADBDNSServices[index] << ", error ("
105 << error << ").";
106 mdns_registered[index] = false;
107 } else {
108 mdns_registered[index] = true;
109 }
110 VLOG(MDNS) << "adbd mDNS service " << kADBDNSServices[index]
111 << " registered: " << mdns_registered[index];
112 }
113
unregister_mdns_service(int index)114 static void unregister_mdns_service(int index) {
115 std::lock_guard<std::mutex> lock(mdns_lock);
116
117 if (mdns_registered[index]) {
118 DNSServiceRefDeallocate(mdns_refs[index]);
119 }
120 }
121
register_base_mdns_transport()122 static void register_base_mdns_transport() {
123 std::string hostname = "adb-";
124 hostname += android::base::GetProperty("ro.serialno", "unidentified");
125 register_mdns_service(kADBTransportServiceRefIndex, tcp_port, hostname);
126 }
127
setup_mdns_thread()128 static void setup_mdns_thread() {
129 start_mdnsd();
130
131 // We will now only set up the normal transport mDNS service
132 // instead of registering all the adb secure mDNS services
133 // in the beginning. This is to provide more privacy/security.
134 register_base_mdns_transport();
135 }
136
137 // This also tears down any adb secure mDNS services, if they exist.
teardown_mdns()138 static void teardown_mdns() {
139 for (int i = 0; i < kNumADBDNSServices; ++i) {
140 unregister_mdns_service(i);
141 }
142 }
143
RandomAlphaNumString(size_t len)144 static std::string RandomAlphaNumString(size_t len) {
145 std::string ret;
146 std::random_device rd;
147 std::mt19937 mt(rd());
148 // Generate values starting with zero and then up to enough to cover numeric
149 // digits, small letters and capital letters (26 each).
150 std::uniform_int_distribution<uint8_t> dist(0, 61);
151 for (size_t i = 0; i < len; ++i) {
152 uint8_t val = dist(mt);
153 if (val < 10) {
154 ret += static_cast<char>('0' + val);
155 } else if (val < 36) {
156 ret += static_cast<char>('A' + (val - 10));
157 } else {
158 ret += static_cast<char>('a' + (val - 36));
159 }
160 }
161 return ret;
162 }
163
GenerateDeviceGuid()164 static std::string GenerateDeviceGuid() {
165 // The format is adb-<serial_no>-<six-random-alphanum>
166 std::string guid = "adb-";
167
168 std::string serial = android::base::GetProperty("ro.serialno", "");
169 if (serial.empty()) {
170 // Generate 16-bytes of random alphanum string
171 serial = RandomAlphaNumString(16);
172 }
173 guid += serial + '-';
174 // Random six-char suffix
175 guid += RandomAlphaNumString(6);
176 return guid;
177 }
178
ReadDeviceGuid()179 static std::string ReadDeviceGuid() {
180 std::string guid = android::base::GetProperty("persist.adb.wifi.guid", "");
181 if (guid.empty()) {
182 guid = GenerateDeviceGuid();
183 CHECK(!guid.empty());
184 android::base::SetProperty("persist.adb.wifi.guid", guid);
185 }
186 return guid;
187 }
188
189 // Public interface/////////////////////////////////////////////////////////////
190
setup_mdns(int tcp_port_in)191 void setup_mdns(int tcp_port_in) {
192 // Make sure the adb wifi guid is generated.
193 std::string guid = ReadDeviceGuid();
194 CHECK(!guid.empty());
195 tcp_port = tcp_port_in;
196 std::thread(setup_mdns_thread).detach();
197
198 // TODO: Make this more robust against a hard kill.
199 atexit(teardown_mdns);
200 }
201
register_adb_secure_connect_service(int tls_port)202 void register_adb_secure_connect_service(int tls_port) {
203 std::thread([tls_port]() {
204 auto service_name = ReadDeviceGuid();
205 if (service_name.empty()) {
206 return;
207 }
208 VLOG(MDNS) << "Registering secure_connect service (" << service_name << ")";
209 register_mdns_service(kADBSecureConnectServiceRefIndex, tls_port, service_name);
210 }).detach();
211 }
212
unregister_adb_secure_connect_service()213 void unregister_adb_secure_connect_service() {
214 std::thread([]() { unregister_mdns_service(kADBSecureConnectServiceRefIndex); }).detach();
215 }
216
is_adb_secure_connect_service_registered()217 bool is_adb_secure_connect_service_registered() {
218 std::lock_guard<std::mutex> lock(mdns_lock);
219 return mdns_registered[kADBSecureConnectServiceRefIndex];
220 }
221