From d6cf064484558336c3258302857c89ef50b01fec Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 4 Mar 2016 12:49:10 -0600 Subject: fix RotationLock shutdown issue that messed with getting clean test runs --- src/rotation-lock.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/rotation-lock.cpp b/src/rotation-lock.cpp index f19ac9f..88c7e1b 100644 --- a/src/rotation-lock.cpp +++ b/src/rotation-lock.cpp @@ -43,6 +43,7 @@ public: ~Impl() { + g_signal_handlers_disconnect_by_data(m_settings, this); g_clear_object(&m_action_group); g_clear_object(&m_settings); } -- cgit v1.2.3 From d911528cfb367fac34a5764ad6bce339a12f56d0 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 6 Mar 2016 23:00:42 -0600 Subject: add ADB server/client + tests --- src/CMakeLists.txt | 3 +- src/adbd-client.cpp | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/adbd-client.h | 73 +++++++++++++++ src/main.cpp | 11 +++ 4 files changed, 344 insertions(+), 1 deletion(-) create mode 100644 src/adbd-client.cpp create mode 100644 src/adbd-client.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 982aa49..414a750 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,7 @@ add_definitions (-DG_LOG_DOMAIN="${CMAKE_PROJECT_NAME}") # handwritten source code... set (SERVICE_LIB_HANDWRITTEN_SOURCES + adbd-client.cpp exporter.cpp rotation-lock.cpp) @@ -19,7 +20,7 @@ link_directories (${SERVICE_DEPS_LIBRARY_DIRS}) set (SERVICE_EXEC_HANDWRITTEN_SOURCES main.cpp) add_executable (${SERVICE_EXEC} ${SERVICE_EXEC_HANDWRITTEN_SOURCES}) -target_link_libraries (${SERVICE_EXEC} ${SERVICE_LIB} ${SERVICE_DEPS_LIBRARIES} ${GCOV_LIBS}) +target_link_libraries (${SERVICE_EXEC} ${SERVICE_LIB} ${SERVICE_DEPS_LIBRARIES} Threads::Threads ${GCOV_LIBS}) install (TARGETS ${SERVICE_EXEC} RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}) # add warnings/coverage info on handwritten files diff --git a/src/adbd-client.cpp b/src/adbd-client.cpp new file mode 100644 index 0000000..38f202f --- /dev/null +++ b/src/adbd-client.cpp @@ -0,0 +1,258 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include + +#include +#include + +#include +#include +#include +#include + +class GAdbdClient::Impl +{ +public: + + explicit Impl(const std::string& socket_path): + m_socket_path{socket_path}, + m_cancellable{g_cancellable_new()}, + m_worker_thread{&Impl::worker_func, this} + { + } + + ~Impl() + { + // tell the worker thread to stop whatever it's doing and exit. + g_cancellable_cancel(m_cancellable); + m_sleep_cv.notify_one(); + m_worker_thread.join(); + g_clear_object(&m_cancellable); + } + + core::Signal& on_pk_request() + { + return m_on_pk_request; + } + +private: + + // struct to carry request info from the worker thread to the GMainContext thread + struct PKIdleData + { + Impl* self = nullptr; + GCancellable* cancellable = nullptr; + const std::string public_key; + + PKIdleData(Impl* self_, GCancellable* cancellable_, std::string public_key_): + self(self_), + cancellable(G_CANCELLABLE(g_object_ref(cancellable_))), + public_key(public_key_) {} + + ~PKIdleData() {g_clear_object(&cancellable);} + + }; + + void pass_public_key_to_main_thread(const std::string& public_key) + { + g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, + on_public_key_request_static, + new PKIdleData{this, m_cancellable, public_key}, + [](gpointer id){delete static_cast(id);}); + } + + static gboolean on_public_key_request_static (gpointer gdata) // runs in main thread + { + /* NB: It's possible (though unlikely) that data.self was destroyed + while this callback was pending, so we must check is-cancelled FIRST */ + auto data = static_cast(gdata); + if (!g_cancellable_is_cancelled(data->cancellable)) + { + // notify our listeners of the request + auto self = data->self; + struct PKRequest req; + req.public_key = data->public_key; + req.respond = [self](PKResponse response){self->on_public_key_response(response);}; + self->m_on_pk_request(req); + } + + return G_SOURCE_REMOVE; + } + + void on_public_key_response(PKResponse response) + { + // set m_pkresponse and wake up the waiting worker thread + std::unique_lock lk(m_pkresponse_mutex); + m_pkresponse = response; + m_pkresponse_ready = true; + m_pkresponse_cv.notify_one(); + } + + /*** + **** + ***/ + + void worker_func() // runs in worker thread + { + const auto socket_path {m_socket_path}; + + while (!g_cancellable_is_cancelled(m_cancellable)) + { + g_debug("%s creating a client socket", G_STRLOC); + auto socket = create_client_socket(socket_path); + bool got_valid_req = false; + + g_debug("%s calling read_request", G_STRLOC); + std::string reqstr; + if (socket != nullptr) + reqstr = read_request(socket); + if (!reqstr.empty()) + g_debug("%s got request [%s]", G_STRLOC, reqstr.c_str()); + + if (reqstr.substr(0,2) == "PK") { + PKResponse response = PKResponse::DENY; + const auto public_key = reqstr.substr(2); + g_debug("%s got pk [%s]", G_STRLOC, public_key.c_str()); + if (!public_key.empty()) { + got_valid_req = true; + std::unique_lock lk(m_pkresponse_mutex); + m_pkresponse_ready = false; + pass_public_key_to_main_thread(public_key); + m_pkresponse_cv.wait(lk, [this](){ + return m_pkresponse_ready || g_cancellable_is_cancelled(m_cancellable); + }); + response = m_pkresponse; + g_debug("%s got response '%d'", G_STRLOC, int(response)); + } + if (!g_cancellable_is_cancelled(m_cancellable)) + send_pk_response(socket, response); + } else if (!reqstr.empty()) { + g_warning("Invalid ADB request: [%s]", reqstr.c_str()); + } + + g_clear_object(&socket); + + // If nothing interesting's happening, sleep a bit. + // (Interval copied from UsbDebuggingManager.java) + static constexpr auto sleep_interval {std::chrono::seconds(1)}; + if (!got_valid_req && !g_cancellable_is_cancelled(m_cancellable)) { + std::unique_lock lk(m_sleep_mutex); + m_sleep_cv.wait_for(lk, sleep_interval); + } + } + } + + // connect to a local domain socket + GSocket* create_client_socket(const std::string& socket_path) + { + GError* error {}; + auto socket = g_socket_new(G_SOCKET_FAMILY_UNIX, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + &error); + if (error != nullptr) { + g_warning("Error creating adbd client socket: %s", error->message); + g_clear_error(&error); + g_clear_object(&socket); + return nullptr; + } + + auto address = g_unix_socket_address_new(socket_path.c_str()); + const auto connected = g_socket_connect(socket, address, m_cancellable, nullptr); + g_clear_object(&address); + if (!connected) { + g_clear_object(&socket); + return nullptr; + } + + return socket; + } + + std::string read_request(GSocket* socket) + { + char buf[4096] = {}; + g_debug("%s calling g_socket_receive()", G_STRLOC); + const auto n_bytes = g_socket_receive (socket, buf, sizeof(buf), m_cancellable, nullptr); + std::string ret; + if (n_bytes > 0) + ret.append(buf, std::string::size_type(n_bytes)); + g_debug("%s g_socket_receive got %d bytes: [%s]", G_STRLOC, int(n_bytes), ret.c_str()); + return ret; + } + + void send_pk_response(GSocket* socket, PKResponse response) + { + std::string response_str; + switch(response) { + case PKResponse::ALLOW: response_str = "OK"; break; + case PKResponse::DENY: response_str = "NO"; break; + } + g_debug("%s sending reply: [%s]", G_STRLOC, response_str.c_str()); + + GError* error {}; + g_socket_send(socket, + response_str.c_str(), + response_str.size(), + m_cancellable, + &error); + if (error != nullptr) { + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning("GAdbdServer: Error accepting socket connection: %s", error->message); + g_clear_error(&error); + } + } + + const std::string m_socket_path; + GCancellable* m_cancellable = nullptr; + std::thread m_worker_thread; + core::Signal m_on_pk_request; + + std::mutex m_sleep_mutex; + std::condition_variable m_sleep_cv; + + std::mutex m_pkresponse_mutex; + std::condition_variable m_pkresponse_cv; + bool m_pkresponse_ready = false; + PKResponse m_pkresponse = PKResponse::DENY; +}; + +/*** +**** +***/ + +AdbdClient::~AdbdClient() +{ +} + +GAdbdClient::GAdbdClient(const std::string& socket_path): + impl{new Impl{socket_path}} +{ +} + +GAdbdClient::~GAdbdClient() +{ +} + +core::Signal& +GAdbdClient::on_pk_request() +{ + return impl->on_pk_request(); +} + diff --git a/src/adbd-client.h b/src/adbd-client.h new file mode 100644 index 0000000..aef7674 --- /dev/null +++ b/src/adbd-client.h @@ -0,0 +1,73 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#pragma once + +#include +#include +#include + +#include + +/** + * Receives public key requests from ADBD and sends a response back. + * + * AdbClient only provides a receive/respond mechanism. The decision + * of what response gets sent is delegated out to a listener via + * the on_pk_request signal. + * + * The decider should connect to on_pk_request, listen for PKRequests, + * and call the request's `respond' method with the desired response. + */ +class AdbdClient +{ +public: + virtual ~AdbdClient(); + + enum class PKResponse { DENY, ALLOW }; + + struct PKRequest { + std::string public_key; + std::function respond; + }; + + virtual core::Signal& on_pk_request() =0; + +protected: + AdbdClient() =default; +}; + +/** + * An AdbdClient designed to work with GLib's event loop. + * + * The on_pk_request() signal will be called in global GMainContext's thread; + * ie, just like a function passed to g_idle_add() or g_timeout_add(). + */ +class GAdbdClient: public AdbdClient +{ +public: + explicit GAdbdClient(const std::string& socket_path); + ~GAdbdClient(); + core::Signal& on_pk_request() override; + +private: + class Impl; + std::unique_ptr impl; +}; + diff --git a/src/main.cpp b/src/main.cpp index 86bdeb3..0c56bd6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,6 +17,7 @@ * Charles Kerr */ +#include #include #include @@ -54,6 +55,16 @@ main(int /*argc*/, char** /*argv*/) exporters.push_back(exporter); } + // We need the ADBD handler running, + // even though it doesn't have an indicator component yet + static constexpr char const * ADB_SOCKET_PATH {"/dev/socket/adb"}; + GAdbdClient adbd_client{ADB_SOCKET_PATH}; + adbd_client.on_pk_request().connect([](const AdbdClient::PKRequest& req){ + g_debug("%s got pk_request [%s]", G_STRLOC, req.public_key.c_str()); + // FIXME: actually decide what response to send back + req.respond(AdbdClient::PKResponse::ALLOW); + }); + g_main_loop_run(loop); // cleanup -- cgit v1.2.3 From 40f48471fe531ba5b9f1e1c4371f252fca4c2d52 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 8 Mar 2016 13:08:07 -0600 Subject: add out-of-line virtual method definitions to Indicator to silence clang++ warnings --- src/CMakeLists.txt | 4 +++- src/indicator.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/indicator.h | 13 ++++++------- 3 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 src/indicator.cpp (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 414a750..ff385d9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,7 +7,9 @@ add_definitions (-DG_LOG_DOMAIN="${CMAKE_PROJECT_NAME}") set (SERVICE_LIB_HANDWRITTEN_SOURCES adbd-client.cpp exporter.cpp - rotation-lock.cpp) + indicator.cpp + rotation-lock.cpp + usb-snap.cpp) add_library (${SERVICE_LIB} STATIC ${SERVICE_LIB_HANDWRITTEN_SOURCES}) diff --git a/src/indicator.cpp b/src/indicator.cpp new file mode 100644 index 0000000..77c4af7 --- /dev/null +++ b/src/indicator.cpp @@ -0,0 +1,37 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include + +Profile::Profile() +{ +} + +Profile::~Profile() +{ +} + +SimpleProfile::~SimpleProfile() +{ +} + +Indicator::~Indicator() +{ +} + diff --git a/src/indicator.h b/src/indicator.h index d0834fd..c55be79 100644 --- a/src/indicator.h +++ b/src/indicator.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Canonical Ltd. + * Copyright 2014-2016 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published @@ -17,8 +17,7 @@ * Charles Kerr */ -#ifndef INDICATOR_DISPLAY_INDICATOR_H -#define INDICATOR_DISPLAY_INDICATOR_H +#pragma once #include @@ -52,10 +51,10 @@ public: virtual std::string name() const =0; virtual const core::Property
& header() const =0; virtual std::shared_ptr menu_model() const =0; - virtual ~Profile() =default; + virtual ~Profile(); protected: - Profile() =default; + Profile(); }; @@ -63,6 +62,7 @@ class SimpleProfile: public Profile { public: SimpleProfile(const char* name, const std::shared_ptr& menu): m_name(name), m_menu(menu) {} + virtual ~SimpleProfile(); std::string name() const {return m_name;} core::Property
& header() {return m_header;} @@ -79,11 +79,10 @@ protected: class Indicator { public: - virtual ~Indicator() =default; + virtual ~Indicator(); virtual const char* name() const =0; virtual GSimpleActionGroup* action_group() const =0; virtual std::vector> profiles() const =0; }; -#endif -- cgit v1.2.3 From 68b671ce04b8b5d6b37025ad093c73a3e14d4d64 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 8 Mar 2016 22:04:56 -0600 Subject: add fingerprint snap decisions; test with notification dbusmock --- src/main.cpp | 9 +- src/usb-snap.cpp | 254 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/usb-snap.h | 39 +++++++++ 3 files changed, 299 insertions(+), 3 deletions(-) create mode 100644 src/usb-snap.cpp create mode 100644 src/usb-snap.h (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 0c56bd6..62eca62 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include // bindtextdomain() #include @@ -60,9 +61,11 @@ main(int /*argc*/, char** /*argv*/) static constexpr char const * ADB_SOCKET_PATH {"/dev/socket/adb"}; GAdbdClient adbd_client{ADB_SOCKET_PATH}; adbd_client.on_pk_request().connect([](const AdbdClient::PKRequest& req){ - g_debug("%s got pk_request [%s]", G_STRLOC, req.public_key.c_str()); - // FIXME: actually decide what response to send back - req.respond(AdbdClient::PKResponse::ALLOW); + auto snap = new UsbSnap(req.public_key); + snap->on_user_response().connect([req,snap](AdbdClient::PKResponse response, bool /*FIXME: remember_choice*/){ + req.respond(response); + g_idle_add([](gpointer gsnap){delete static_cast(gsnap); return G_SOURCE_REMOVE;}, snap); // delete-later + }); }); g_main_loop_run(loop); diff --git a/src/usb-snap.cpp b/src/usb-snap.cpp new file mode 100644 index 0000000..40f02a2 --- /dev/null +++ b/src/usb-snap.cpp @@ -0,0 +1,254 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include + +#include +#include + +/*** +**** +***/ + +class UsbSnap::Impl +{ +public: + + explicit Impl(const std::string& fingerprint): + m_fingerprint{fingerprint}, + m_cancellable{g_cancellable_new()} + { + g_bus_get (G_BUS_TYPE_SESSION, m_cancellable, on_bus_ready_static, this); + } + + ~Impl() + { + g_cancellable_cancel(m_cancellable); + g_clear_object(&m_cancellable); + + if (m_subscription_id != 0) + g_dbus_connection_signal_unsubscribe (m_bus, m_subscription_id); + + if (m_notification_id != 0) { + GError* error {}; + g_dbus_connection_call_sync(m_bus, + BUS_NAME, + OBJECT_PATH, + IFACE_NAME, + "CloseNotification", + g_variant_new("(u)", m_notification_id), + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + if (error != nullptr) { + g_warning("Error closing notification: %s", error->message); + g_clear_error(&error); + } + } + + g_clear_object(&m_bus); + } + + core::Signal& on_user_response() + { + return m_on_user_response; + } + +private: + + static void on_bus_ready_static(GObject* /*source*/, GAsyncResult* res, gpointer gself) + { + GError* error {}; + auto bus = g_bus_get_finish (res, &error); + if (error != nullptr) { + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning("UsbSnap: Error getting session bus: %s", error->message); + g_clear_error(&error); + } else { + static_cast(gself)->on_bus_ready(bus); + } + g_clear_object(&bus); + } + + void on_bus_ready(GDBusConnection* bus) + { + m_bus = G_DBUS_CONNECTION(g_object_ref(G_OBJECT(bus))); + + auto body = g_strdup_printf(_("The computer's RSA key fingerprint is: %s"), m_fingerprint.c_str()); + + GVariantBuilder actions_builder; + g_variant_builder_init(&actions_builder, G_VARIANT_TYPE_STRING_ARRAY); + g_variant_builder_add(&actions_builder, "s", ACTION_ALLOW); + g_variant_builder_add(&actions_builder, "s", _("Allow")); + g_variant_builder_add(&actions_builder, "s", ACTION_DENY); + g_variant_builder_add(&actions_builder, "s", _("Deny")); + + GVariantBuilder hints_builder; + g_variant_builder_init(&hints_builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&hints_builder, "{sv}", "x-canonical-non-shaped-icon", g_variant_new_string("true")); + g_variant_builder_add(&hints_builder, "{sv}", "x-canonical-snap-decisions", g_variant_new_string("true")); + g_variant_builder_add(&hints_builder, "{sv}", "x-canonical-private-affirmative-tint", g_variant_new_string("true")); + + auto args = g_variant_new("(susssasa{sv}i)", + "", + uint32_t(0), + "computer-symbolic", + _("Allow USB Debugging?"), + body, + &actions_builder, + &hints_builder, + -1); + g_dbus_connection_call(m_bus, + BUS_NAME, + OBJECT_PATH, + IFACE_NAME, + "Notify", + args, + G_VARIANT_TYPE("(u)"), + G_DBUS_CALL_FLAGS_NONE, + -1, // timeout + m_cancellable, + on_notify_reply_static, + this); + + g_clear_pointer(&body, g_free); + } + + static void on_notify_reply_static(GObject* obus, GAsyncResult* res, gpointer gself) + { + GError* error {}; + auto reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION(obus), res, &error); + if (error != nullptr) { + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning("UsbSnap: Error calling Notify: %s", error->message); + g_clear_error(&error); + } else { + uint32_t id {}; + g_variant_get(reply, "(u)", &id); + static_cast(gself)->on_notify_reply(id); + } + g_clear_pointer(&reply, g_variant_unref); + } + + void on_notify_reply(uint32_t id) + { + m_notification_id = id; + + m_subscription_id = g_dbus_connection_signal_subscribe(m_bus, + BUS_NAME, + IFACE_NAME, + nullptr, + OBJECT_PATH, + nullptr, + G_DBUS_SIGNAL_FLAGS_NONE, + on_notification_signal_static, + this, + nullptr); + } + + static void on_notification_signal_static(GDBusConnection* /*connection*/, + const gchar* /*sender_name*/, + const gchar* object_path, + const gchar* interface_name, + const gchar* signal_name, + GVariant* parameters, + gpointer gself) + { + g_return_if_fail(!g_strcmp0(object_path, OBJECT_PATH)); + g_return_if_fail(!g_strcmp0(interface_name, IFACE_NAME)); + + auto self = static_cast(gself); + + if (!g_strcmp0(signal_name, "ActionInvoked")) + { + uint32_t id {}; + const char* action_name {}; + g_variant_get(parameters, "(u&s)", &id, &action_name); + if (id == self->m_notification_id) + self->on_action_invoked(action_name); + } + else if (!g_strcmp0(signal_name, "NotificationClosed")) + { + uint32_t id {}; + uint32_t close_reason {}; + g_variant_get(parameters, "(uu)", &id, &close_reason); + if (id == self->m_notification_id) + self->on_notification_closed(close_reason); + } + } + + void on_action_invoked(const char* action_name) + { + const auto response = !g_strcmp0(action_name, ACTION_ALLOW) + ? AdbdClient::PKResponse::ALLOW + : AdbdClient::PKResponse::DENY; + + // FIXME: the current default is to cover the most common use case. + // We need to get the notification ui's checkbox working ASAP so + // that the user can provide this flag + const bool remember_this_choice = response == AdbdClient::PKResponse::ALLOW; + + m_on_user_response(response, remember_this_choice); + } + + void on_notification_closed(uint32_t close_reason) + { + if (close_reason == CloseReason::EXPIRED) + m_on_user_response(AdbdClient::PKResponse::DENY, false); + + m_notification_id = 0; + } + + static constexpr char const * ACTION_ALLOW{"allow"}; + static constexpr char const * ACTION_DENY{"deny"}; + + static constexpr char const * BUS_NAME {"org.freedesktop.Notifications" }; + static constexpr char const * IFACE_NAME {"org.freedesktop.Notifications" }; + static constexpr char const * OBJECT_PATH {"/org/freedesktop/Notifications" }; + enum CloseReason { EXPIRED=1, DISMISSED=2, API=3, UNDEFINED=4 }; + + const std::string m_fingerprint; + core::Signal m_on_user_response; + GCancellable* m_cancellable {}; + GDBusConnection* m_bus {}; + uint32_t m_notification_id {}; + unsigned int m_subscription_id {}; +}; + +/*** +**** +***/ + +UsbSnap::UsbSnap(const std::string& public_key): + impl{new Impl{public_key}} +{ +} + +UsbSnap::~UsbSnap() +{ +} + +core::Signal& +UsbSnap::on_user_response() +{ + return impl->on_user_response(); +} + diff --git a/src/usb-snap.h b/src/usb-snap.h new file mode 100644 index 0000000..6ad3a4c --- /dev/null +++ b/src/usb-snap.h @@ -0,0 +1,39 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#pragma once + +#include // AdbdClient::PKResponse + +#include + +#include +#include + +class UsbSnap +{ +public: + explicit UsbSnap(const std::string& public_key); + ~UsbSnap(); + core::Signal& on_user_response(); + +protected: + class Impl; + std::unique_ptr impl; +}; -- cgit v1.2.3 From 13a0b901492901638a7abc90bb2935a9c0387f75 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 9 Mar 2016 17:19:23 -0600 Subject: add human-readable fingerprint extraction from the adb public keys --- src/adbd-client.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/adbd-client.h | 1 + src/main.cpp | 2 +- src/usb-snap.cpp | 4 ++-- 4 files changed, 43 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/adbd-client.cpp b/src/adbd-client.cpp index 38f202f..edd403c 100644 --- a/src/adbd-client.cpp +++ b/src/adbd-client.cpp @@ -22,6 +22,9 @@ #include #include +#include +#include +#include #include #include #include @@ -89,6 +92,7 @@ private: auto self = data->self; struct PKRequest req; req.public_key = data->public_key; + req.fingerprint = get_fingerprint(req.public_key); req.respond = [self](PKResponse response){self->on_public_key_response(response);}; self->m_on_pk_request(req); } @@ -219,6 +223,37 @@ private: } } + static std::string get_fingerprint(const std::string& public_key) + { + // The first token is base64-encoded data, so cut on the first whitespace + const std::string base64 ( + public_key.begin(), + std::find_if( + public_key.begin(), public_key.end(), + [](const std::string::value_type& ch){return std::isspace(ch);} + ) + ); + + gsize digest_len {}; + auto digest = g_base64_decode(base64.c_str(), &digest_len); + + auto checksum = g_compute_checksum_for_data(G_CHECKSUM_MD5, digest, digest_len); + const gsize checksum_len = checksum ? strlen(checksum) : 0; + + // insert ':' between character pairs; eg "ff27b5f3" --> "ff:27:b5:f3" + std::string fingerprint; + for (gsize i=0; i respond; }; diff --git a/src/main.cpp b/src/main.cpp index 62eca62..151b642 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -61,7 +61,7 @@ main(int /*argc*/, char** /*argv*/) static constexpr char const * ADB_SOCKET_PATH {"/dev/socket/adb"}; GAdbdClient adbd_client{ADB_SOCKET_PATH}; adbd_client.on_pk_request().connect([](const AdbdClient::PKRequest& req){ - auto snap = new UsbSnap(req.public_key); + auto snap = new UsbSnap(req.fingerprint); snap->on_user_response().connect([req,snap](AdbdClient::PKResponse response, bool /*FIXME: remember_choice*/){ req.respond(response); g_idle_add([](gpointer gsnap){delete static_cast(gsnap); return G_SOURCE_REMOVE;}, snap); // delete-later diff --git a/src/usb-snap.cpp b/src/usb-snap.cpp index 40f02a2..87f4673 100644 --- a/src/usb-snap.cpp +++ b/src/usb-snap.cpp @@ -217,8 +217,8 @@ private: m_notification_id = 0; } - static constexpr char const * ACTION_ALLOW{"allow"}; - static constexpr char const * ACTION_DENY{"deny"}; + static constexpr char const * ACTION_ALLOW {"allow"}; + static constexpr char const * ACTION_DENY {"deny"}; static constexpr char const * BUS_NAME {"org.freedesktop.Notifications" }; static constexpr char const * IFACE_NAME {"org.freedesktop.Notifications" }; -- cgit v1.2.3 From f8a5d99b5ac03b5b759f67b33ed2c989fc0d0ceb Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 10 Mar 2016 12:13:20 -0600 Subject: cmake and test directory cleanup --- src/CMakeLists.txt | 61 +++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ff385d9..6cfda91 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,32 +1,33 @@ -set (SERVICE_LIB "indicatordisplayservice") -set (SERVICE_EXEC "indicator-display-service") -add_definitions (-DG_LOG_DOMAIN="${CMAKE_PROJECT_NAME}") - -# handwritten source code... -set (SERVICE_LIB_HANDWRITTEN_SOURCES - adbd-client.cpp - exporter.cpp - indicator.cpp - rotation-lock.cpp - usb-snap.cpp) - -add_library (${SERVICE_LIB} STATIC - ${SERVICE_LIB_HANDWRITTEN_SOURCES}) - -# add the bin dir to the include path so that -# the compiler can find the generated header files -include_directories (${CMAKE_CURRENT_BINARY_DIR}) - -link_directories (${SERVICE_DEPS_LIBRARY_DIRS}) - -set (SERVICE_EXEC_HANDWRITTEN_SOURCES main.cpp) -add_executable (${SERVICE_EXEC} ${SERVICE_EXEC_HANDWRITTEN_SOURCES}) -target_link_libraries (${SERVICE_EXEC} ${SERVICE_LIB} ${SERVICE_DEPS_LIBRARIES} Threads::Threads ${GCOV_LIBS}) -install (TARGETS ${SERVICE_EXEC} RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}) - -# add warnings/coverage info on handwritten files -# but not the generated ones... -set_property (SOURCE ${SERVICE_LIB_HANDWRITTEN_SOURCES} ${SERVICE_EXEC_HANDWRITTEN_SOURCES} - APPEND_STRING PROPERTY COMPILE_FLAGS " -std=c++11 -g ${CXX_WARNING_ARGS} ${GCOV_FLAGS}") +add_definitions(-DG_LOG_DOMAIN="${CMAKE_PROJECT_NAME}") + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARNING_ARGS} ${GCOV_FLAGS}") + +add_library( + ${SERVICE_LIB} + STATIC + adbd-client.cpp + exporter.cpp + indicator.cpp + rotation-lock.cpp + usb-snap.cpp +) + +add_executable( + ${SERVICE_EXEC} + main.cpp +) + +target_link_libraries(${SERVICE_EXEC} + ${SERVICE_LIB} + ${SERVICE_DEPS_LIBRARIES} + Threads::Threads + ${GCOV_LIBS} +) + +install( + TARGETS + ${SERVICE_EXEC} + RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR} +) -- cgit v1.2.3 From d8ef8e68805ab7f53258427c79ee5aaafec916ba Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 10 Mar 2016 17:09:59 -0600 Subject: add UsbManager --- src/CMakeLists.txt | 1 + src/main.cpp | 14 ++----- src/usb-manager.cpp | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/usb-manager.h | 34 ++++++++++++++++ 4 files changed, 148 insertions(+), 10 deletions(-) create mode 100644 src/usb-manager.cpp create mode 100644 src/usb-manager.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6cfda91..d0ab901 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ add_library( exporter.cpp indicator.cpp rotation-lock.cpp + usb-manager.cpp usb-snap.cpp ) diff --git a/src/main.cpp b/src/main.cpp index 151b642..eb1bb2c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,10 +17,9 @@ * Charles Kerr */ -#include #include #include -#include +#include #include // bindtextdomain() #include @@ -59,15 +58,10 @@ main(int /*argc*/, char** /*argv*/) // We need the ADBD handler running, // even though it doesn't have an indicator component yet static constexpr char const * ADB_SOCKET_PATH {"/dev/socket/adb"}; - GAdbdClient adbd_client{ADB_SOCKET_PATH}; - adbd_client.on_pk_request().connect([](const AdbdClient::PKRequest& req){ - auto snap = new UsbSnap(req.fingerprint); - snap->on_user_response().connect([req,snap](AdbdClient::PKResponse response, bool /*FIXME: remember_choice*/){ - req.respond(response); - g_idle_add([](gpointer gsnap){delete static_cast(gsnap); return G_SOURCE_REMOVE;}, snap); // delete-later - }); - }); + static constexpr char const * PUBLIC_KEYS_FILENAME {"/data/misc/adb/adb_keys"}; + UsbManager usb_manager {ADB_SOCKET_PATH, PUBLIC_KEYS_FILENAME}; + // let's go! g_main_loop_run(loop); // cleanup diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp new file mode 100644 index 0000000..6b40cea --- /dev/null +++ b/src/usb-manager.cpp @@ -0,0 +1,109 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include + +class UsbManager::Impl +{ +public: + + explicit Impl( + const std::string& socket_path, + const std::string& public_keys_filename + ): + m_adbd_client{std::make_shared(socket_path)}, + m_public_keys_filename{public_keys_filename} + { + m_adbd_client->on_pk_request().connect([this](const AdbdClient::PKRequest& req){ + auto snap = new UsbSnap(req.fingerprint); + snap->on_user_response().connect([this,req,snap](AdbdClient::PKResponse response, bool /*FIXME: remember_choice*/){ + req.respond(response); + if (response == AdbdClient::PKResponse::ALLOW) + write_public_key(req.public_key); + + // delete later + g_idle_add([](gpointer gsnap){delete static_cast(gsnap); return G_SOURCE_REMOVE;}, snap); + }); + }); + } + + ~Impl() + { + } + +private: + + void write_public_key(const std::string& public_key) + { + // confirm the directory exists + auto dirname = g_path_get_dirname(m_public_keys_filename.c_str()); + const auto dir_exists = g_file_test(dirname, G_FILE_TEST_IS_DIR); + if (!dir_exists) + g_warning("ADB data directory '%s' does not exist", dirname); + g_clear_pointer(&dirname, g_free); + if (!dir_exists) + return; + + // open the file in append mode, with user rw and group r permissions + const auto fd = open( + m_public_keys_filename.c_str(), + O_APPEND|O_CREAT|O_WRONLY, + S_IRUSR|S_IWUSR|S_IRGRP + ); + if (fd == -1) { + g_warning("Error opening ADB datafile: %s", g_strerror(errno)); + return; + } + + // write the new public key on its own line + std::string buf {public_key + '\n'}; + if (write(fd, buf.c_str(), buf.size()) == -1) + g_warning("Error writing ADB datafile: %d %s", errno, g_strerror(errno)); + close(fd); + } + + std::shared_ptr m_adbd_client; + const std::string m_public_keys_filename; +}; + +/*** +**** +***/ + +UsbManager::UsbManager( + const std::string& socket_path, + const std::string& public_keys_filename +): + impl{new Impl{socket_path, public_keys_filename}} +{ +} + +UsbManager::~UsbManager() +{ +} + diff --git a/src/usb-manager.h b/src/usb-manager.h new file mode 100644 index 0000000..28a27f3 --- /dev/null +++ b/src/usb-manager.h @@ -0,0 +1,34 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#pragma once + +#include +#include + +class UsbManager +{ +public: + UsbManager(const std::string& socket_path, const std::string& public_key_filename); + ~UsbManager(); + +protected: + class Impl; + std::unique_ptr impl; +}; -- cgit v1.2.3 From 0734731e7296f84ab30ac403886635b7cb89da49 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 11 Mar 2016 14:06:34 -0600 Subject: clean up compile_options and warnings. Add DBUS debug log messages to ctest environment variables. --- src/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d0ab901..02d973e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,10 @@ add_definitions(-DG_LOG_DOMAIN="${CMAKE_PROJECT_NAME}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARNING_ARGS} ${GCOV_FLAGS}") +add_compile_options( + ${CXX_WARNING_ARGS} + ${GCOV_FLAGS} +) add_library( ${SERVICE_LIB} -- cgit v1.2.3 From 6174e922ef0e819d0b8f8f16ad863c83f8fa6421 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 15 Mar 2016 13:49:19 -0500 Subject: tweak a couple of 'auto' declarations that g++ 5.3.1 understands but 4.9.2 on vivid doesn't --- src/adbd-client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/adbd-client.cpp b/src/adbd-client.cpp index edd403c..30929a7 100644 --- a/src/adbd-client.cpp +++ b/src/adbd-client.cpp @@ -115,7 +115,7 @@ private: void worker_func() // runs in worker thread { - const auto socket_path {m_socket_path}; + const std::string socket_path {m_socket_path}; while (!g_cancellable_is_cancelled(m_cancellable)) { @@ -155,7 +155,7 @@ private: // If nothing interesting's happening, sleep a bit. // (Interval copied from UsbDebuggingManager.java) - static constexpr auto sleep_interval {std::chrono::seconds(1)}; + static constexpr std::chrono::seconds sleep_interval {std::chrono::seconds(1)}; if (!got_valid_req && !g_cancellable_is_cancelled(m_cancellable)) { std::unique_lock lk(m_sleep_mutex); m_sleep_cv.wait_for(lk, sleep_interval); -- cgit v1.2.3 From b3f65b988fe0a646acaee6d3e71a9b1682e0b014 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 15 Mar 2016 14:17:21 -0500 Subject: cmake's Thread::Thread import doesn't exist in vivid's version of cmake (3.0.2), so fall back gracefully to -pthread there --- src/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 02d973e..4fe7b1a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,10 +22,16 @@ add_executable( main.cpp ) +if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} LESS 3.2) + set(SERVICE_THREAD_LIBS -pthread) +else() + set(SERVICE_THREAD_LIBS Threads::Threads) +endif() + target_link_libraries(${SERVICE_EXEC} ${SERVICE_LIB} ${SERVICE_DEPS_LIBRARIES} - Threads::Threads + ${SERVICE_THREAD_LIBS} ${GCOV_LIBS} ) -- cgit v1.2.3 From df322a475939f3d30e4ff20213df1c01f7ff26d5 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 15 Mar 2016 15:41:55 -0500 Subject: add some debug stubs --- src/adbd-client.cpp | 6 ++++-- src/main.cpp | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/adbd-client.cpp b/src/adbd-client.cpp index 30929a7..4f7d28f 100644 --- a/src/adbd-client.cpp +++ b/src/adbd-client.cpp @@ -119,7 +119,7 @@ private: while (!g_cancellable_is_cancelled(m_cancellable)) { - g_debug("%s creating a client socket", G_STRLOC); + g_debug("%s creating a client socket to '%s'", G_STRLOC, socket_path.c_str()); auto socket = create_client_socket(socket_path); bool got_valid_req = false; @@ -179,9 +179,11 @@ private: } auto address = g_unix_socket_address_new(socket_path.c_str()); - const auto connected = g_socket_connect(socket, address, m_cancellable, nullptr); + const auto connected = g_socket_connect(socket, address, m_cancellable, &error); g_clear_object(&address); if (!connected) { + g_debug("unable to connect to '%s': %s", socket_path.c_str(), error->message); + g_clear_error(&error); g_clear_object(&socket); return nullptr; } diff --git a/src/main.cpp b/src/main.cpp index eb1bb2c..2e84afa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,6 +29,9 @@ int main(int /*argc*/, char** /*argv*/) { +#warning temp +g_assert(g_setenv("G_MESSAGES_DEBUG", "all", true)); + // Work around a deadlock in glib's type initialization. // It can be removed when https://bugzilla.gnome.org/show_bug.cgi?id=674885 is fixed. g_type_ensure(G_TYPE_DBUS_CONNECTION); -- cgit v1.2.3 From ee369babc9185bac7c7910a68a1e58bab7efa64c Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 15 Mar 2016 16:12:05 -0500 Subject: oops, last commit's diagnosis was incorrect. The timing test issue came from async dbus handling interfering with fast setup/teardown of automated tests. Revert the last change and fix by setting up the dbus signal subscription immediately upon getting the dbus connection. --- src/usb-snap.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/usb-snap.cpp b/src/usb-snap.cpp index 87f4673..c42f9f0 100644 --- a/src/usb-snap.cpp +++ b/src/usb-snap.cpp @@ -92,6 +92,17 @@ private: { m_bus = G_DBUS_CONNECTION(g_object_ref(G_OBJECT(bus))); + m_subscription_id = g_dbus_connection_signal_subscribe(m_bus, + BUS_NAME, + IFACE_NAME, + nullptr, + OBJECT_PATH, + nullptr, + G_DBUS_SIGNAL_FLAGS_NONE, + on_notification_signal_static, + this, + nullptr); + auto body = g_strdup_printf(_("The computer's RSA key fingerprint is: %s"), m_fingerprint.c_str()); GVariantBuilder actions_builder; @@ -151,17 +162,6 @@ private: void on_notify_reply(uint32_t id) { m_notification_id = id; - - m_subscription_id = g_dbus_connection_signal_subscribe(m_bus, - BUS_NAME, - IFACE_NAME, - nullptr, - OBJECT_PATH, - nullptr, - G_DBUS_SIGNAL_FLAGS_NONE, - on_notification_signal_static, - this, - nullptr); } static void on_notification_signal_static(GDBusConnection* /*connection*/, -- cgit v1.2.3 From 8ddb1713fa0816ea1c98ae039fea181d629acc7d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 15 Mar 2016 17:09:47 -0500 Subject: listen on /dev/socket/adbd, not /dev/socket/adb --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 2e84afa..f195bda 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,7 +60,7 @@ g_assert(g_setenv("G_MESSAGES_DEBUG", "all", true)); // We need the ADBD handler running, // even though it doesn't have an indicator component yet - static constexpr char const * ADB_SOCKET_PATH {"/dev/socket/adb"}; + static constexpr char const * ADB_SOCKET_PATH {"/dev/socket/adbd"}; static constexpr char const * PUBLIC_KEYS_FILENAME {"/data/misc/adb/adb_keys"}; UsbManager usb_manager {ADB_SOCKET_PATH, PUBLIC_KEYS_FILENAME}; -- cgit v1.2.3 From 2b21545845221a841c11db2c3b4782f6893e72d7 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 15 Mar 2016 19:25:33 -0500 Subject: use cmake's find_package(Threads) output everywhere instead of just in src/ --- src/CMakeLists.txt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4fe7b1a..63c236d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,16 +22,10 @@ add_executable( main.cpp ) -if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} LESS 3.2) - set(SERVICE_THREAD_LIBS -pthread) -else() - set(SERVICE_THREAD_LIBS Threads::Threads) -endif() - target_link_libraries(${SERVICE_EXEC} ${SERVICE_LIB} ${SERVICE_DEPS_LIBRARIES} - ${SERVICE_THREAD_LIBS} + ${THREAD_LINK_LIBRARIES} ${GCOV_LIBS} ) -- cgit v1.2.3 From 9482a77503a72cbda7ca824c2ff9bd66b04098fb Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 16 Mar 2016 08:29:07 -0500 Subject: use cmake-extras' EnableCoverageReport instead of home-rolled rules --- src/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 63c236d..d3a021b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,6 @@ add_definitions(-DG_LOG_DOMAIN="${CMAKE_PROJECT_NAME}") add_compile_options( ${CXX_WARNING_ARGS} - ${GCOV_FLAGS} ) add_library( @@ -26,7 +25,6 @@ target_link_libraries(${SERVICE_EXEC} ${SERVICE_LIB} ${SERVICE_DEPS_LIBRARIES} ${THREAD_LINK_LIBRARIES} - ${GCOV_LIBS} ) install( -- cgit v1.2.3 From 078459b6c837264eb2d6b45a84a1641a3aeab2cc Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 16 Mar 2016 09:04:26 -0500 Subject: in usb-manager.cpp, remove the remember_choice workaround since is already working around it --- src/usb-manager.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 6b40cea..f089a22 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -41,12 +41,11 @@ public: { m_adbd_client->on_pk_request().connect([this](const AdbdClient::PKRequest& req){ auto snap = new UsbSnap(req.fingerprint); - snap->on_user_response().connect([this,req,snap](AdbdClient::PKResponse response, bool /*FIXME: remember_choice*/){ + snap->on_user_response().connect([this,req,snap](AdbdClient::PKResponse response, bool remember_choice){ req.respond(response); - if (response == AdbdClient::PKResponse::ALLOW) + if (remember_choice) write_public_key(req.public_key); - - // delete later + // delete_later g_idle_add([](gpointer gsnap){delete static_cast(gsnap); return G_SOURCE_REMOVE;}, snap); }); }); -- cgit v1.2.3 From 3ef931c4bc8d87497dbe9f6ceda9ce4ca3bb116f Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 16 Mar 2016 09:04:44 -0500 Subject: tweak class description comments --- src/usb-manager.h | 3 +++ src/usb-snap.h | 3 +++ 2 files changed, 6 insertions(+) (limited to 'src') diff --git a/src/usb-manager.h b/src/usb-manager.h index 28a27f3..ec405c0 100644 --- a/src/usb-manager.h +++ b/src/usb-manager.h @@ -22,6 +22,9 @@ #include #include +/** + * Manager class that connects the AdbdClient, UsbSnap, and manages the public key file + */ class UsbManager { public: diff --git a/src/usb-snap.h b/src/usb-snap.h index 6ad3a4c..94de394 100644 --- a/src/usb-snap.h +++ b/src/usb-snap.h @@ -26,6 +26,9 @@ #include #include +/** + * A snap decision prompt for whether or not to allow an ADB connection + */ class UsbSnap { public: -- cgit v1.2.3 From c63d90da0f1d9cbd1eee5dd66a9828c51cc8dcc9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 17 Mar 2016 09:59:32 -0500 Subject: de-dupe use of dbus names --- src/dbus-names.h | 42 ++++++++++++++++++++++++++++++++++++++++++ src/usb-snap.cpp | 34 +++++++++++++++------------------- 2 files changed, 57 insertions(+), 19 deletions(-) create mode 100644 src/dbus-names.h (limited to 'src') diff --git a/src/dbus-names.h b/src/dbus-names.h new file mode 100644 index 0000000..753b8c8 --- /dev/null +++ b/src/dbus-names.h @@ -0,0 +1,42 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#pragma once + +namespace DBusNames +{ + namespace Notify + { + static constexpr char const * NAME = "org.freedesktop.Notifications"; + static constexpr char const * PATH = "/org/freedesktop/Notifications"; + static constexpr char const * INTERFACE = "org.freedesktop.Notifications"; + + namespace ActionInvoked + { + static constexpr char const * NAME = "ActionInvoked"; + } + + namespace NotificationClosed + { + static constexpr char const * NAME = "NotificationClosed"; + enum Reason { EXPIRED=1, DISMISSED=2, API=3, UNDEFINED=4 }; + } + } +} + diff --git a/src/usb-snap.cpp b/src/usb-snap.cpp index c42f9f0..41c78c6 100644 --- a/src/usb-snap.cpp +++ b/src/usb-snap.cpp @@ -17,6 +17,7 @@ * Charles Kerr */ +#include #include #include @@ -48,9 +49,9 @@ public: if (m_notification_id != 0) { GError* error {}; g_dbus_connection_call_sync(m_bus, - BUS_NAME, - OBJECT_PATH, - IFACE_NAME, + DBusNames::Notify::NAME, + DBusNames::Notify::PATH, + DBusNames::Notify::INTERFACE, "CloseNotification", g_variant_new("(u)", m_notification_id), nullptr, @@ -93,10 +94,10 @@ private: m_bus = G_DBUS_CONNECTION(g_object_ref(G_OBJECT(bus))); m_subscription_id = g_dbus_connection_signal_subscribe(m_bus, - BUS_NAME, - IFACE_NAME, + DBusNames::Notify::NAME, + DBusNames::Notify::INTERFACE, nullptr, - OBJECT_PATH, + DBusNames::Notify::PATH, nullptr, G_DBUS_SIGNAL_FLAGS_NONE, on_notification_signal_static, @@ -128,9 +129,9 @@ private: &hints_builder, -1); g_dbus_connection_call(m_bus, - BUS_NAME, - OBJECT_PATH, - IFACE_NAME, + DBusNames::Notify::NAME, + DBusNames::Notify::PATH, + DBusNames::Notify::INTERFACE, "Notify", args, G_VARIANT_TYPE("(u)"), @@ -172,12 +173,12 @@ private: GVariant* parameters, gpointer gself) { - g_return_if_fail(!g_strcmp0(object_path, OBJECT_PATH)); - g_return_if_fail(!g_strcmp0(interface_name, IFACE_NAME)); + g_return_if_fail(!g_strcmp0(object_path, DBusNames::Notify::PATH)); + g_return_if_fail(!g_strcmp0(interface_name, DBusNames::Notify::INTERFACE)); auto self = static_cast(gself); - if (!g_strcmp0(signal_name, "ActionInvoked")) + if (!g_strcmp0(signal_name, DBusNames::Notify::ActionInvoked::NAME)) { uint32_t id {}; const char* action_name {}; @@ -185,7 +186,7 @@ private: if (id == self->m_notification_id) self->on_action_invoked(action_name); } - else if (!g_strcmp0(signal_name, "NotificationClosed")) + else if (!g_strcmp0(signal_name, DBusNames::Notify::NotificationClosed::NAME)) { uint32_t id {}; uint32_t close_reason {}; @@ -211,7 +212,7 @@ private: void on_notification_closed(uint32_t close_reason) { - if (close_reason == CloseReason::EXPIRED) + if (close_reason == DBusNames::Notify::NotificationClosed::Reason::EXPIRED) m_on_user_response(AdbdClient::PKResponse::DENY, false); m_notification_id = 0; @@ -220,11 +221,6 @@ private: static constexpr char const * ACTION_ALLOW {"allow"}; static constexpr char const * ACTION_DENY {"deny"}; - static constexpr char const * BUS_NAME {"org.freedesktop.Notifications" }; - static constexpr char const * IFACE_NAME {"org.freedesktop.Notifications" }; - static constexpr char const * OBJECT_PATH {"/org/freedesktop/Notifications" }; - enum CloseReason { EXPIRED=1, DISMISSED=2, API=3, UNDEFINED=4 }; - const std::string m_fingerprint; core::Signal m_on_user_response; GCancellable* m_cancellable {}; -- cgit v1.2.3 From ff5be6a08a602e8a4454cbfcd8eeb38e28db3e1f Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 17 Mar 2016 13:29:09 -0500 Subject: fix warning message --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index f195bda..2e428f9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,7 +29,7 @@ int main(int /*argc*/, char** /*argv*/) { -#warning temp +#warning NB the next line turns on verbose debug logging and is used for developement. Remove it before landing. g_assert(g_setenv("G_MESSAGES_DEBUG", "all", true)); // Work around a deadlock in glib's type initialization. -- cgit v1.2.3 From ccecdd46da33ff51b2d45528439de09fe87a393c Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 18 Mar 2016 10:42:41 -0500 Subject: add some extra debug statements to usb-manager.cpp to track user response and the act of writing the pk out to disk --- src/usb-manager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index f089a22..335db00 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -42,8 +42,9 @@ public: m_adbd_client->on_pk_request().connect([this](const AdbdClient::PKRequest& req){ auto snap = new UsbSnap(req.fingerprint); snap->on_user_response().connect([this,req,snap](AdbdClient::PKResponse response, bool remember_choice){ + g_debug("user responded! response %d, remember %d", int(response), int(remember_choice)); req.respond(response); - if (remember_choice) + if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) write_public_key(req.public_key); // delete_later g_idle_add([](gpointer gsnap){delete static_cast(gsnap); return G_SOURCE_REMOVE;}, snap); @@ -59,6 +60,8 @@ private: void write_public_key(const std::string& public_key) { + g_debug("writing public key '%s' to '%s'", public_key.c_str(), m_public_keys_filename.c_str()); + // confirm the directory exists auto dirname = g_path_get_dirname(m_public_keys_filename.c_str()); const auto dir_exists = g_file_test(dirname, G_FILE_TEST_IS_DIR); -- cgit v1.2.3 From 45709c48f34e0909c1309dccac1dd3e047f518fb Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 18 Mar 2016 12:39:58 -0500 Subject: turn off verbose debugging --- src/main.cpp | 3 --- src/usb-manager.cpp | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 2e428f9..7d6eb5f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,9 +29,6 @@ int main(int /*argc*/, char** /*argv*/) { -#warning NB the next line turns on verbose debug logging and is used for developement. Remove it before landing. -g_assert(g_setenv("G_MESSAGES_DEBUG", "all", true)); - // Work around a deadlock in glib's type initialization. // It can be removed when https://bugzilla.gnome.org/show_bug.cgi?id=674885 is fixed. g_type_ensure(G_TYPE_DBUS_CONNECTION); diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 335db00..7f43520 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -42,7 +42,7 @@ public: m_adbd_client->on_pk_request().connect([this](const AdbdClient::PKRequest& req){ auto snap = new UsbSnap(req.fingerprint); snap->on_user_response().connect([this,req,snap](AdbdClient::PKResponse response, bool remember_choice){ - g_debug("user responded! response %d, remember %d", int(response), int(remember_choice)); + g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); req.respond(response); if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) write_public_key(req.public_key); @@ -78,12 +78,12 @@ private: S_IRUSR|S_IWUSR|S_IRGRP ); if (fd == -1) { - g_warning("Error opening ADB datafile: %s", g_strerror(errno)); + g_warning("Error opening ADB datafile '%s': %s", m_public_keys_filename.c_str(), g_strerror(errno)); return; } // write the new public key on its own line - std::string buf {public_key + '\n'}; + const std::string buf {public_key + '\n'}; if (write(fd, buf.c_str(), buf.size()) == -1) g_warning("Error writing ADB datafile: %d %s", errno, g_strerror(errno)); close(fd); -- cgit v1.2.3 From 7a25132c125f6e5e413ad26ea950ae22bee982f5 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 21 Mar 2016 13:40:11 -0500 Subject: if our USB device is disconnected while prompting the user for ADBD, cancel the prompt. --- src/CMakeLists.txt | 1 + src/adbd-client.cpp | 1 + src/main.cpp | 4 ++- src/usb-manager.cpp | 63 ++++++++++++++++++++++++++++------------- src/usb-manager.h | 11 +++++++- src/usb-monitor.cpp | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/usb-monitor.h | 52 ++++++++++++++++++++++++++++++++++ src/usb-snap.cpp | 1 + 8 files changed, 192 insertions(+), 22 deletions(-) create mode 100644 src/usb-monitor.cpp create mode 100644 src/usb-monitor.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d3a021b..cdd2384 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,7 @@ add_library( indicator.cpp rotation-lock.cpp usb-manager.cpp + usb-monitor.cpp usb-snap.cpp ) diff --git a/src/adbd-client.cpp b/src/adbd-client.cpp index 4f7d28f..937215e 100644 --- a/src/adbd-client.cpp +++ b/src/adbd-client.cpp @@ -45,6 +45,7 @@ public: { // tell the worker thread to stop whatever it's doing and exit. g_cancellable_cancel(m_cancellable); + m_pkresponse_cv.notify_one(); m_sleep_cv.notify_one(); m_worker_thread.join(); g_clear_object(&m_cancellable); diff --git a/src/main.cpp b/src/main.cpp index 7d6eb5f..27e6bcc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include // bindtextdomain() #include @@ -59,7 +60,8 @@ main(int /*argc*/, char** /*argv*/) // even though it doesn't have an indicator component yet static constexpr char const * ADB_SOCKET_PATH {"/dev/socket/adbd"}; static constexpr char const * PUBLIC_KEYS_FILENAME {"/data/misc/adb/adb_keys"}; - UsbManager usb_manager {ADB_SOCKET_PATH, PUBLIC_KEYS_FILENAME}; + auto usb_monitor = std::make_shared(); + UsbManager usb_manager {ADB_SOCKET_PATH, PUBLIC_KEYS_FILENAME, usb_monitor}; // let's go! g_main_loop_run(loop); diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 7f43520..840a04b 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -28,39 +28,57 @@ #include #include +#include + class UsbManager::Impl { public: explicit Impl( const std::string& socket_path, - const std::string& public_keys_filename + const std::string& public_keys_filename, + const std::shared_ptr& usb_monitor ): m_adbd_client{std::make_shared(socket_path)}, - m_public_keys_filename{public_keys_filename} + m_public_keys_filename{public_keys_filename}, + m_usb_monitor{usb_monitor} { - m_adbd_client->on_pk_request().connect([this](const AdbdClient::PKRequest& req){ - auto snap = new UsbSnap(req.fingerprint); - snap->on_user_response().connect([this,req,snap](AdbdClient::PKResponse response, bool remember_choice){ - g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); - req.respond(response); - if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) - write_public_key(req.public_key); - // delete_later - g_idle_add([](gpointer gsnap){delete static_cast(gsnap); return G_SOURCE_REMOVE;}, snap); - }); + m_usb_monitor->on_usb_disconnected().connect([this](const std::string& /*usb_name*/) { + m_snap.reset(); }); - } - ~Impl() - { + m_adbd_client->on_pk_request().connect( + [this](const AdbdClient::PKRequest& req){ + + m_snap.reset(new UsbSnap(req.fingerprint), + [this](UsbSnap* snap){ + m_snap_connections.clear(); + delete snap; + } + ); + + m_snap_connections.insert((*m_snap).on_user_response().connect( + [this,req](AdbdClient::PKResponse response, bool remember_choice){ + g_message("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); + req.respond(response); + g_message("%s", G_STRLOC); + if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) + write_public_key(req.public_key); + g_idle_add([](gpointer gself){static_cast(gself)->m_snap.reset(); return G_SOURCE_REMOVE;}, this); + } + )); + } + ); + } + ~Impl() =default; + private: void write_public_key(const std::string& public_key) { - g_debug("writing public key '%s' to '%s'", public_key.c_str(), m_public_keys_filename.c_str()); + g_message("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); // confirm the directory exists auto dirname = g_path_get_dirname(m_public_keys_filename.c_str()); @@ -78,12 +96,12 @@ private: S_IRUSR|S_IWUSR|S_IRGRP ); if (fd == -1) { - g_warning("Error opening ADB datafile '%s': %s", m_public_keys_filename.c_str(), g_strerror(errno)); + g_warning("Error opening ADB datafile: %s", g_strerror(errno)); return; } // write the new public key on its own line - const std::string buf {public_key + '\n'}; + std::string buf {public_key + '\n'}; if (write(fd, buf.c_str(), buf.size()) == -1) g_warning("Error writing ADB datafile: %d %s", errno, g_strerror(errno)); close(fd); @@ -91,6 +109,10 @@ private: std::shared_ptr m_adbd_client; const std::string m_public_keys_filename; + std::shared_ptr m_usb_monitor; + + std::shared_ptr m_snap; + std::set m_snap_connections; }; /*** @@ -99,9 +121,10 @@ private: UsbManager::UsbManager( const std::string& socket_path, - const std::string& public_keys_filename + const std::string& public_keys_filename, + const std::shared_ptr& usb_monitor ): - impl{new Impl{socket_path, public_keys_filename}} + impl{new Impl{socket_path, public_keys_filename, usb_monitor}} { } diff --git a/src/usb-manager.h b/src/usb-manager.h index ec405c0..960d634 100644 --- a/src/usb-manager.h +++ b/src/usb-manager.h @@ -19,6 +19,8 @@ #pragma once +#include + #include #include @@ -28,10 +30,17 @@ class UsbManager { public: - UsbManager(const std::string& socket_path, const std::string& public_key_filename); + + UsbManager( + const std::string& socket_path, + const std::string& public_key_filename, + const std::shared_ptr& + ); + ~UsbManager(); protected: + class Impl; std::unique_ptr impl; }; diff --git a/src/usb-monitor.cpp b/src/usb-monitor.cpp new file mode 100644 index 0000000..5fc5a6d --- /dev/null +++ b/src/usb-monitor.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include + +#include +#include + +class GUDevUsbMonitor::Impl +{ +public: + + Impl() + { + const char* subsystems[] = {"android_usb", nullptr}; + m_udev_client = g_udev_client_new(subsystems); + g_signal_connect(m_udev_client, "uevent", G_CALLBACK(on_android_usb_event), this); + } + + ~Impl() + { + g_signal_handlers_disconnect_by_data(m_udev_client, this); + g_clear_object(&m_udev_client); + } + + core::Signal& on_usb_disconnected() + { + return m_on_usb_disconnected; + } + +private: + + static void on_android_usb_event(GUdevClient*, gchar* action, GUdevDevice* device, gpointer gself) + { + if (!g_strcmp0(action, "change")) + if (!g_strcmp0(g_udev_device_get_property(device, "USB_STATE"), "DISCONNECTED")) + static_cast(gself)->m_on_usb_disconnected(g_udev_device_get_name(device)); + } + + core::Signal m_on_usb_disconnected; + + GUdevClient* m_udev_client = nullptr; +}; + +/*** +**** +***/ + +UsbMonitor::UsbMonitor() =default; + +UsbMonitor::~UsbMonitor() =default; + +GUDevUsbMonitor::GUDevUsbMonitor(): + impl{new Impl{}} +{ +} + +GUDevUsbMonitor::~GUDevUsbMonitor() =default; + +core::Signal& +GUDevUsbMonitor::on_usb_disconnected() +{ + return impl->on_usb_disconnected(); +} + diff --git a/src/usb-monitor.h b/src/usb-monitor.h new file mode 100644 index 0000000..d9be539 --- /dev/null +++ b/src/usb-monitor.h @@ -0,0 +1,52 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#pragma once + +#include + +#include +#include + +/** + * Simple interface that emits signals on USB device state changes + */ +class UsbMonitor +{ +public: + UsbMonitor(); + virtual ~UsbMonitor(); + virtual core::Signal& on_usb_disconnected() =0; +}; + +/** + * Simple GUDev wrapper that notifies on android_usb device state changes + */ +class GUDevUsbMonitor: public UsbMonitor +{ +public: + GUDevUsbMonitor(); + virtual ~GUDevUsbMonitor(); + core::Signal& on_usb_disconnected() override; + +protected: + class Impl; + std::unique_ptr impl; +}; + diff --git a/src/usb-snap.cpp b/src/usb-snap.cpp index 41c78c6..349d80e 100644 --- a/src/usb-snap.cpp +++ b/src/usb-snap.cpp @@ -148,6 +148,7 @@ private: { GError* error {}; auto reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION(obus), res, &error); +g_message("%s got notify response %s", G_STRLOC, g_variant_print(reply, true)); if (error != nullptr) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning("UsbSnap: Error calling Notify: %s", error->message); -- cgit v1.2.3 From 1c4f005f0765f460b28808a624fbec7737324b1a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 21 Mar 2016 17:05:01 -0500 Subject: in UsbManager, reset AdbdClient on usb disconnect --- src/usb-manager.cpp | 44 ++++++++++++++++++++++++++------------------ src/usb-snap.cpp | 1 - 2 files changed, 26 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 840a04b..f5957d9 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -39,29 +39,40 @@ public: const std::string& public_keys_filename, const std::shared_ptr& usb_monitor ): - m_adbd_client{std::make_shared(socket_path)}, + m_socket_path{socket_path}, m_public_keys_filename{public_keys_filename}, m_usb_monitor{usb_monitor} { m_usb_monitor->on_usb_disconnected().connect([this](const std::string& /*usb_name*/) { - m_snap.reset(); + restart(); }); + restart(); + } + + ~Impl() =default; + +private: + + void restart() + { + // clear out old state + m_snap_connections.clear(); + m_snap.reset(); + m_adbd_client.reset(); + + // add a new client + m_adbd_client.reset(new GAdbdClient{m_socket_path}); m_adbd_client->on_pk_request().connect( - [this](const AdbdClient::PKRequest& req){ + [this](const AdbdClient::PKRequest& req) { - m_snap.reset(new UsbSnap(req.fingerprint), - [this](UsbSnap* snap){ - m_snap_connections.clear(); - delete snap; - } - ); + g_debug("%s got pk request", G_STRLOC); + m_snap = std::make_shared(req.fingerprint); m_snap_connections.insert((*m_snap).on_user_response().connect( [this,req](AdbdClient::PKResponse response, bool remember_choice){ - g_message("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); + g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); req.respond(response); - g_message("%s", G_STRLOC); if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) write_public_key(req.public_key); g_idle_add([](gpointer gself){static_cast(gself)->m_snap.reset(); return G_SOURCE_REMOVE;}, this); @@ -69,16 +80,11 @@ public: )); } ); - } - ~Impl() =default; - -private: - void write_public_key(const std::string& public_key) { - g_message("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); + g_debug("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); // confirm the directory exists auto dirname = g_path_get_dirname(m_public_keys_filename.c_str()); @@ -107,10 +113,12 @@ private: close(fd); } - std::shared_ptr m_adbd_client; + const std::string m_socket_path; const std::string m_public_keys_filename; + std::shared_ptr m_usb_monitor; + std::shared_ptr m_adbd_client; std::shared_ptr m_snap; std::set m_snap_connections; }; diff --git a/src/usb-snap.cpp b/src/usb-snap.cpp index 349d80e..41c78c6 100644 --- a/src/usb-snap.cpp +++ b/src/usb-snap.cpp @@ -148,7 +148,6 @@ private: { GError* error {}; auto reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION(obus), res, &error); -g_message("%s got notify response %s", G_STRLOC, g_variant_print(reply, true)); if (error != nullptr) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning("UsbSnap: Error calling Notify: %s", error->message); -- cgit v1.2.3 From ecf802d7c939fcc73838d19de546294bc1c89e33 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 21 Mar 2016 18:15:05 -0500 Subject: add Greeter skeleton --- src/CMakeLists.txt | 1 + src/dbus-names.h | 7 +++ src/greeter.cpp | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/greeter.h | 47 ++++++++++++++++++++ 4 files changed, 178 insertions(+) create mode 100644 src/greeter.cpp create mode 100644 src/greeter.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cdd2384..060071d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ add_library( STATIC adbd-client.cpp exporter.cpp + greeter.cpp indicator.cpp rotation-lock.cpp usb-manager.cpp diff --git a/src/dbus-names.h b/src/dbus-names.h index 753b8c8..3127b9f 100644 --- a/src/dbus-names.h +++ b/src/dbus-names.h @@ -38,5 +38,12 @@ namespace DBusNames enum Reason { EXPIRED=1, DISMISSED=2, API=3, UNDEFINED=4 }; } } + + namespace UnityGreeter + { + static constexpr char const * NAME = "com.canonical.UnityGreeter"; + static constexpr char const * PATH = "/"; + static constexpr char const * INTERFACE = "com.canonical.UnityGreeter"; + } } diff --git a/src/greeter.cpp b/src/greeter.cpp new file mode 100644 index 0000000..351b870 --- /dev/null +++ b/src/greeter.cpp @@ -0,0 +1,123 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include +#include + +#include + +class UnityGreeter::Impl +{ +public: + + Impl(): + m_cancellable{g_cancellable_new()} + { + g_bus_get(G_BUS_TYPE_SESSION, m_cancellable, on_bus_ready_static, this); + } + + ~Impl() + { + g_cancellable_cancel(m_cancellable); + g_clear_object(&m_cancellable); + + if (m_subscription_id != 0) + g_dbus_connection_signal_unsubscribe (m_bus, m_subscription_id); + + g_clear_object(&m_bus); + } + + core::Property& is_active() + { + return m_is_active; + } + +private: + + static void on_bus_ready_static(GObject* /*source*/, GAsyncResult* res, gpointer gself) + { + GError* error {}; + auto bus = g_bus_get_finish (res, &error); + if (error != nullptr) { + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning("UsbSnap: Error getting session bus: %s", error->message); + g_clear_error(&error); + } else { + static_cast(gself)->on_bus_ready(bus); + } + g_clear_object(&bus); + } + + void on_bus_ready(GDBusConnection* bus) + { + m_bus = G_DBUS_CONNECTION(g_object_ref(G_OBJECT(bus))); + + m_subscription_id = g_dbus_connection_signal_subscribe(m_bus, + DBusNames::UnityGreeter::NAME, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + DBusNames::UnityGreeter::PATH, + nullptr, + G_DBUS_SIGNAL_FLAGS_NONE, + on_properties_changed_signal_static, + this, + nullptr); + } + + static void on_properties_changed_signal_static(GDBusConnection* /*connection*/, + const gchar* sender_name, + const gchar* object_path, + const gchar* interface_name, + const gchar* signal_name, + GVariant* parameters, + gpointer gself) + { + g_return_if_fail(!g_strcmp0(sender_name, DBusNames::UnityGreeter::NAME)); + g_return_if_fail(!g_strcmp0(object_path, DBusNames::UnityGreeter::PATH)); + g_return_if_fail(!g_strcmp0(interface_name, "org.freedesktop.DBus.Properties")); + g_return_if_fail(!g_strcmp0(signal_name, "PropertiesChanged")); + + static_cast(gself)->on_properties_changed_signal(parameters); + } + + void on_properties_changed_signal(GVariant* parameters) + { + g_message("%s %s", G_STRLOC, g_variant_print(parameters, true)); + } + + core::Property m_is_active; + GCancellable* m_cancellable {}; + GDBusConnection* m_bus {}; + unsigned int m_subscription_id {}; +}; + +/*** +**** +***/ + +Greeter::Greeter() =default; + +Greeter::~Greeter() =default; + +UnityGreeter::~UnityGreeter() =default; + +UnityGreeter::UnityGreeter(): + impl{new Impl{}} +{ +} diff --git a/src/greeter.h b/src/greeter.h new file mode 100644 index 0000000..e084d25 --- /dev/null +++ b/src/greeter.h @@ -0,0 +1,47 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#pragma once + +#include + +#include +#include + +class Greeter +{ +public: + Greeter(); + virtual ~Greeter(); + virtual core::Property& is_active() =0; +}; + + +class UnityGreeter: public Greeter +{ +public: + UnityGreeter(); + virtual ~UnityGreeter(); + core::Property& is_active() override; + +protected: + class Impl; + std::unique_ptr impl; +}; + -- cgit v1.2.3 From 70209f30bc6907ad545e33dc6e7de78cf63b9e9a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 21 Mar 2016 19:33:35 -0500 Subject: get greeter's IsActive property working --- src/dbus-names.h | 11 ++++++++ src/greeter.cpp | 80 +++++++++++++++++++++++++++++++++++++++++--------------- src/main.cpp | 3 +++ 3 files changed, 73 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/dbus-names.h b/src/dbus-names.h index 3127b9f..b31098a 100644 --- a/src/dbus-names.h +++ b/src/dbus-names.h @@ -45,5 +45,16 @@ namespace DBusNames static constexpr char const * PATH = "/"; static constexpr char const * INTERFACE = "com.canonical.UnityGreeter"; } + + namespace Properties + { + static constexpr char const * INTERFACE = "org.freedesktop.DBus.Properties"; + + namespace PropertiesChanged + { + static constexpr char const* NAME = "PropertiesChanged"; + static constexpr char const* ARGS_VARIANT_TYPE = "(sa{sv}as)"; + } + } } diff --git a/src/greeter.cpp b/src/greeter.cpp index 351b870..cffa376 100644 --- a/src/greeter.cpp +++ b/src/greeter.cpp @@ -68,37 +68,69 @@ private: { m_bus = G_DBUS_CONNECTION(g_object_ref(G_OBJECT(bus))); + g_dbus_connection_call(m_bus, + DBusNames::UnityGreeter::NAME, + DBusNames::UnityGreeter::PATH, + DBusNames::Properties::INTERFACE, + "Get", + g_variant_new("(ss)", DBusNames::UnityGreeter::INTERFACE, "IsActive"), + G_VARIANT_TYPE("(v)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + m_cancellable, + on_get_is_active_ready, + this); + m_subscription_id = g_dbus_connection_signal_subscribe(m_bus, DBusNames::UnityGreeter::NAME, - "org.freedesktop.DBus.Properties", - "PropertiesChanged", + DBusNames::Properties::INTERFACE, + DBusNames::Properties::PropertiesChanged::NAME, DBusNames::UnityGreeter::PATH, - nullptr, + DBusNames::UnityGreeter::INTERFACE, G_DBUS_SIGNAL_FLAGS_NONE, - on_properties_changed_signal_static, + on_properties_changed_signal, this, nullptr); } - static void on_properties_changed_signal_static(GDBusConnection* /*connection*/, - const gchar* sender_name, - const gchar* object_path, - const gchar* interface_name, - const gchar* signal_name, - GVariant* parameters, - gpointer gself) + static void on_get_is_active_ready(GObject* source, GAsyncResult* res, gpointer gself) { - g_return_if_fail(!g_strcmp0(sender_name, DBusNames::UnityGreeter::NAME)); - g_return_if_fail(!g_strcmp0(object_path, DBusNames::UnityGreeter::PATH)); - g_return_if_fail(!g_strcmp0(interface_name, "org.freedesktop.DBus.Properties")); - g_return_if_fail(!g_strcmp0(signal_name, "PropertiesChanged")); - - static_cast(gself)->on_properties_changed_signal(parameters); + GError* error {}; + auto v = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &error); + if (error != nullptr) { + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning("UsbSnap: Error getting session bus: %s", error->message); + g_clear_error(&error); + } else { + GVariant* is_active {}; + g_variant_get_child(v, 0, "v", &is_active_v); + static_cast(gself)->m_is_active.set(g_variant_get_boolean(is_active); + g_clear_pointer(&is_active, g_variant_unref); + } + g_clear_pointer(&v, g_variant_unref); } - void on_properties_changed_signal(GVariant* parameters) + static void on_properties_changed_signal(GDBusConnection* /*connection*/, + const gchar* /*sender_name*/, + const gchar* object_path, + const gchar* interface_name, + const gchar* signal_name, + GVariant* parameters, + gpointer gself) { - g_message("%s %s", G_STRLOC, g_variant_print(parameters, true)); + g_return_if_fail(!g_strcmp0(object_path, DBusNames::UnityGreeter::PATH)); + g_return_if_fail(!g_strcmp0(interface_name, DBusNames::Properties::INTERFACE)); + g_return_if_fail(!g_strcmp0(signal_name, DBusNames::Properties::PropertiesChanged::NAME)); + g_return_if_fail(g_variant_is_of_type(parameters, G_VARIANT_TYPE(DBusNames::Properties::PropertiesChanged::ARGS_VARIANT_TYPE))); + + auto v = g_variant_get_child_value (parameters, 1); + gboolean is_active {}; + if (g_variant_lookup(v, "IsActive", "b", &is_active)) + { + g_debug("%s is_active changed to %d", G_STRLOC, int(is_active)); + static_cast(gself)->m_is_active.set(is_active); + } + g_clear_pointer(&v, g_variant_unref); } core::Property m_is_active; @@ -115,9 +147,15 @@ Greeter::Greeter() =default; Greeter::~Greeter() =default; -UnityGreeter::~UnityGreeter() =default; - UnityGreeter::UnityGreeter(): impl{new Impl{}} { } + +UnityGreeter::~UnityGreeter() =default; + +core::Property& +UnityGreeter::is_active() +{ + return impl->is_active(); +} diff --git a/src/main.cpp b/src/main.cpp index 27e6bcc..6c111f1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,6 +19,8 @@ #include #include + +#include #include #include @@ -61,6 +63,7 @@ main(int /*argc*/, char** /*argv*/) static constexpr char const * ADB_SOCKET_PATH {"/dev/socket/adbd"}; static constexpr char const * PUBLIC_KEYS_FILENAME {"/data/misc/adb/adb_keys"}; auto usb_monitor = std::make_shared(); + auto greeter = std::make_shared(); UsbManager usb_manager {ADB_SOCKET_PATH, PUBLIC_KEYS_FILENAME, usb_monitor}; // let's go! -- cgit v1.2.3 From cc2e2265ada413826e199248dee90a19db31b741 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 22 Mar 2016 08:15:38 -0500 Subject: fix typo --- src/greeter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/greeter.cpp b/src/greeter.cpp index cffa376..f9cd965 100644 --- a/src/greeter.cpp +++ b/src/greeter.cpp @@ -103,8 +103,8 @@ private: g_clear_error(&error); } else { GVariant* is_active {}; - g_variant_get_child(v, 0, "v", &is_active_v); - static_cast(gself)->m_is_active.set(g_variant_get_boolean(is_active); + g_variant_get_child(v, 0, "v", &is_active); + static_cast(gself)->m_is_active.set(g_variant_get_boolean(is_active)); g_clear_pointer(&is_active, g_variant_unref); } g_clear_pointer(&v, g_variant_unref); -- cgit v1.2.3 From a5f330f6b73101d7bbdeadc6a5f53b8da3349999 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 22 Mar 2016 15:39:36 -0500 Subject: don't show the snap decision until we're out of the greeter --- src/main.cpp | 2 +- src/usb-manager.cpp | 76 ++++++++++++++++++++++++++++++++++++++--------------- src/usb-manager.h | 4 ++- 3 files changed, 59 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 6c111f1..52cdd58 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -64,7 +64,7 @@ main(int /*argc*/, char** /*argv*/) static constexpr char const * PUBLIC_KEYS_FILENAME {"/data/misc/adb/adb_keys"}; auto usb_monitor = std::make_shared(); auto greeter = std::make_shared(); - UsbManager usb_manager {ADB_SOCKET_PATH, PUBLIC_KEYS_FILENAME, usb_monitor}; + UsbManager usb_manager {ADB_SOCKET_PATH, PUBLIC_KEYS_FILENAME, usb_monitor, greeter}; // let's go! g_main_loop_run(loop); diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index f5957d9..0e59ca2 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -37,51 +37,83 @@ public: explicit Impl( const std::string& socket_path, const std::string& public_keys_filename, - const std::shared_ptr& usb_monitor + const std::shared_ptr& usb_monitor, + const std::shared_ptr& greeter ): m_socket_path{socket_path}, m_public_keys_filename{public_keys_filename}, - m_usb_monitor{usb_monitor} + m_usb_monitor{usb_monitor}, + m_greeter{greeter} { m_usb_monitor->on_usb_disconnected().connect([this](const std::string& /*usb_name*/) { restart(); }); + m_greeter->is_active().changed().connect([this](bool /*is_active*/) { + maybe_snap_now(); + }); + restart(); } - ~Impl() =default; + ~Impl() + { + clear(); + } private: - void restart() + void clear() { // clear out old state m_snap_connections.clear(); m_snap.reset(); + m_req = AdbdClient::PKRequest{}; m_adbd_client.reset(); + } - // add a new client + void restart() + { + clear(); + + // set a new client m_adbd_client.reset(new GAdbdClient{m_socket_path}); m_adbd_client->on_pk_request().connect( [this](const AdbdClient::PKRequest& req) { - g_debug("%s got pk request", G_STRLOC); - - m_snap = std::make_shared(req.fingerprint); - m_snap_connections.insert((*m_snap).on_user_response().connect( - [this,req](AdbdClient::PKResponse response, bool remember_choice){ - g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); - req.respond(response); - if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) - write_public_key(req.public_key); - g_idle_add([](gpointer gself){static_cast(gself)->m_snap.reset(); return G_SOURCE_REMOVE;}, this); - } - )); + m_req = req; + maybe_snap_now(); } ); } + bool ready_to_snap() + { + return !m_greeter->is_active().get() && !m_req.public_key.empty(); + } + + void maybe_snap_now() + { + if (ready_to_snap()) + snap_now(); + } + + void snap_now() + { + g_return_if_fail(ready_to_snap()); + + m_snap = std::make_shared(m_req.fingerprint); + m_snap_connections.insert((*m_snap).on_user_response().connect( + [this](AdbdClient::PKResponse response, bool remember_choice){ + g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); + m_req.respond(response); + if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) + write_public_key(m_req.public_key); + g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); + } + )); + } + void write_public_key(const std::string& public_key) { g_debug("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); @@ -115,10 +147,11 @@ private: const std::string m_socket_path; const std::string m_public_keys_filename; - - std::shared_ptr m_usb_monitor; + const std::shared_ptr m_usb_monitor; + const std::shared_ptr m_greeter; std::shared_ptr m_adbd_client; + AdbdClient::PKRequest m_req; std::shared_ptr m_snap; std::set m_snap_connections; }; @@ -130,9 +163,10 @@ private: UsbManager::UsbManager( const std::string& socket_path, const std::string& public_keys_filename, - const std::shared_ptr& usb_monitor + const std::shared_ptr& usb_monitor, + const std::shared_ptr& greeter ): - impl{new Impl{socket_path, public_keys_filename, usb_monitor}} + impl{new Impl{socket_path, public_keys_filename, usb_monitor, greeter}} { } diff --git a/src/usb-manager.h b/src/usb-manager.h index 960d634..b93992f 100644 --- a/src/usb-manager.h +++ b/src/usb-manager.h @@ -19,6 +19,7 @@ #pragma once +#include #include #include @@ -34,7 +35,8 @@ public: UsbManager( const std::string& socket_path, const std::string& public_key_filename, - const std::shared_ptr& + const std::shared_ptr&, + const std::shared_ptr& ); ~UsbManager(); -- cgit v1.2.3 From 4f8a17f23a0bba7da7654c147ca377e271abe0db Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 22 Mar 2016 16:01:47 -0500 Subject: add tests for not showing snap decisions in greeter mode --- src/usb-manager.cpp | 48 ++++++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 0e59ca2..4fdfdc1 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -50,7 +50,7 @@ public: }); m_greeter->is_active().changed().connect([this](bool /*is_active*/) { - maybe_snap_now(); + restart(); }); restart(); @@ -68,7 +68,6 @@ private: // clear out old state m_snap_connections.clear(); m_snap.reset(); - m_req = AdbdClient::PKRequest{}; m_adbd_client.reset(); } @@ -76,44 +75,30 @@ private: { clear(); + // don't prompt in the greeter! + if (m_greeter->is_active().get()) + return; + // set a new client +g_message("creating a new adbd client"); m_adbd_client.reset(new GAdbdClient{m_socket_path}); m_adbd_client->on_pk_request().connect( [this](const AdbdClient::PKRequest& req) { g_debug("%s got pk request", G_STRLOC); - m_req = req; - maybe_snap_now(); + m_snap = std::make_shared(req.fingerprint); + m_snap_connections.insert((*m_snap).on_user_response().connect( + [this,req](AdbdClient::PKResponse response, bool remember_choice){ + g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); + req.respond(response); + if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) + write_public_key(req.public_key); + g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); + } + )); } ); } - bool ready_to_snap() - { - return !m_greeter->is_active().get() && !m_req.public_key.empty(); - } - - void maybe_snap_now() - { - if (ready_to_snap()) - snap_now(); - } - - void snap_now() - { - g_return_if_fail(ready_to_snap()); - - m_snap = std::make_shared(m_req.fingerprint); - m_snap_connections.insert((*m_snap).on_user_response().connect( - [this](AdbdClient::PKResponse response, bool remember_choice){ - g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); - m_req.respond(response); - if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) - write_public_key(m_req.public_key); - g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); - } - )); - } - void write_public_key(const std::string& public_key) { g_debug("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); @@ -151,7 +136,6 @@ private: const std::shared_ptr m_greeter; std::shared_ptr m_adbd_client; - AdbdClient::PKRequest m_req; std::shared_ptr m_snap; std::set m_snap_connections; }; -- cgit v1.2.3 From 82588108a40fb50b2bbd3c7b89b990f76f488edc Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 23 Mar 2016 12:16:06 -0500 Subject: replace text 'Deny' with 'Don't Allow' for consistency with other permission prompts --- src/usb-snap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/usb-snap.cpp b/src/usb-snap.cpp index 41c78c6..ba964fb 100644 --- a/src/usb-snap.cpp +++ b/src/usb-snap.cpp @@ -111,7 +111,7 @@ private: g_variant_builder_add(&actions_builder, "s", ACTION_ALLOW); g_variant_builder_add(&actions_builder, "s", _("Allow")); g_variant_builder_add(&actions_builder, "s", ACTION_DENY); - g_variant_builder_add(&actions_builder, "s", _("Deny")); + g_variant_builder_add(&actions_builder, "s", _("Don't Allow")); GVariantBuilder hints_builder; g_variant_builder_init(&hints_builder, G_VARIANT_TYPE_VARDICT); -- cgit v1.2.3 From ccc831d425006a803ca64c5525d38fef8912aac5 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 23 Mar 2016 14:02:48 -0500 Subject: keep the adbd socket open even when the lockscreen is closed. hold the pkrequest state in USBManager until the screen's unlocked. --- src/usb-manager.cpp | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 4fdfdc1..656b6a0 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -50,7 +50,7 @@ public: }); m_greeter->is_active().changed().connect([this](bool /*is_active*/) { - restart(); + maybe_snap(); }); restart(); @@ -68,6 +68,7 @@ private: // clear out old state m_snap_connections.clear(); m_snap.reset(); + m_req = decltype(m_req){}; m_adbd_client.reset(); } @@ -75,30 +76,38 @@ private: { clear(); - // don't prompt in the greeter! - if (m_greeter->is_active().get()) - return; - // set a new client -g_message("creating a new adbd client"); m_adbd_client.reset(new GAdbdClient{m_socket_path}); m_adbd_client->on_pk_request().connect( [this](const AdbdClient::PKRequest& req) { - g_debug("%s got pk request", G_STRLOC); - m_snap = std::make_shared(req.fingerprint); - m_snap_connections.insert((*m_snap).on_user_response().connect( - [this,req](AdbdClient::PKResponse response, bool remember_choice){ - g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); - req.respond(response); - if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) - write_public_key(req.public_key); - g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); - } - )); + g_debug("%s got pk request: %s", G_STRLOC, req.fingerprint.c_str()); + m_req = req; + maybe_snap(); } ); } + void maybe_snap() + { + // don't prompt in the greeter! + if (!m_req.public_key.empty() && !m_greeter->is_active().get()) + snap(); + } + + void snap() + { + m_snap = std::make_shared(m_req.fingerprint); + m_snap_connections.insert((*m_snap).on_user_response().connect( + [this](AdbdClient::PKResponse response, bool remember_choice){ + g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); + m_req.respond(response); + if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) + write_public_key(m_req.public_key); + g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); + } + )); + } + void write_public_key(const std::string& public_key) { g_debug("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); @@ -136,6 +145,7 @@ g_message("creating a new adbd client"); const std::shared_ptr m_greeter; std::shared_ptr m_adbd_client; + AdbdClient::PKRequest m_req; std::shared_ptr m_snap; std::set m_snap_connections; }; -- cgit v1.2.3 From 8f396a525d1353d724b6a96b8a777be2dde35984 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 23 Mar 2016 14:12:05 -0500 Subject: fix missing field initialization compiler warning --- src/usb-manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 656b6a0..f67f0e2 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -68,7 +68,7 @@ private: // clear out old state m_snap_connections.clear(); m_snap.reset(); - m_req = decltype(m_req){}; + m_req = decltype(m_req)(); m_adbd_client.reset(); } -- cgit v1.2.3 From 9f03876ba4aef09f5b93905f90df9a7b9d1073e4 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 23 Mar 2016 14:44:23 -0500 Subject: fix UsbManager dtor issue found by valgrind --- src/usb-manager.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index f67f0e2..4d750c0 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -58,6 +58,9 @@ public: ~Impl() { + if (m_restart_idle_tag) + g_source_remove(m_restart_idle_tag); + clear(); } @@ -103,7 +106,12 @@ private: m_req.respond(response); if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) write_public_key(m_req.public_key); - g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); + m_restart_idle_tag = g_idle_add([](gpointer gself){ + auto self = static_cast(gself); + self->m_restart_idle_tag = 0; + self->restart(); + return G_SOURCE_REMOVE; + }, this); } )); } @@ -143,6 +151,8 @@ private: const std::string m_public_keys_filename; const std::shared_ptr m_usb_monitor; const std::shared_ptr m_greeter; + + unsigned int m_restart_idle_tag {}; std::shared_ptr m_adbd_client; AdbdClient::PKRequest m_req; -- cgit v1.2.3 From 194d7e85a52cbc0060a2d85b71b9ddd8b606aee4 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 24 Mar 2016 11:01:16 -0500 Subject: add tracer g_debug() calls for the benefit of the integration tests --- src/adbd-client.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/adbd-client.cpp b/src/adbd-client.cpp index 937215e..400c7c9 100644 --- a/src/adbd-client.cpp +++ b/src/adbd-client.cpp @@ -44,6 +44,7 @@ public: ~Impl() { // tell the worker thread to stop whatever it's doing and exit. + g_debug("%s Client::Impl dtor, cancelling m_cancellable", G_STRLOC); g_cancellable_cancel(m_cancellable); m_pkresponse_cv.notify_one(); m_sleep_cv.notify_one(); @@ -144,7 +145,9 @@ private: return m_pkresponse_ready || g_cancellable_is_cancelled(m_cancellable); }); response = m_pkresponse; - g_debug("%s got response '%d'", G_STRLOC, int(response)); + g_debug("%s got response '%d', is-cancelled %d", G_STRLOC, + int(response), + int(g_cancellable_is_cancelled(m_cancellable))); } if (!g_cancellable_is_cancelled(m_cancellable)) send_pk_response(socket, response); -- cgit v1.2.3