Merge "Notify the framework when an adb key is authorized" into qt-dev
This commit is contained in:
commit
b9c555e2cf
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue