Loading adb/adb.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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: Loading adb/adb.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading adb/adb_auth.h +4 −2 Original line number Diff line number Diff line Loading @@ -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); Loading adb/daemon/auth.cpp +88 −41 Original line number Diff line number Diff line Loading @@ -26,7 +26,9 @@ #include <resolv.h> #include <stdio.h> #include <string.h> #include <iomanip> #include <algorithm> #include <memory> #include <android-base/file.h> Loading @@ -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}; Loading @@ -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; Loading @@ -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'; Loading Loading @@ -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; Loading @@ -103,12 +131,13 @@ static void adb_disconnected(void* unused, atransport* t) { LOG(INFO) << "ADB disconnect"; adb_transport = nullptr; needs_retry = false; { std::lock_guard<std::mutex> lock(framework_mutex); 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"; 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()); } } Loading @@ -116,9 +145,12 @@ static void framework_disconnected() { LOG(INFO) << "Framework disconnect"; if (framework_fde) { fdevent_destroy(framework_fde); { std::lock_guard<std::mutex> lock(framework_mutex); framework_fd = -1; } } } static void adbd_auth_event(int fd, unsigned events, void*) { if (events & FDE_READ) { Loading @@ -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); } { std::lock_guard<std::mutex> lock(framework_mutex); 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 << "'"; if (!WriteFdExactly(framework_fd, msg, msg_len)) { PLOG(ERROR) << "Failed to write PK"; return; adbd_send_key_message_locked("PK", t->auth_key); } } Loading @@ -172,6 +191,8 @@ static void adbd_auth_listener(int fd, unsigned events, void* data) { return; } { std::lock_guard<std::mutex> lock(framework_mutex); if (framework_fd >= 0) { LOG(WARNING) << "adb received framework auth socket connection again"; framework_disconnected(); Loading @@ -185,6 +206,32 @@ static void adbd_auth_listener(int fd, unsigned events, void* data) { needs_retry = false; send_auth_request(adb_transport); } // 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); } } } } 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); } } } void adbd_cloexec_auth_socket() { Loading adb/transport.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading
adb/adb.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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: Loading
adb/adb.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
adb/adb_auth.h +4 −2 Original line number Diff line number Diff line Loading @@ -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); Loading
adb/daemon/auth.cpp +88 −41 Original line number Diff line number Diff line Loading @@ -26,7 +26,9 @@ #include <resolv.h> #include <stdio.h> #include <string.h> #include <iomanip> #include <algorithm> #include <memory> #include <android-base/file.h> Loading @@ -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}; Loading @@ -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; Loading @@ -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'; Loading Loading @@ -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; Loading @@ -103,12 +131,13 @@ static void adb_disconnected(void* unused, atransport* t) { LOG(INFO) << "ADB disconnect"; adb_transport = nullptr; needs_retry = false; { std::lock_guard<std::mutex> lock(framework_mutex); 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"; 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()); } } Loading @@ -116,9 +145,12 @@ static void framework_disconnected() { LOG(INFO) << "Framework disconnect"; if (framework_fde) { fdevent_destroy(framework_fde); { std::lock_guard<std::mutex> lock(framework_mutex); framework_fd = -1; } } } static void adbd_auth_event(int fd, unsigned events, void*) { if (events & FDE_READ) { Loading @@ -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); } { std::lock_guard<std::mutex> lock(framework_mutex); 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 << "'"; if (!WriteFdExactly(framework_fd, msg, msg_len)) { PLOG(ERROR) << "Failed to write PK"; return; adbd_send_key_message_locked("PK", t->auth_key); } } Loading @@ -172,6 +191,8 @@ static void adbd_auth_listener(int fd, unsigned events, void* data) { return; } { std::lock_guard<std::mutex> lock(framework_mutex); if (framework_fd >= 0) { LOG(WARNING) << "adb received framework auth socket connection again"; framework_disconnected(); Loading @@ -185,6 +206,32 @@ static void adbd_auth_listener(int fd, unsigned events, void* data) { needs_retry = false; send_auth_request(adb_transport); } // 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); } } } } 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); } } } void adbd_cloexec_auth_socket() { Loading
adb/transport.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 Loading