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 "socket_spec.h" 18 19 #include <limits> 20 #include <string> 21 #include <string_view> 22 #include <unordered_map> 23 #include <vector> 24 25 #include <android-base/parseint.h> 26 #include <android-base/parsenetaddress.h> 27 #include <android-base/stringprintf.h> 28 #include <android-base/strings.h> 29 #include <cutils/sockets.h> 30 31 #include "adb.h" 32 #include "adb_auth.h" 33 #include "adb_mdns.h" 34 #include "adb_utils.h" 35 #include "sysdeps.h" 36 37 using namespace std::string_literals; 38 39 using android::base::ConsumePrefix; 40 using android::base::StringPrintf; 41 42 #if defined(__linux__) 43 #define ADB_LINUX 1 44 #else 45 #define ADB_LINUX 0 46 #endif 47 48 #if defined(_WIN32) 49 #define ADB_WINDOWS 1 50 #else 51 #define ADB_WINDOWS 0 52 #endif 53 54 #if ADB_LINUX 55 #include <sys/socket.h> 56 #include "sysdeps/vm_sockets.h" 57 #endif 58 59 // Not static because it is used in commandline.c. 60 int gListenAll = 0; 61 62 struct LocalSocketType { 63 int socket_namespace; 64 bool available; 65 }; 66 67 static auto& kLocalSocketTypes = *new std::unordered_map<std::string, LocalSocketType>({ 68 #if ADB_HOST 69 { "local", { ANDROID_SOCKET_NAMESPACE_FILESYSTEM, !ADB_WINDOWS } }, 70 #else 71 { "local", { ANDROID_SOCKET_NAMESPACE_RESERVED, !ADB_WINDOWS } }, 72 #endif 73 74 { "localreserved", { ANDROID_SOCKET_NAMESPACE_RESERVED, !ADB_HOST } }, 75 { "localabstract", { ANDROID_SOCKET_NAMESPACE_ABSTRACT, ADB_LINUX } }, 76 { "localfilesystem", { ANDROID_SOCKET_NAMESPACE_FILESYSTEM, !ADB_WINDOWS } }, 77 }); 78 79 bool parse_tcp_socket_spec(std::string_view spec, std::string* hostname, int* port, 80 std::string* serial, std::string* error) { 81 if (!spec.starts_with("tcp:")) { 82 *error = "specification is not tcp: "; 83 *error += spec; 84 return false; 85 } 86 87 std::string hostname_value; 88 int port_value; 89 90 // If the spec is tcp:<port>, parse it ourselves. 91 // Otherwise, delegate to android::base::ParseNetAddress. 92 if (android::base::ParseInt(&spec[4], &port_value)) { 93 // Do the range checking ourselves, because ParseInt rejects 'tcp:65536' and 'tcp:foo:1234' 94 // identically. 95 if (port_value < 0 || port_value > 65535) { 96 *error = StringPrintf("bad port number '%d'", port_value); 97 return false; 98 } 99 } else { 100 std::string addr(spec.substr(4)); 101 port_value = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; 102 103 // FIXME: ParseNetAddress rejects port 0. This currently doesn't hurt, because listening 104 // on an address that isn't 'localhost' is unsupported. 105 if (!android::base::ParseNetAddress(addr, &hostname_value, &port_value, serial, error)) { 106 return false; 107 } 108 } 109 110 if (hostname) { 111 *hostname = std::move(hostname_value); 112 } 113 114 if (port) { 115 *port = port_value; 116 } 117 118 return true; 119 } 120 121 int get_host_socket_spec_port(std::string_view spec, std::string* error) { 122 int port; 123 if (spec.starts_with("tcp:")) { 124 if (!parse_tcp_socket_spec(spec, nullptr, &port, nullptr, error)) { 125 return -1; 126 } 127 } else if (spec.starts_with("vsock:")) { 128 #if ADB_LINUX 129 std::string spec_str(spec); 130 std::vector<std::string> fragments = android::base::Split(spec_str, ":"); 131 if (fragments.size() != 2) { 132 *error = "given vsock server socket string was invalid"; 133 return -1; 134 } 135 if (!android::base::ParseInt(fragments[1], &port)) { 136 *error = "could not parse vsock port"; 137 errno = EINVAL; 138 return -1; 139 } 140 if (port < 0) { 141 *error = "vsock port was negative."; 142 errno = EINVAL; 143 return -1; 144 } 145 #else // ADB_LINUX 146 *error = "vsock is only supported on linux"; 147 return -1; 148 #endif // ADB_LINUX 149 } else { 150 *error = "given socket spec string was invalid"; 151 return -1; 152 } 153 return port; 154 } 155 156 static bool tcp_host_is_local(std::string_view hostname) { 157 // FIXME 158 return hostname.empty() || hostname == "localhost"; 159 } 160 161 bool is_socket_spec(std::string_view spec) { 162 for (const auto& it : kLocalSocketTypes) { 163 std::string prefix = it.first + ":"; 164 if (spec.starts_with(prefix)) { 165 return true; 166 } 167 } 168 return spec.starts_with("tcp:") || spec.starts_with("acceptfd:") || spec.starts_with("vsock:"); 169 } 170 171 bool is_local_socket_spec(std::string_view spec) { 172 for (const auto& it : kLocalSocketTypes) { 173 std::string prefix = it.first + ":"; 174 if (spec.starts_with(prefix)) { 175 return true; 176 } 177 } 178 179 std::string error; 180 std::string hostname; 181 if (!parse_tcp_socket_spec(spec, &hostname, nullptr, nullptr, &error)) { 182 return false; 183 } 184 return tcp_host_is_local(hostname); 185 } 186 187 bool socket_spec_connect(unique_fd* fd, std::string_view address, int* port, std::string* serial, 188 std::string* error) { 189 #if !ADB_HOST 190 if (!socket_access_allowed) { // Check whether this security suppression is 191 // active (initiated from minadbd), and if so disable socket communications 192 // for the (min)deamon. 193 *error = "Suppressing minadbd socket communications"; 194 return false; 195 } 196 #endif 197 198 if (address.starts_with("tcp:")) { 199 std::string hostname; 200 int port_value = port ? *port : 0; 201 if (!parse_tcp_socket_spec(address, &hostname, &port_value, serial, error)) { 202 return false; 203 } 204 205 if (tcp_host_is_local(hostname)) { 206 fd->reset(network_loopback_client(port_value, SOCK_STREAM, error)); 207 } else { 208 #if ADB_HOST 209 // Check if the address is an mdns service we can connect to. 210 if (auto mdns_info = mdns_get_connect_service_info(std::string(address.substr(4))); 211 mdns_info != std::nullopt) { 212 fd->reset(network_connect(mdns_info->addr, mdns_info->port, SOCK_STREAM, 0, error)); 213 if (fd->get() != -1) { 214 // TODO(joshuaduong): We still show the ip address for the serial. Change it to 215 // use the mdns instance name, so we can adjust to address changes on 216 // reconnects. 217 port_value = mdns_info->port; 218 if (serial) { 219 *serial = android::base::StringPrintf("%s.%s", 220 mdns_info->service_name.c_str(), 221 mdns_info->service_type.c_str()); 222 } 223 } 224 } else { 225 fd->reset(network_connect(hostname, port_value, SOCK_STREAM, 0, error)); 226 } 227 #else 228 // Disallow arbitrary connections in adbd. 229 *error = "adbd does not support arbitrary tcp connections"; 230 return false; 231 #endif 232 } 233 234 if (fd->get() > 0) { 235 int keepalive_interval = 1; 236 if (const char* keepalive_env = getenv("ADB_TCP_KEEPALIVE_INTERVAL")) { 237 android::base::ParseInt(keepalive_env, &keepalive_interval, 0); 238 } 239 240 set_tcp_keepalive(fd->get(), keepalive_interval); 241 disable_tcp_nagle(fd->get()); 242 if (port) { 243 *port = port_value; 244 } 245 return true; 246 } 247 return false; 248 } else if (address.starts_with("vsock:")) { 249 #if ADB_LINUX 250 std::string spec_str(address); 251 std::vector<std::string> fragments = android::base::Split(spec_str, ":"); 252 unsigned int port_value = port ? *port : 0; 253 if (fragments.size() != 2 && fragments.size() != 3) { 254 *error = android::base::StringPrintf("expected vsock:cid or vsock:cid:port in '%s'", 255 spec_str.c_str()); 256 errno = EINVAL; 257 return false; 258 } 259 unsigned int cid = 0; 260 if (!android::base::ParseUint(fragments[1], &cid)) { 261 *error = android::base::StringPrintf("could not parse vsock cid in '%s'", 262 spec_str.c_str()); 263 errno = EINVAL; 264 return false; 265 } 266 if (fragments.size() == 3 && !android::base::ParseUint(fragments[2], &port_value)) { 267 *error = android::base::StringPrintf("could not parse vsock port in '%s'", 268 spec_str.c_str()); 269 errno = EINVAL; 270 return false; 271 } 272 if (port_value == 0) { 273 *error = android::base::StringPrintf("vsock port was not provided."); 274 errno = EINVAL; 275 return false; 276 } 277 fd->reset(socket(AF_VSOCK, SOCK_STREAM, 0)); 278 if (fd->get() == -1) { 279 *error = "could not open vsock socket"; 280 return false; 281 } 282 sockaddr_vm addr{}; 283 addr.svm_family = AF_VSOCK; 284 addr.svm_port = port_value; 285 addr.svm_cid = cid; 286 if (serial) { 287 *serial = android::base::StringPrintf("vsock:%u:%d", cid, port_value); 288 } 289 if (connect(fd->get(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr))) { 290 int error_num = errno; 291 *error = android::base::StringPrintf("could not connect to vsock address '%s'", 292 spec_str.c_str()); 293 errno = error_num; 294 return false; 295 } 296 if (port) { 297 *port = port_value; 298 } 299 return true; 300 #else // ADB_LINUX 301 *error = "vsock is only supported on Linux"; 302 return false; 303 #endif // ADB_LINUX 304 } else if (address.starts_with("acceptfd:")) { 305 *error = "cannot connect to acceptfd"; 306 return false; 307 } 308 309 for (const auto& it : kLocalSocketTypes) { 310 std::string prefix = it.first + ":"; 311 if (address.starts_with(prefix)) { 312 if (!it.second.available) { 313 *error = StringPrintf("socket type %s is unavailable on this platform", 314 it.first.c_str()); 315 return false; 316 } 317 318 fd->reset(network_local_client(&address[prefix.length()], it.second.socket_namespace, 319 SOCK_STREAM, error)); 320 321 if (fd->get() < 0) { 322 *error = 323 android::base::StringPrintf("could not connect to %s address '%s'", 324 it.first.c_str(), std::string(address).c_str()); 325 return false; 326 } 327 328 if (serial) { 329 *serial = address; 330 } 331 return true; 332 } 333 } 334 335 *error = "unknown socket specification: "; 336 *error += address; 337 return false; 338 } 339 340 int socket_spec_listen(std::string_view spec, std::string* error, int* resolved_port) { 341 if (spec.starts_with("tcp:")) { 342 std::string hostname; 343 int port; 344 if (!parse_tcp_socket_spec(spec, &hostname, &port, nullptr, error)) { 345 return -1; 346 } 347 348 int result; 349 #if ADB_HOST 350 if (hostname.empty() && gListenAll) { 351 #else 352 if (hostname.empty()) { 353 #endif 354 result = network_inaddr_any_server(port, SOCK_STREAM, error); 355 } else if (tcp_host_is_local(hostname)) { 356 result = network_loopback_server(port, SOCK_STREAM, error, true); 357 } else if (hostname == "::1") { 358 result = network_loopback_server(port, SOCK_STREAM, error, false); 359 } else { 360 // TODO: Implement me. 361 *error = "listening on specified hostname currently unsupported"; 362 return -1; 363 } 364 365 if (result >= 0 && resolved_port) { 366 *resolved_port = adb_socket_get_local_port(result); 367 } 368 return result; 369 } else if (spec.starts_with("vsock:")) { 370 #if ADB_LINUX 371 std::string spec_str(spec); 372 std::vector<std::string> fragments = android::base::Split(spec_str, ":"); 373 if (fragments.size() != 2) { 374 *error = "given vsock server socket string was invalid"; 375 return -1; 376 } 377 int port; 378 if (!android::base::ParseInt(fragments[1], &port)) { 379 *error = "could not parse vsock port"; 380 errno = EINVAL; 381 return -1; 382 } else if (port < 0) { 383 *error = "vsock port was negative."; 384 errno = EINVAL; 385 return -1; 386 } 387 unique_fd serverfd(socket(AF_VSOCK, SOCK_STREAM, 0)); 388 if (serverfd == -1) { 389 int error_num = errno; 390 *error = android::base::StringPrintf("could not create vsock server: '%s'", 391 strerror(error_num)); 392 errno = error_num; 393 return -1; 394 } 395 sockaddr_vm addr{}; 396 addr.svm_family = AF_VSOCK; 397 addr.svm_port = port == 0 ? VMADDR_PORT_ANY : port; 398 addr.svm_cid = VMADDR_CID_ANY; 399 socklen_t addr_len = sizeof(addr); 400 if (bind(serverfd.get(), reinterpret_cast<struct sockaddr*>(&addr), addr_len)) { 401 return -1; 402 } 403 if (listen(serverfd.get(), 4)) { 404 return -1; 405 } 406 if (serverfd >= 0 && resolved_port) { 407 if (getsockname(serverfd.get(), reinterpret_cast<sockaddr*>(&addr), &addr_len) == 0) { 408 *resolved_port = addr.svm_port; 409 } else { 410 return -1; 411 } 412 } 413 return serverfd.release(); 414 #else // ADB_LINUX 415 *error = "vsock is only supported on linux"; 416 return -1; 417 #endif // ADB_LINUX 418 } else if (ConsumePrefix(&spec, "acceptfd:")) { 419 #if ADB_WINDOWS 420 *error = "socket activation not supported under Windows"; 421 return -1; 422 #else 423 // We inherited the socket from some kind of launcher. It's already bound and 424 // listening. Return a copy of the FD instead of the FD itself so we implement the 425 // normal "listen" contract and can succeed more than once. 426 unsigned int fd_u; 427 if (!ParseUint(&fd_u, spec) || fd_u > std::numeric_limits<int>::max()) { 428 *error = "invalid fd"; 429 return -1; 430 } 431 int fd = static_cast<int>(fd_u); 432 int flags = get_fd_flags(fd); 433 if (flags < 0) { 434 *error = android::base::StringPrintf("could not get flags of inherited fd %d: '%s'", fd, 435 strerror(errno)); 436 return -1; 437 } 438 if (flags & FD_CLOEXEC) { 439 *error = android::base::StringPrintf("fd %d was not inherited from parent", fd); 440 return -1; 441 } 442 443 int dummy_sock_type; 444 socklen_t dummy_sock_type_size = sizeof(dummy_sock_type); 445 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &dummy_sock_type, &dummy_sock_type_size)) { 446 *error = android::base::StringPrintf("fd %d does not refer to a socket", fd); 447 return -1; 448 } 449 450 int new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); 451 if (new_fd < 0) { 452 *error = android::base::StringPrintf("could not dup inherited fd %d: '%s'", fd, 453 strerror(errno)); 454 return -1; 455 } 456 return new_fd; 457 #endif 458 } 459 460 for (const auto& it : kLocalSocketTypes) { 461 std::string prefix = it.first + ":"; 462 if (spec.starts_with(prefix)) { 463 if (!it.second.available) { 464 *error = "attempted to listen on unavailable socket type: "; 465 *error += spec; 466 return -1; 467 } 468 469 return network_local_server(&spec[prefix.length()], it.second.socket_namespace, 470 SOCK_STREAM, error); 471 } 472 } 473 474 *error = "unknown socket specification:"; 475 *error += spec; 476 return -1; 477 } 478