diff options
author | Michael Groover <mpgroover@google.com> | 2019-04-25 18:33:35 -0700 |
---|---|---|
committer | Michael Groover <mpgroover@google.com> | 2019-05-09 16:05:40 -0700 |
commit | 7eeda6ba0307e70d977b7d1303270b5f25425db3 (patch) | |
tree | ab28d0b85a2dd88da9a2d461e6175b09a5ec1277 | |
parent | 664193a62e55e016d8dd7cf3eb8453c772f0fff4 (diff) | |
download | system_core-7eeda6ba0307e70d977b7d1303270b5f25425db3.tar.gz system_core-7eeda6ba0307e70d977b7d1303270b5f25425db3.tar.bz2 system_core-7eeda6ba0307e70d977b7d1303270b5f25425db3.zip |
Notify the framework when an adb key is authorized
Bug: 124076524
Test: atest AdbDebuggingManagerTest
Change-Id: If73b81ca73ba4d64763cf49c1bbe42de81fa1cb6
-rw-r--r-- | adb/adb.cpp | 8 | ||||
-rw-r--r-- | adb/adb.h | 1 | ||||
-rw-r--r-- | adb/adb_auth.h | 6 | ||||
-rw-r--r-- | adb/daemon/auth.cpp | 129 | ||||
-rw-r--r-- | adb/transport.h | 3 | ||||
-rw-r--r-- | rootdir/init.usb.rc | 2 |
6 files changed, 103 insertions, 46 deletions
diff --git a/adb/adb.cpp b/adb/adb.cpp index 2dd22b38b..050ba49ad 100644 --- a/adb/adb.cpp +++ b/adb/adb.cpp @@ -337,9 +337,12 @@ void handle_packet(apacket *p, atransport *t) case ADB_AUTH_SIGNATURE: { // TODO: Switch to string_view. std::string signature(p->payload.begin(), p->payload.end()); - if (adbd_auth_verify(t->token, sizeof(t->token), signature)) { + std::string auth_key; + if (adbd_auth_verify(t->token, sizeof(t->token), signature, &auth_key)) { adbd_auth_verified(t); t->failed_auth_attempts = 0; + t->auth_key = auth_key; + adbd_notify_framework_connected_key(t); } else { if (t->failed_auth_attempts++ > 256) std::this_thread::sleep_for(1s); send_auth_request(t); @@ -348,7 +351,8 @@ void handle_packet(apacket *p, atransport *t) } case ADB_AUTH_RSAPUBLICKEY: - adbd_auth_confirm_key(p->payload.data(), p->msg.data_length, t); + t->auth_key = std::string(p->payload.data()); + adbd_auth_confirm_key(t); break; #endif default: @@ -33,6 +33,7 @@ constexpr size_t MAX_PAYLOAD_V1 = 4 * 1024; constexpr size_t MAX_PAYLOAD = 1024 * 1024; +constexpr size_t MAX_FRAMEWORK_PAYLOAD = 64 * 1024; constexpr size_t LINUX_MAX_SOCKET_SIZE = 4194304; diff --git a/adb/adb_auth.h b/adb/adb_auth.h index 2fc84789a..2be9a7684 100644 --- a/adb/adb_auth.h +++ b/adb/adb_auth.h @@ -50,8 +50,10 @@ void adbd_auth_init(void); void adbd_auth_verified(atransport *t); void adbd_cloexec_auth_socket(); -bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig); -void adbd_auth_confirm_key(const char* data, size_t len, atransport* t); +bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig, + std::string* auth_key); +void adbd_auth_confirm_key(atransport* t); +void adbd_notify_framework_connected_key(atransport* t); void send_auth_request(atransport *t); diff --git a/adb/daemon/auth.cpp b/adb/daemon/auth.cpp index a829bac0a..a18afa4ea 100644 --- a/adb/daemon/auth.cpp +++ b/adb/daemon/auth.cpp @@ -26,7 +26,9 @@ #include <resolv.h> #include <stdio.h> #include <string.h> +#include <iomanip> +#include <algorithm> #include <memory> #include <android-base/file.h> @@ -38,7 +40,9 @@ static fdevent* listener_fde = nullptr; static fdevent* framework_fde = nullptr; -static int framework_fd = -1; +static auto& framework_mutex = *new std::mutex(); +static int framework_fd GUARDED_BY(framework_mutex) = -1; +static auto& connected_keys GUARDED_BY(framework_mutex) = *new std::vector<std::string>; static void adb_disconnected(void* unused, atransport* t); static struct adisconnect adb_disconnect = {adb_disconnected, nullptr}; @@ -47,13 +51,13 @@ static bool needs_retry = false; bool auth_required = true; -bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig) { +bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig, + std::string* auth_key) { static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr }; for (const auto& path : key_paths) { if (access(path, R_OK) == 0) { LOG(INFO) << "Loading keys from " << path; - std::string content; if (!android::base::ReadFileToString(path, &content)) { PLOG(ERROR) << "Couldn't read " << path; @@ -61,6 +65,8 @@ bool adbd_auth_verify(const char* token, size_t token_size, const std::string& s } for (const auto& line : android::base::Split(content, "\n")) { + if (line.empty()) continue; + *auth_key = line; // TODO: do we really have to support both ' ' and '\t'? char* sep = strpbrk(const_cast<char*>(line.c_str()), " \t"); if (sep) *sep = '\0'; @@ -88,9 +94,31 @@ bool adbd_auth_verify(const char* token, size_t token_size, const std::string& s } } } + auth_key->clear(); return false; } +static bool adbd_send_key_message_locked(std::string_view msg_type, std::string_view key) + REQUIRES(framework_mutex) { + if (framework_fd < 0) { + LOG(ERROR) << "Client not connected to send msg_type " << msg_type; + return false; + } + std::string msg = std::string(msg_type) + std::string(key); + int msg_len = msg.length(); + if (msg_len >= static_cast<int>(MAX_FRAMEWORK_PAYLOAD)) { + LOG(ERROR) << "Key too long (" << msg_len << ")"; + return false; + } + + LOG(DEBUG) << "Sending '" << msg << "'"; + if (!WriteFdExactly(framework_fd, msg.c_str(), msg_len)) { + PLOG(ERROR) << "Failed to write " << msg_type; + return false; + } + return true; +} + static bool adbd_auth_generate_token(void* token, size_t token_size) { FILE* fp = fopen("/dev/urandom", "re"); if (!fp) return false; @@ -103,12 +131,13 @@ static void adb_disconnected(void* unused, atransport* t) { LOG(INFO) << "ADB disconnect"; adb_transport = nullptr; needs_retry = false; - if (framework_fd >= 0) { - const char msg[] = "DC"; - LOG(DEBUG) << "Sending '" << msg << "'"; - if (!WriteFdExactly(framework_fd, msg, sizeof(msg))) { - PLOG(ERROR) << "Failed to send disconnected message"; + { + std::lock_guard<std::mutex> lock(framework_mutex); + if (framework_fd >= 0) { + adbd_send_key_message_locked("DC", t->auth_key); } + connected_keys.erase(std::remove(connected_keys.begin(), connected_keys.end(), t->auth_key), + connected_keys.end()); } } @@ -116,7 +145,10 @@ static void framework_disconnected() { LOG(INFO) << "Framework disconnect"; if (framework_fde) { fdevent_destroy(framework_fde); - framework_fd = -1; + { + std::lock_guard<std::mutex> lock(framework_mutex); + framework_fd = -1; + } } } @@ -134,34 +166,21 @@ static void adbd_auth_event(int fd, unsigned events, void*) { } } -void adbd_auth_confirm_key(const char* key, size_t len, atransport* t) { +void adbd_auth_confirm_key(atransport* t) { if (!adb_transport) { adb_transport = t; t->AddDisconnect(&adb_disconnect); } - if (framework_fd < 0) { - LOG(ERROR) << "Client not connected"; - needs_retry = true; - return; - } - - if (key[len - 1] != '\0') { - LOG(ERROR) << "Key must be a null-terminated string"; - return; - } - - char msg[MAX_PAYLOAD_V1]; - int msg_len = snprintf(msg, sizeof(msg), "PK%s", key); - if (msg_len >= static_cast<int>(sizeof(msg))) { - LOG(ERROR) << "Key too long (" << msg_len << ")"; - return; - } - LOG(DEBUG) << "Sending '" << msg << "'"; + { + std::lock_guard<std::mutex> lock(framework_mutex); + if (framework_fd < 0) { + LOG(ERROR) << "Client not connected"; + needs_retry = true; + return; + } - if (!WriteFdExactly(framework_fd, msg, msg_len)) { - PLOG(ERROR) << "Failed to write PK"; - return; + adbd_send_key_message_locked("PK", t->auth_key); } } @@ -172,18 +191,46 @@ static void adbd_auth_listener(int fd, unsigned events, void* data) { return; } - if (framework_fd >= 0) { - LOG(WARNING) << "adb received framework auth socket connection again"; - framework_disconnected(); - } + { + std::lock_guard<std::mutex> lock(framework_mutex); + if (framework_fd >= 0) { + LOG(WARNING) << "adb received framework auth socket connection again"; + framework_disconnected(); + } + + framework_fd = s; + framework_fde = fdevent_create(framework_fd, adbd_auth_event, nullptr); + fdevent_add(framework_fde, FDE_READ); + + if (needs_retry) { + needs_retry = false; + send_auth_request(adb_transport); + } - framework_fd = s; - framework_fde = fdevent_create(framework_fd, adbd_auth_event, nullptr); - fdevent_add(framework_fde, FDE_READ); + // if a client connected before the framework was available notify the framework of the + // connected key now. + if (!connected_keys.empty()) { + for (const auto& key : connected_keys) { + adbd_send_key_message_locked("CK", key); + } + } + } +} - if (needs_retry) { - needs_retry = false; - send_auth_request(adb_transport); +void adbd_notify_framework_connected_key(atransport* t) { + if (!adb_transport) { + adb_transport = t; + t->AddDisconnect(&adb_disconnect); + } + { + std::lock_guard<std::mutex> lock(framework_mutex); + if (std::find(connected_keys.begin(), connected_keys.end(), t->auth_key) == + connected_keys.end()) { + connected_keys.push_back(t->auth_key); + } + if (framework_fd >= 0) { + adbd_send_key_message_locked("CK", t->auth_key); + } } } diff --git a/adb/transport.h b/adb/transport.h index f4490eded..3473ca2c4 100644 --- a/adb/transport.h +++ b/adb/transport.h @@ -274,6 +274,9 @@ class atransport { std::string device; std::string devpath; + // Used to provide the key to the framework. + std::string auth_key; + bool IsTcpDevice() const { return type == kTransportLocal; } #if ADB_HOST diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc index f0681d2c2..b6cba901e 100644 --- a/rootdir/init.usb.rc +++ b/rootdir/init.usb.rc @@ -14,7 +14,7 @@ on post-fs-data # adbd is controlled via property triggers in init.<platform>.usb.rc service adbd /system/bin/adbd --root_seclabel=u:r:su:s0 class core - socket adbd stream 660 system system + socket adbd seqpacket 660 system system disabled seclabel u:r:adbd:s0 |