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