/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if !ADB_HOST #define TRACE_TAG ADB_WIRELESS #include "adb_wifi.h" #include #include #include #include #include "adb.h" #include "daemon/mdns.h" #include "sysdeps.h" #include "transport.h" using namespace android::base; namespace { static AdbdAuthContext* auth_ctx; static void adb_disconnected(void* unused, atransport* t); static struct adisconnect adb_disconnect = {adb_disconnected, nullptr}; static void adb_disconnected(void* unused, atransport* t) { LOG(INFO) << "ADB wifi device disconnected"; CHECK(t->auth_id.has_value()); adbd_auth_tls_device_disconnected(auth_ctx, kAdbTransportTypeWifi, t->auth_id.value()); } // TODO(b/31559095): need bionic host so that we can use 'prop_info' returned // from WaitForProperty #if defined(__ANDROID__) class TlsServer { public: explicit TlsServer(int port); virtual ~TlsServer(); bool Start(); uint16_t port() { return port_; }; private: void OnFdEvent(int fd, unsigned ev); static void StaticOnFdEvent(int fd, unsigned ev, void* opaque); fdevent* fd_event_ = nullptr; uint16_t port_; }; // TlsServer TlsServer::TlsServer(int port) : port_(port) {} TlsServer::~TlsServer() { fdevent* fde = fd_event_; fdevent_run_on_main_thread([fde]() { if (fde != nullptr) { fdevent_destroy(fde); } }); } bool TlsServer::Start() { std::condition_variable cv; std::mutex mutex; std::optional success; auto callback = [&](bool result) { { std::lock_guard lock(mutex); success = result; } cv.notify_one(); }; std::string err; unique_fd fd(network_inaddr_any_server(port_, SOCK_STREAM, &err)); if (fd.get() == -1) { LOG(ERROR) << "Failed to start TLS server [" << err << "]"; return false; } close_on_exec(fd.get()); int port = socket_get_local_port(fd.get()); if (port <= 0 || port > 65535) { LOG(ERROR) << "Invalid port for tls server"; return false; } port_ = static_cast(port); LOG(INFO) << "adbwifi started on port " << port_; std::unique_lock lock(mutex); fdevent_run_on_main_thread([&]() { fd_event_ = fdevent_create(fd.release(), &TlsServer::StaticOnFdEvent, this); if (fd_event_ == nullptr) { LOG(ERROR) << "Failed to create fd event for TlsServer."; callback(false); return; } callback(true); }); cv.wait(lock, [&]() { return success.has_value(); }); if (!*success) { LOG(INFO) << "TlsServer fdevent_create failed"; return false; } fdevent_set(fd_event_, FDE_READ); LOG(INFO) << "TlsServer running on port " << port_; return *success; } // static void TlsServer::StaticOnFdEvent(int fd, unsigned ev, void* opaque) { auto server = reinterpret_cast(opaque); server->OnFdEvent(fd, ev); } void TlsServer::OnFdEvent(int fd, unsigned ev) { if ((ev & FDE_READ) == 0 || fd != fd_event_->fd.get()) { LOG(INFO) << __func__ << ": No read [ev=" << ev << " fd=" << fd << "]"; return; } unique_fd new_fd(adb_socket_accept(fd, nullptr, nullptr)); if (new_fd >= 0) { LOG(INFO) << "New TLS connection [fd=" << new_fd.get() << "]"; close_on_exec(new_fd.get()); disable_tcp_nagle(new_fd.get()); std::string serial = android::base::StringPrintf("host-%d", new_fd.get()); register_socket_transport( std::move(new_fd), std::move(serial), port_, 1, [](atransport*) { return ReconnectResult::Abort; }, true); } } TlsServer* sTlsServer = nullptr; const char kWifiPortProp[] = "service.adb.tls.port"; const char kWifiEnabledProp[] = "persist.adb.tls_server.enable"; static void enable_wifi_debugging() { start_mdnsd(); if (sTlsServer != nullptr) { delete sTlsServer; } sTlsServer = new TlsServer(0); if (!sTlsServer->Start()) { LOG(ERROR) << "Failed to start TlsServer"; delete sTlsServer; sTlsServer = nullptr; return; } // Start mdns connect service for discovery register_adb_secure_connect_service(sTlsServer->port()); LOG(INFO) << "adb wifi started on port " << sTlsServer->port(); SetProperty(kWifiPortProp, std::to_string(sTlsServer->port())); } static void disable_wifi_debugging() { if (sTlsServer != nullptr) { delete sTlsServer; sTlsServer = nullptr; } if (is_adb_secure_connect_service_registered()) { unregister_adb_secure_connect_service(); } kick_all_tcp_tls_transports(); LOG(INFO) << "adb wifi stopped"; SetProperty(kWifiPortProp, ""); } // Watches for the #kWifiEnabledProp property to toggle the TlsServer static void start_wifi_enabled_observer() { std::thread([]() { bool wifi_enabled = false; while (true) { std::string toggled_val = wifi_enabled ? "0" : "1"; LOG(INFO) << "Waiting for " << kWifiEnabledProp << "=" << toggled_val; if (WaitForProperty(kWifiEnabledProp, toggled_val)) { wifi_enabled = !wifi_enabled; LOG(INFO) << kWifiEnabledProp << " changed to " << toggled_val; if (wifi_enabled) { enable_wifi_debugging(); } else { disable_wifi_debugging(); } } } }).detach(); } #endif //__ANDROID__ } // namespace void adbd_wifi_init(AdbdAuthContext* ctx) { auth_ctx = ctx; #if defined(__ANDROID__) start_wifi_enabled_observer(); #endif //__ANDROID__ } void adbd_wifi_secure_connect(atransport* t) { t->AddDisconnect(&adb_disconnect); handle_online(t); send_connect(t); LOG(INFO) << __func__ << ": connected " << t->serial; t->auth_id = adbd_auth_tls_device_connected(auth_ctx, kAdbTransportTypeWifi, t->auth_key.data(), t->auth_key.size()); } #endif /* !HOST */