• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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