From 1a06926464f7e0944ff2734b80b41f3931d4c8db Mon Sep 17 00:00:00 2001 From: Inkyun Kil Date: Wed, 21 Feb 2018 16:11:44 +0900 Subject: [PATCH] Add new AccessControl and Remove sender_appid from dbus - Add new AccessControl for trusted app - Remove sender_appid that was passed through dbus Change-Id: I648bdbfa8bc97a8c363ffa994ebe5d71a10c6288 Signed-off-by: Inkyun Kil --- include/rpc-port.h | 3 +++ src/ac-internal.cc | 66 ++++++++++++++++++++++++++++++++++++++++-------- src/ac-internal.h | 14 +++++++--- src/fdbroker-internal.cc | 66 ++++++++++++++++++++++++++++++++++++------------ src/fdbroker-internal.h | 3 ++- src/rpc-port.cc | 13 ++++++++++ src/stub-internal.cc | 5 ++++ src/stub-internal.h | 1 + 8 files changed, 140 insertions(+), 31 deletions(-) diff --git a/include/rpc-port.h b/include/rpc-port.h index 7897990..855c14e 100755 --- a/include/rpc-port.h +++ b/include/rpc-port.h @@ -21,6 +21,8 @@ extern "C" { #endif +#include + /* common */ typedef void *rpc_port_h; int rpc_port_read(rpc_port_h h, void *buf, unsigned int size); @@ -62,6 +64,7 @@ int rpc_port_stub_create(rpc_port_stub_h *h, const char *port_name); int rpc_port_stub_destroy(rpc_port_stub_h h); int rpc_port_stub_listen(rpc_port_stub_h h); int rpc_port_stub_add_privilege(rpc_port_stub_h h, const char *privilege); +int rpc_port_stub_set_trusted(rpc_port_stub_h h, const bool trusted); int rpc_port_stub_add_connected_event_cb(rpc_port_stub_h h, rpc_port_stub_connected_event_cb cb, void *data); int rpc_port_stub_add_disconnected_event_cb(rpc_port_stub_h h, diff --git a/src/ac-internal.cc b/src/ac-internal.cc index 7ce273c..97f47af 100644 --- a/src/ac-internal.cc +++ b/src/ac-internal.cc @@ -18,7 +18,9 @@ #define _GNU_SOURCE #endif +#include #include +#include #include #include @@ -39,12 +41,11 @@ void AccessController::AddPrivilege(const std::string& privilege) { privileges_.push_back(privilege); } -int AccessController::CheckPrivilege(GDBusConnection *connection, const char* sender_appid) { - Cynara c; - - if (c.FetchCredsFromDBus(connection, sender_appid) != 0 ) - return -1; +void AccessController::SetTrusted(const bool trusted) { + trusted_ = trusted; +} +int AccessController::CheckPrivilege(Cynara& c) { for (auto& privilege : privileges_) { if (c.Check(privilege) != 0) { return -1; @@ -54,6 +55,51 @@ int AccessController::CheckPrivilege(GDBusConnection *connection, const char* se return 0; } +int AccessController::CheckTrusted(const char* sender_appid) { + if (appid_.empty()) { + char appid[255]; + if (aul_app_get_appid_bypid(getpid(), appid, sizeof(appid)) < 0) + return -1; + + appid_ = appid; + } + + LOGD("CheckCertificate : %s :: %s", appid_.c_str(), sender_appid); + pkgmgrinfo_cert_compare_result_type_e res; + int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(appid_.c_str(), sender_appid, getuid(), &res); + if (ret < 0) { + LOGE("CheckCertificate() Failed"); + return -1; + } + if (res != PMINFO_CERT_COMPARE_MATCH) { + LOGE("CheckCertificate() Failed : MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH"); + return -1; + } + + return 0; +} + +int AccessController::Check(GDBusConnection* connection, const char* sender, + const char* sender_appid) { + Cynara c; + int ret = 0; + + if (c.FetchCredsFromDBus(connection, sender) != 0) + return -1; + + if (!privileges_.empty()) { + ret = CheckPrivilege(c); + if (ret) + return ret; + } + + if (trusted_) { + ret = CheckTrusted(sender_appid); + } + + return ret; +} + int AccessController::SetCache(const std::string& sender) { return -1; } @@ -77,7 +123,7 @@ AccessController::Cynara::~Cynara() { cynara_finish(cynara_); } -int AccessController::Cynara::FetchCredsFromDBus(GDBusConnection *connection, const char *sender_appid) { +int AccessController::Cynara::FetchCredsFromDBus(GDBusConnection* connection, const char* sender) { int ret; if (client_) { @@ -90,13 +136,13 @@ int AccessController::Cynara::FetchCredsFromDBus(GDBusConnection *connection, co user_ = nullptr; } - ret = cynara_creds_gdbus_get_user(connection, sender_appid, USER_METHOD_DEFAULT, &user_); + ret = cynara_creds_gdbus_get_user(connection, sender, USER_METHOD_DEFAULT, &user_); if (ret != CYNARA_API_SUCCESS) { LOGE("cynara_creds_gdbus_get_user() is failed : %d", ret); return -1; } - ret = cynara_creds_gdbus_get_client(connection, sender_appid, CLIENT_METHOD_DEFAULT, &client_); + ret = cynara_creds_gdbus_get_client(connection, sender, CLIENT_METHOD_DEFAULT, &client_); if (ret != CYNARA_API_SUCCESS) { LOGE("cynara_creds_gdbus_get_client() is failed : %d", ret); return -1; @@ -107,9 +153,9 @@ int AccessController::Cynara::FetchCredsFromDBus(GDBusConnection *connection, co } int AccessController::Cynara::Check(const std::string& privilege) { - LOGD("check %s", privilege.c_str()); + LOGD("check privilege %s", privilege.c_str()); if (cynara_check(cynara_, client_, "", user_, privilege.c_str()) != CYNARA_API_ACCESS_ALLOWED) { - LOGE("cynara_check() is failed : %s", privilege.c_str()); + LOGD("cynara_check() is not allowed : %s", privilege.c_str()); return -1; } diff --git a/src/ac-internal.h b/src/ac-internal.h index 1948ff0..9a9ae63 100644 --- a/src/ac-internal.h +++ b/src/ac-internal.h @@ -31,20 +31,20 @@ namespace internal { class AccessController { public: + AccessController(bool trusted = false) : trusted_(trusted) {} virtual ~AccessController(); void AddPrivilege(const std::string& privilege); - int CheckPrivilege(GDBusConnection *connection, const char* sender_appid); + void SetTrusted(const bool trusted); + int Check(GDBusConnection *connection, const char *sender, const char* sender_appid); private: - int SetCache(const std::string& sender); - class Cynara { public: Cynara(); ~Cynara(); - int FetchCredsFromDBus(GDBusConnection *connection, const char *sender_appid); + int FetchCredsFromDBus(GDBusConnection *connection, const char *sender); int Check(const std::string& privilege); private: @@ -53,9 +53,15 @@ class AccessController { char *user_; }; + int SetCache(const std::string& sender); + int CheckTrusted(const char *sender_appid); + int CheckPrivilege(Cynara& c); + private: std::vector privileges_; std::map cache_; + bool trusted_; + std::string appid_; }; } // namespace internal diff --git a/src/fdbroker-internal.cc b/src/fdbroker-internal.cc index 451ab34..ce59d32 100644 --- a/src/fdbroker-internal.cc +++ b/src/fdbroker-internal.cc @@ -225,7 +225,6 @@ int FdBroker::Send(const std::string& target_appid, GDBusMessage *msg; GDBusMessage *reply; GError *err = nullptr; - GVariant *body; GVariant *reply_body; SocketPair sock_pair(mock_); FdList fd_list; @@ -261,9 +260,7 @@ int FdBroker::Send(const std::string& target_appid, return -1; } - body = g_variant_new("(s)", sender_appid); g_dbus_message_set_unix_fd_list(msg, fd_list.GetRaw()); - g_dbus_message_set_body(msg, body); reply = g_dbus_connection_send_message_with_reply_sync(DBusConnectionManager::GetInst().GetConnection(), msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 500, nullptr, nullptr, &err); @@ -298,21 +295,13 @@ int FdBroker::Send(const std::string& target_appid, return fd; } -void FdBroker::ReceiveMessage(GVariant* parameters, +void FdBroker::ReceiveMessage(const char* sender_appid, GDBusMethodInvocation* invocation) { - char* sender_appid = nullptr; GDBusMessage* msg; GUnixFDList* fd_list; int fd_len; int* returned_fds = nullptr; - g_variant_get(parameters, "(&s)", &sender_appid); - - if (sender_appid == nullptr) { - LOGE("Invalid argument : sender_appid is NULL"); - return; - } - msg = g_dbus_method_invocation_get_message(invocation); fd_list = g_dbus_message_get_unix_fd_list(msg); @@ -335,12 +324,20 @@ void FdBroker::OnReceiveDbusMethod(GDBusConnection *conn, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { FdBroker* broker = static_cast(user_data); - int ret; + int ret = -1; + char sender_appid[255]; + int sender_pid; + + sender_pid = broker->GetSenderPid(conn, sender); + if (aul_app_get_appid_bypid(sender_pid, sender_appid, sizeof(sender_appid)) < 0) { + g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret)); + return; + } AccessController& ac = broker->GetAccessController(); - ret = ac.CheckPrivilege(conn, sender); + ret = ac.Check(conn, sender, sender_appid); if (ret == 0) - broker->ReceiveMessage(parameters, invocation); + broker->ReceiveMessage(sender_appid, invocation); g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret)); } @@ -386,6 +383,44 @@ int FdBroker::GetOwnerId(const std::string& interface_name) { return owner_id; } +int FdBroker::GetSenderPid(GDBusConnection *connection, const gchar *sender) { + GDBusMessage *msg = NULL; + GDBusMessage *reply = NULL; + GError *err = NULL; + GVariant *body; + int pid = 0; + + msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus", + "org.freedesktop.DBus", "GetConnectionUnixProcessID"); + if (!msg) { + LOGE("Can't allocate new method call"); + goto out; + } + + g_dbus_message_set_body(msg, g_variant_new("(s)", sender)); + reply = g_dbus_connection_send_message_with_reply_sync(connection, msg, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err); + + if (!reply) { + if (err != NULL) { + LOGE("Failed to get pid [%s]", err->message); + g_error_free(err); + } + goto out; + } + + body = g_dbus_message_get_body(reply); + g_variant_get(body, "(u)", &pid); + +out: + if (msg) + g_object_unref(msg); + if (reply) + g_object_unref(reply); + + return pid; +} + int FdBroker::RegisterDbusInterface(const std::string& port_name) { static const GDBusInterfaceVTable interface_vtable = { OnReceiveDbusMethod, @@ -398,7 +433,6 @@ int FdBroker::RegisterDbusInterface(const std::string& port_name) { static const char introspection_postfix[] = "'>" " " - " " " " " " " " diff --git a/src/fdbroker-internal.h b/src/fdbroker-internal.h index 77ff32d..b5fba79 100644 --- a/src/fdbroker-internal.h +++ b/src/fdbroker-internal.h @@ -143,8 +143,9 @@ class FdBroker { GDBusMethodInvocation *invocation, gpointer user_data); int GetOwnerId(const std::string& interface_name); + int GetSenderPid(GDBusConnection *connection, const gchar *sender); int RegisterDbusInterface(const std::string& port_name); - void ReceiveMessage(GVariant* parameters, GDBusMethodInvocation* invocation); + void ReceiveMessage(const char* sender_appid, GDBusMethodInvocation* invocation); std::string GetInterfaceName(const std::string& target_appid, const std::string& port_name); static void OnNameAppeared(GDBusConnection *connection, diff --git a/src/rpc-port.cc b/src/rpc-port.cc index 5c81f93..3c9e142 100755 --- a/src/rpc-port.cc +++ b/src/rpc-port.cc @@ -331,6 +331,19 @@ RPC_API int rpc_port_stub_add_privilege(rpc_port_stub_h h, return 0; } +RPC_API int rpc_port_stub_set_trusted(rpc_port_stub_h h, + const bool trusted) { + if (h == nullptr) + return -1; + + auto p = static_cast<::StubExt*>(h); + std::lock_guard lock(p->GetMutex()); + + p->SetTrusted(trusted); + return 0; +} + + RPC_API int rpc_port_stub_add_connected_event_cb(rpc_port_stub_h h, rpc_port_stub_connected_event_cb cb, void* data) { if (h == nullptr) diff --git a/src/stub-internal.cc b/src/stub-internal.cc index 18a2dbb..c981ba5 100644 --- a/src/stub-internal.cc +++ b/src/stub-internal.cc @@ -55,6 +55,11 @@ void Stub::AddPrivilege(const std::string& privilege) { ac.AddPrivilege(privilege); } +void Stub::SetTrusted(const bool trusted) { + AccessController& ac = fd_broker_.GetAccessController(); + ac.SetTrusted(trusted); +} + gboolean Stub::OnDataReceived(GIOChannel *gio, GIOCondition cond, gpointer data) { Stub* stub = static_cast(data); diff --git a/src/stub-internal.h b/src/stub-internal.h index 5819428..ab89aa3 100644 --- a/src/stub-internal.h +++ b/src/stub-internal.h @@ -48,6 +48,7 @@ class Stub : private FdBroker::IEventListener { void Listen(IEventListener* ev); void AddPrivilege(const std::string& privilege); + void SetTrusted(const bool trusted); private: class AcceptedPort : public Port { -- 2.7.4