Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9c555e2 authored by Michael Groover's avatar Michael Groover Committed by Android (Google) Code Review
Browse files

Merge "Notify the framework when an adb key is authorized" into qt-dev

parents 377a2447 7eeda6ba
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -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:
+1 −0
Original line number Diff line number Diff line
@@ -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;

+4 −2
Original line number Diff line number Diff line
@@ -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);

+88 −41
Original line number Diff line number Diff line
@@ -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;
    {
        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());
    }
}

@@ -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) {
@@ -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);
    }
}

@@ -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();
@@ -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() {
+3 −0
Original line number Diff line number Diff line
@@ -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