From d05adbc69eed15aa9b66aad89ee14e1779adb9c0 Mon Sep 17 00:00:00 2001 From: Slava Monich Date: Wed, 6 Nov 2019 02:07:40 +0300 Subject: [PATCH] [mms-engine] D-Bus access control. JB#46060 By default, only privileged and sailfish-mms groups (effective or primary) are allowed to call most D-Bus methods. D-Bus access rules can be configured by adding [DBus] section to /etc/mms-engine.conf config file: [DBus] MmsEngineAccess=... TransferAccess=... TransferListAccess=... The default rules are: MmsEngineAccess: (!group(privileged))&(!group(sailfish-mms))&(cancel()|receiveMessage()| sendReadReport()|sendMessage()|push()|pushNotify()|setLogLevel()| setLogType()|migrateSettings())=deny TransferAccess: (!group(privileged))&(!group(sailfish-mms))&Get()=deny TransferListAccess: (!group(privileged))&(!group(sailfish-mms))&(GetAll()|EnableUpdates()| DisableUpdates()|GetSendProgress()|GetReceiveProgress())=deny --- mms-engine/Makefile | 2 +- mms-engine/main.c | 253 +++++++++++++- mms-engine/mms-engine.pro | 2 +- mms-engine/mms_engine.c | 330 +++++++++++------- mms-engine/mms_engine.h | 40 ++- mms-lib/include/mms_settings.h | 11 +- mms-lib/src/mms_settings.c | 24 +- mms-transfer-list-dbus/Makefile | 2 +- .../include/mms_transfer_list_dbus.h | 38 +- .../mms-transfer-list-dbus.pro | 2 +- .../src/mms_transfer_dbus.c | 184 ++++++---- .../src/mms_transfer_dbus.h | 9 +- .../src/mms_transfer_list_dbus.c | 112 +++--- rpm/mms-engine.spec | 4 +- 14 files changed, 752 insertions(+), 261 deletions(-) diff --git a/mms-engine/Makefile b/mms-engine/Makefile index cfd095e..97ef940 100644 --- a/mms-engine/Makefile +++ b/mms-engine/Makefile @@ -17,7 +17,7 @@ include ../mms-lib/Config.mak # Required packages # -PKGS = gio-unix-2.0 gio-2.0 libglibutil +PKGS = gio-unix-2.0 gio-2.0 libdbusaccess libglibutil LIB_PKGS = libwspcodec gmime-2.6 libgofono libsoup-2.4 dconf ifdef SAILFISH diff --git a/mms-engine/main.c b/mms-engine/main.c index 3f4babc..a4121a3 100644 --- a/mms-engine/main.c +++ b/mms-engine/main.c @@ -1,6 +1,7 @@ /* - * Copyright (C) 2013-2018 Jolla Ltd. - * Copyright (C) 2013-2018 Slava Monich + * Copyright (C) 2013-2019 Jolla Ltd. + * Copyright (C) 2013-2019 Slava Monich + * Copyright (C) 2019 Open Mobile Platform LLC. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -20,23 +21,123 @@ #include "mms_lib_util.h" #include "mms_settings.h" +#include "mms_transfer_list_dbus.h" + #ifdef SAILFISH # include "mms_connman_nemo_log.h" #else # include "mms_connman_ofono_log.h" #endif +#include #include #define RET_OK (0) #define RET_ERR (1) +typedef struct mms_app_dbus_policy { + const char* spec; + const DA_ACTION* actions; +} MMSAppDBusPolicy; + +#define RADIO_USER "radio" /* ofono */ +#define RADIO_GROUP "radio" + +#define PRIVILEGED_GROUP "privileged" /* commhistoryd */ +#define MMS_GROUP "sailfish-mms" + +/* org.nemomobile.MmsEngine */ +#define MMS_ENGINE_DBUS_METHOD_CANCEL "cancel" +#define MMS_ENGINE_DBUS_METHOD_RECEIVE_MESSAGE "receiveMessage" +#define MMS_ENGINE_DBUS_METHOD_SEND_READ_REPORT "sendReadReport" +#define MMS_ENGINE_DBUS_METHOD_SEND_MESSAGE "sendMessage" +#define MMS_ENGINE_DBUS_METHOD_PUSH "push" +#define MMS_ENGINE_DBUS_METHOD_PUSH_NOTIFY "pushNotify" +#define MMS_ENGINE_DBUS_METHOD_SET_LOG_LEVEL "setLogLevel" +#define MMS_ENGINE_DBUS_METHOD_SET_LOG_TYPE "setLogType" +#define MMS_ENGINE_DBUS_METHOD_GET_VERSION "getVersion" +#define MMS_ENGINE_DBUS_METHOD_MIGRATE_SETTINGS "migrateSettings" + +static const DA_ACTION mms_engine_dbus_actions[] = { + #define INIT_DA_ACTION(id) \ + {MMS_ENGINE_DBUS_METHOD_##id, MMS_ENGINE_ACTION_##id, 0}, + MMS_ENGINE_DBUS_METHODS(INIT_DA_ACTION) + #undef INIT_DA_ACTION + { NULL } +}; + +static const MMSAppDBusPolicy mms_engine_default_dbus_policy = { + "((!group("PRIVILEGED_GROUP"))&(!group("MMS_GROUP"))&(" + MMS_ENGINE_DBUS_METHOD_CANCEL "()|" + MMS_ENGINE_DBUS_METHOD_RECEIVE_MESSAGE "()|" + MMS_ENGINE_DBUS_METHOD_SEND_READ_REPORT"()|" + MMS_ENGINE_DBUS_METHOD_SEND_MESSAGE"()|" + MMS_ENGINE_DBUS_METHOD_SET_LOG_LEVEL"()|" + MMS_ENGINE_DBUS_METHOD_SET_LOG_TYPE"()|" + MMS_ENGINE_DBUS_METHOD_MIGRATE_SETTINGS"()))|" + "((!(user("RADIO_USER")&group("RADIO_GROUP")))&(" + MMS_ENGINE_DBUS_METHOD_PUSH"()|" + MMS_ENGINE_DBUS_METHOD_PUSH_NOTIFY "()))=deny", + mms_engine_dbus_actions +}; + +/* org.nemomobile.MmsEngine.TransferList */ +#define MMS_TRANSFER_LIST_DBUS_METHOD_GET "Get" + +static const DA_ACTION mms_tx_list_dbus_actions[] = { + #define INIT_DA_ACTION(id) \ + {MMS_TRANSFER_LIST_DBUS_METHOD_##id, \ + MMS_TRANSFER_LIST_ACTION_##id, 0}, + MMS_TRANSFER_LIST_DBUS_METHODS(INIT_DA_ACTION) + #undef INIT_DA_ACTION + { NULL } +}; + +static const MMSAppDBusPolicy mms_tx_list_default_dbus_policy = { + "(!group("PRIVILEGED_GROUP"))&(!group("MMS_GROUP"))&" + MMS_TRANSFER_LIST_DBUS_METHOD_GET "()=deny", + mms_tx_list_dbus_actions +}; + +/* org.nemomobile.MmsEngine.Transfer */ +#define MMS_TRANSFER_DBUS_METHOD_GET_ALL "GetAll" +#define MMS_TRANSFER_DBUS_METHOD_ENABLE_UPDATES "EnableUpdates" +#define MMS_TRANSFER_DBUS_METHOD_DISABLE_UPDATES "DisableUpdates" +#define MMS_TRANSFER_DBUS_METHOD_GET_INTERFACE_VERSION "GetInterfaceVersion" +#define MMS_TRANSFER_DBUS_METHOD_GET_SEND_PROGRESS "GetSendProgress" +#define MMS_TRANSFER_DBUS_METHOD_GET_RECEIVE_PROGRESS "GetReceiveProgress" + +static const DA_ACTION mms_tx_dbus_actions[] = { + #define INIT_DA_ACTION(id) \ + {MMS_TRANSFER_DBUS_METHOD_##id, MMS_TRANSFER_ACTION_##id, 0}, + MMS_TRANSFER_DBUS_METHODS(INIT_DA_ACTION) + #undef INIT_DA_ACTION + { NULL } +}; + +static const MMSAppDBusPolicy mms_tx_default_dbus_policy = { + "(!group("PRIVILEGED_GROUP"))&(!group("MMS_GROUP"))&(" + MMS_TRANSFER_DBUS_METHOD_GET_ALL "()|" + MMS_TRANSFER_DBUS_METHOD_ENABLE_UPDATES"()|" + MMS_TRANSFER_DBUS_METHOD_DISABLE_UPDATES"()|" + MMS_TRANSFER_DBUS_METHOD_GET_SEND_PROGRESS"()|" + MMS_TRANSFER_DBUS_METHOD_GET_RECEIVE_PROGRESS"())=deny", + mms_tx_dbus_actions +}; + +/* Config groups and keys */ +static const char SETTINGS_DBUS_GROUP[] = "DBus"; +static const char SETTINGS_DBUS_TYPE[] = "Bus"; +static const char SETTINGS_DBUS_ENGINE_ACCESS[] = "MmsEngineAccess"; +static const char SETTINGS_DBUS_TRANSFER_ACCESS[] = "TransferAccess"; +static const char SETTINGS_DBUS_TRANSFER_LIST_ACCESS[] = "TransferListAccess"; + /* Options configurable from the command line */ typedef struct mms_app_options { - GBusType bus_type; int flags; MMSConfigCopy global; MMSSettingsSimDataCopy settings; + MMSEngineDbusConfig dbus; } MMSAppOptions; /* All known log modules */ @@ -46,6 +147,7 @@ static MMSLogModule* mms_app_log_modules[] = { MMS_LIB_LOG_MODULES(MMS_LIB_LOG_MODULE) MMS_CONNMAN_LOG_MODULES(MMS_LIB_LOG_MODULE) #undef MMS_LIB_LOG_MODULE + NULL }; /* Signal handler */ @@ -109,8 +211,10 @@ mms_app_option_loglevel( gpointer data, GError** error) { - return gutil_log_parse_option(value, mms_app_log_modules, - G_N_ELEMENTS(mms_app_log_modules), error); + int count = 0; + MMSLogModule** ptr = mms_app_log_modules; + while (*ptr++) count++; + return gutil_log_parse_option(value, mms_app_log_modules, count, error); } static @@ -144,6 +248,116 @@ mms_app_option_verbose( return TRUE; } +/* Load settings from config file */ + +static +DAPolicy* +mms_app_dbus_policy_new( + const MMSAppDBusPolicy* policy) +{ + if (policy) { + DAPolicy* access = da_policy_new_full(policy->spec, policy->actions); + + if (access) { + return access; + } + GWARN("Invalid D-Bus policy \"%s\"", policy->spec); + } + return NULL; +} + +static +DAPolicy* +mms_app_dbus_config_update( + DAPolicy* current_policy, + GKeyFile* file, + const char* group, + const char* key, + const MMSAppDBusPolicy* default_policy) +{ + char* value = g_key_file_get_string(file, group, key, NULL); + DAPolicy* policy = NULL; + + if (value) { + policy = da_policy_new_full(value, default_policy->actions); + if (policy) { + GDEBUG("Using %s policy \"%s\"", key, value); + } else { + GWARN("Invalid %s policy \"%s\"", key, value); + } + g_free(value); + } + if (policy) { + da_policy_unref(current_policy); + return policy; + } else if (!current_policy) { + return mms_app_dbus_policy_new(default_policy); + } else { + return current_policy; + } +} + +static +void +mms_app_dbus_config_init( + MMSEngineDbusConfig* dbus) +{ + dbus->engine_access = + mms_app_dbus_policy_new(&mms_engine_default_dbus_policy); + dbus->tx_list_access = + mms_app_dbus_policy_new(&mms_tx_list_default_dbus_policy); + dbus->tx_access = + mms_app_dbus_policy_new(&mms_tx_default_dbus_policy); +} + +static +void +mms_app_dbus_config_clear( + MMSEngineDbusConfig* dbus) +{ + da_policy_unref(dbus->engine_access); + da_policy_unref(dbus->tx_list_access); + da_policy_unref(dbus->tx_access); +} + +static +void +mms_app_dbus_config_parse( + GKeyFile* file, + MMSEngineDbusConfig* dbus) +{ + const char* group = SETTINGS_DBUS_GROUP; + + dbus->engine_access = mms_app_dbus_config_update(dbus->engine_access, + file, group, SETTINGS_DBUS_ENGINE_ACCESS, + &mms_engine_default_dbus_policy); + dbus->tx_list_access = mms_app_dbus_config_update(dbus->tx_list_access, + file, group, SETTINGS_DBUS_TRANSFER_LIST_ACCESS, + &mms_tx_list_default_dbus_policy); + dbus->tx_access = mms_app_dbus_config_update(dbus->tx_access, + file, group, SETTINGS_DBUS_TRANSFER_ACCESS, + &mms_tx_default_dbus_policy); +} + +static +gboolean +mms_app_config_load( + const char* config_file, + MMSAppOptions* opt, + GError** error) +{ + GKeyFile* file = g_key_file_new(); + gboolean ok = g_key_file_load_from_file(file, config_file, 0, error); + + if (ok) { + GDEBUG("Loading %s", config_file); + mms_settings_parse(file, &opt->global, &opt->settings); + mms_app_dbus_config_parse(file, &opt->dbus); + } + g_key_file_free(file); + return ok; +} + /** * Parses command line and sets up application options. Returns TRUE if * we should go ahead and run the application, FALSE if we should exit @@ -218,7 +432,7 @@ mms_app_parse_options( { "attic", 'a', 0, G_OPTION_ARG_NONE, &opt->global.config.attic_enabled, "Store unrecognized push messages in the attic", NULL }, -#define OPT_VERBOSE_INDEX 12 +#define OPT_VERBOSE_INDEX 13 { "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, mms_app_option_verbose, "Be verbose (equivalent to -l=verbose)", NULL }, @@ -270,13 +484,11 @@ mms_app_parse_options( if (ok) { if (config_file) { /* Config file was specified on the command line */ - ok = mms_settings_load_defaults(config_file, - &opt->global, &opt->settings, &error); + ok = mms_app_config_load(config_file, opt, &error); } else { /* The default config file may be (and usually is) missing */ if (g_file_test(MMS_ENGINE_CONFIG_FILE, G_FILE_TEST_EXISTS)) { - mms_settings_load_defaults(MMS_ENGINE_CONFIG_FILE, - &opt->global, &opt->settings, NULL); + mms_app_config_load(MMS_ENGINE_CONFIG_FILE, opt, NULL); } } if (ok) { @@ -305,9 +517,12 @@ mms_app_parse_options( g_error_free(error); *result = RET_ERR; } else if (log_modules) { - unsigned int i; - for (i=0; iname); + MMSLogModule** ptr = mms_app_log_modules; + + while (*ptr) { + MMSLogModule* log = *ptr++; + + printf("%s\n", log->name); } *result = RET_OK; ok = FALSE; @@ -351,10 +566,10 @@ mms_app_parse_options( if (keep_running) opt->flags |= MMS_ENGINE_FLAG_KEEP_RUNNING; if (session_bus) { GDEBUG("Attaching to session bus"); - opt->bus_type = G_BUS_TYPE_SESSION; + opt->dbus.type = G_BUS_TYPE_SESSION; } else { GDEBUG("Attaching to system bus"); - opt->bus_type = G_BUS_TYPE_SYSTEM; + opt->dbus.type = G_BUS_TYPE_SYSTEM; } *result = RET_OK; } @@ -378,12 +593,13 @@ int main(int argc, char* argv[]) memset(&opt, 0, sizeof(opt)); mms_lib_default_config(config); mms_settings_sim_data_default(settings); + mms_app_dbus_config_init(&opt.dbus); if (mms_app_parse_options(&opt, argc, argv, &result)) { MMSEngine* engine; /* Create engine instance. This may fail */ - engine = mms_engine_new(config, settings, opt.flags, - mms_app_log_modules, G_N_ELEMENTS(mms_app_log_modules)); + engine = mms_engine_new(config, settings, &opt.dbus, + mms_app_log_modules, opt.flags); if (engine) { /* Setup main loop */ @@ -392,7 +608,7 @@ int main(int argc, char* argv[]) guint sigint = g_unix_signal_add(SIGINT, mms_app_signal, engine); /* Acquire name, don't allow replacement */ - guint name_id = g_bus_own_name(opt.bus_type, MMS_ENGINE_SERVICE, + guint name_id = g_bus_own_name(opt.dbus.type, MMS_ENGINE_SERVICE, G_BUS_NAME_OWNER_FLAGS_REPLACE, mms_app_bus_acquired, mms_app_name_acquired, mms_app_name_lost, engine, NULL); @@ -413,6 +629,7 @@ int main(int argc, char* argv[]) } g_free(opt.global.root_dir); mms_settings_sim_data_reset(&opt.settings); + mms_app_dbus_config_clear(&opt.dbus); mms_lib_deinit(); return result; } diff --git a/mms-engine/mms-engine.pro b/mms-engine/mms-engine.pro index d81ca4c..fb92da4 100644 --- a/mms-engine/mms-engine.pro +++ b/mms-engine/mms-engine.pro @@ -1,7 +1,7 @@ TEMPLATE = app CONFIG += link_pkgconfig PKGCONFIG += gmime-2.6 gio-unix-2.0 gio-2.0 glib-2.0 libsoup-2.4 dconf -PKGCONFIG += libwspcodec libgofono libglibutil +PKGCONFIG += libwspcodec libgofono libdbusaccess libglibutil QMAKE_CFLAGS += -Wno-unused-parameter include(../mms-lib/mms-lib-config.pri) diff --git a/mms-engine/mms_engine.c b/mms-engine/mms_engine.c index df1d648..89c3fd3 100644 --- a/mms-engine/mms_engine.c +++ b/mms-engine/mms_engine.c @@ -1,6 +1,7 @@ /* - * Copyright (C) 2013-2018 Jolla Ltd. - * Copyright (C) 2013-2018 Slava Monich + * Copyright (C) 2013-2019 Jolla Ltd. + * Copyright (C) 2013-2019 Slava Monich + * Copyright (C) 2019 Open Mobile Platform LLC. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -31,22 +32,18 @@ /* Generated code */ #include "org.nemomobile.MmsEngine.h" +#include +#include + #include #include #include -/* Signals D-Bus proxy */ +/* D-Bus proxy Signals */ enum mms_engine_dbus_methods { - MMS_ENGINE_METHOD_SEND_MESSAGE, - MMS_ENGINE_METHOD_PUSH, - MMS_ENGINE_METHOD_PUSH_NOTIFY, - MMS_ENGINE_METHOD_CANCEL, - MMS_ENGINE_METHOD_RECEIVE_MESSAGE, - MMS_ENGINE_METHOD_SEND_READ_REPORT, - MMS_ENGINE_METHOD_SET_LOG_LEVEL, - MMS_ENGINE_METHOD_SET_LOG_TYPE, - MMS_ENGINE_METHOD_GET_VERSION, - MMS_ENGINE_METHOD_MIGRATE_SETTINGS, + #define MMS_ENGINE_METHOD_(id) MMS_ENGINE_METHOD_##id, + MMS_ENGINE_DBUS_METHODS(MMS_ENGINE_METHOD_) + #undef MMS_ENGINE_METHOD_ MMS_ENGINE_METHOD_COUNT }; @@ -58,7 +55,8 @@ struct mms_engine { MMSDispatcher* dispatcher; MMSDispatcherDelegate dispatcher_delegate; MMSLogModule** log_modules; - int log_count; + DAPolicy* dbus_access; + DA_BUS da_bus; GDBusConnection* engine_bus; OrgNemomobileMmsEngine* proxy; GMainLoop* loop; @@ -135,6 +133,31 @@ mms_engine_idle_timer_check( } } +static +gboolean +mms_engine_dbus_access_allowed( + MMSEngine* engine, + GDBusMethodInvocation* call, + MMS_ENGINE_ACTION action) +{ + const char* sender = g_dbus_method_invocation_get_sender(call); + DAPeer* peer = da_peer_get(engine->da_bus, sender); + + if (peer && da_policy_check(engine->dbus_access, &peer->cred, action, 0, + DA_ACCESS_ALLOW) == DA_ACCESS_ALLOW) { + return TRUE; + } else { + const char* iface = g_dbus_method_invocation_get_interface_name(call); + const char* method = g_dbus_method_invocation_get_method_name(call); + + GWARN("Client %s is not allowed to call %s.%s", sender, iface, method); + g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "Client %s is not allowed to call %s.%s", + sender, iface, method); + return FALSE; + } +} + /* org.nemomobile.MmsEngine.sendMessage */ static gboolean @@ -151,7 +174,10 @@ mms_engine_handle_send_message( GVariant* attachments, MMSEngine* engine) { - if (to && *to) { + if (!mms_engine_dbus_access_allowed(engine, call, + MMS_ENGINE_ACTION_SEND_MESSAGE)) { + /* mms_engine_dbus_access_allowed has completed the call */ + } else if (to && *to) { unsigned int i; char* to_list = g_strjoinv(",", (char**)to); char* cc_list = NULL; @@ -229,27 +255,31 @@ mms_engine_handle_receive_message( GVariant* data, MMSEngine* engine) { - gsize len = 0; - const guint8* bytes = g_variant_get_fixed_array(data, &len, 1); - GDEBUG("Processing push %u bytes from %s", (guint)len, imsi); - if (imsi && bytes && len) { - char* id = g_strdup_printf("%d", database_id); - GBytes* push = g_bytes_new(bytes, len); - GError* error = NULL; - if (mms_dispatcher_receive_message(engine->dispatcher, id, imsi, - automatic, push, &error)) { - mms_dispatcher_start(engine->dispatcher); - org_nemomobile_mms_engine_complete_receive_message(proxy, call); + /* mms_engine_dbus_access_allowed completes the call if access is denied */ + if (mms_engine_dbus_access_allowed(engine, call, + MMS_ENGINE_ACTION_RECEIVE_MESSAGE)) { + gsize len = 0; + const guint8* bytes = g_variant_get_fixed_array(data, &len, 1); + GDEBUG("Processing push %u bytes from %s", (guint)len, imsi); + if (imsi && bytes && len) { + char* id = g_strdup_printf("%d", database_id); + GBytes* push = g_bytes_new(bytes, len); + GError* error = NULL; + if (mms_dispatcher_receive_message(engine->dispatcher, id, imsi, + automatic, push, &error)) { + mms_dispatcher_start(engine->dispatcher); + org_nemomobile_mms_engine_complete_receive_message(proxy, call); + } else { + g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "%s", GERRMSG(error)); + g_error_free(error); + } + g_bytes_unref(push); + g_free(id); } else { g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, "%s", GERRMSG(error)); - g_error_free(error); + G_DBUS_ERROR_FAILED, "Invalid parameters"); } - g_bytes_unref(push); - g_free(id); - } else { - g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, "Invalid parameters"); } mms_engine_idle_timer_check(engine); return TRUE; @@ -268,20 +298,24 @@ mms_engine_handle_send_read_report( int read_status, /* 0: Read 1: Deleted without reading */ MMSEngine* engine) { - GError* error = NULL; - char* id = g_strdup_printf("%d", database_id); - GDEBUG_("%s %s %s %s %d", id, imsi, message_id, to, read_status); - if (mms_dispatcher_send_read_report(engine->dispatcher, id, imsi, - message_id, to, (read_status == 1) ? MMS_READ_STATUS_DELETED : - MMS_READ_STATUS_READ, &error)) { - mms_dispatcher_start(engine->dispatcher); - org_nemomobile_mms_engine_complete_send_read_report(proxy, call); - } else { - g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, "%s", GERRMSG(error)); - g_error_free(error); + /* mms_engine_dbus_access_allowed completes the call if access is denied */ + if (mms_engine_dbus_access_allowed(engine, call, + MMS_ENGINE_ACTION_SEND_READ_REPORT)) { + GError* error = NULL; + char* id = g_strdup_printf("%d", database_id); + GDEBUG_("%s %s %s %s %d", id, imsi, message_id, to, read_status); + if (mms_dispatcher_send_read_report(engine->dispatcher, id, imsi, + message_id, to, (read_status == 1) ? MMS_READ_STATUS_DELETED : + MMS_READ_STATUS_READ, &error)) { + mms_dispatcher_start(engine->dispatcher); + org_nemomobile_mms_engine_complete_send_read_report(proxy, call); + } else { + g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "%s", GERRMSG(error)); + g_error_free(error); + } + g_free(id); } - g_free(id); mms_engine_idle_timer_check(engine); return TRUE; } @@ -295,54 +329,85 @@ mms_engine_handle_cancel( int database_id, MMSEngine* engine) { - char* id = NULL; - if (database_id > 0) id = g_strdup_printf("%u", database_id); - GDEBUG_("%s", id); - mms_dispatcher_cancel(engine->dispatcher, id); - org_nemomobile_mms_engine_complete_cancel(proxy, call); - g_free(id); + /* mms_engine_dbus_access_allowed completes the call if access is denied */ + if (mms_engine_dbus_access_allowed(engine, call, + MMS_ENGINE_ACTION_CANCEL)) { + char* id = NULL; + if (database_id > 0) id = g_strdup_printf("%u", database_id); + GDEBUG_("%s", id); + mms_dispatcher_cancel(engine->dispatcher, id); + org_nemomobile_mms_engine_complete_cancel(proxy, call); + g_free(id); + } mms_engine_idle_timer_check(engine); return TRUE; } /* org.nemomobile.MmsEngine.pushNotify */ + static -gboolean -mms_engine_handle_push_notify( - OrgNemomobileMmsEngine* proxy, +void +mms_engine_push_handler( + MMSEngine* engine, GDBusMethodInvocation* call, const char* imsi, const char* type, GVariant* data, - MMSEngine* engine) + void (*complete)( + OrgNemomobileMmsEngine* proxy, + GDBusMethodInvocation* call)) { - gsize len = 0; - const guint8* bytes = g_variant_get_fixed_array(data, &len, 1); - GDEBUG("Received %u bytes from %s", (guint)len, imsi); if (!type || g_ascii_strcasecmp(type, MMS_CONTENT_TYPE)) { - GERR("Unsupported content type %s", type); + GERR_("Unsupported content type %s", type); g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Unsupported content type"); } else if (!imsi || !imsi[0]) { GERR_("IMSI is missing"); g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "IMSI is missing"); - } else if (!bytes || !len) { - GERR_("No data provided"); - g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, "No data provided"); } else { - GError* err = NULL; - GBytes* msg = g_bytes_new(bytes, len); - if (mms_dispatcher_handle_push(engine->dispatcher, imsi, msg, &err)) { - mms_dispatcher_start(engine->dispatcher); - org_nemomobile_mms_engine_complete_push(proxy, call); - } else { + gsize len = 0; + const guint8* bytes = g_variant_get_fixed_array(data, &len, 1); + + if (!bytes || !len) { + GERR_("No data provided"); g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, "%s", GERRMSG(err)); - g_error_free(err); + G_DBUS_ERROR_FAILED, "No data provided"); + } else { + GError* err = NULL; + MMSDispatcher* dispatcher = engine->dispatcher; + GBytes* msg = g_bytes_new_with_free_func(bytes, len, + (GDestroyNotify) g_variant_unref, g_variant_ref(data)); + + GDEBUG("Received %u bytes from %s", (guint)len, imsi); + if (mms_dispatcher_handle_push(dispatcher, imsi, msg, &err)) { + mms_dispatcher_start(dispatcher); + complete(engine->proxy, call); + } else { + g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "%s", GERRMSG(err)); + g_error_free(err); + } + g_bytes_unref(msg); } - g_bytes_unref(msg); + } +} + +static +gboolean +mms_engine_handle_push_notify( + OrgNemomobileMmsEngine* proxy, + GDBusMethodInvocation* call, + const char* imsi, + const char* type, + GVariant* data, + MMSEngine* engine) +{ + /* mms_engine_dbus_access_allowed completes the call if access is denied */ + if (mms_engine_dbus_access_allowed(engine, call, + MMS_ENGINE_ACTION_PUSH_NOTIFY)) { + mms_engine_push_handler(engine, call, imsi, type, data, + org_nemomobile_mms_engine_complete_push_notify); } mms_engine_idle_timer_check(engine); return TRUE; @@ -362,9 +427,16 @@ mms_engine_handle_push( int src_port, const char* type, GVariant* data, - MMSEngine* eng) + MMSEngine* engine) { - return mms_engine_handle_push_notify(proxy, call, imsi, type, data, eng); + /* mms_engine_dbus_access_allowed completes the call if access is denied */ + if (mms_engine_dbus_access_allowed(engine, call, + MMS_ENGINE_ACTION_PUSH)) { + mms_engine_push_handler(engine, call, imsi, type, data, + org_nemomobile_mms_engine_complete_push); + } + mms_engine_idle_timer_check(engine); + return TRUE; } /* org.nemomobile.MmsEngine.setLogLevel */ @@ -377,20 +449,26 @@ mms_engine_handle_set_log_level( gint level, MMSEngine* engine) { - GDEBUG_("%s:%d", module, level); - if (module && module[0]) { - int i; - for (i=0; ilog_count; i++) { - MMSLogModule* log = engine->log_modules[i]; - if (log->name && log->name[0] && !strcmp(log->name, module)) { - log->level = level; - break; + /* mms_engine_dbus_access_allowed completes the call if access is denied */ + if (mms_engine_dbus_access_allowed(engine, call, + MMS_ENGINE_ACTION_SET_LOG_LEVEL)) { + GDEBUG_("%s:%d", module, level); + if (module && module[0]) { + MMSLogModule** ptr = engine->log_modules; + + while (*ptr) { + MMSLogModule* log = *ptr++; + + if (log->name && log->name[0] && !strcmp(log->name, module)) { + log->level = level; + break; + } } + } else { + gutil_log_default.level = level; } - } else { - gutil_log_default.level = level; + org_nemomobile_mms_engine_complete_set_log_level(proxy, call); } - org_nemomobile_mms_engine_complete_set_log_level(proxy, call); mms_engine_idle_timer_check(engine); return TRUE; } @@ -404,9 +482,13 @@ mms_engine_handle_set_log_type( const char* type, MMSEngine* engine) { - GDEBUG_("%s", type); - gutil_log_set_type(type, MMS_APP_LOG_PREFIX); - org_nemomobile_mms_engine_complete_set_log_type(proxy, call); + /* mms_engine_dbus_access_allowed completes the call if access is denied */ + if (mms_engine_dbus_access_allowed(engine, call, + MMS_ENGINE_ACTION_SET_LOG_TYPE)) { + GDEBUG_("%s", type); + gutil_log_set_type(type, MMS_APP_LOG_PREFIX); + org_nemomobile_mms_engine_complete_set_log_type(proxy, call); + } mms_engine_idle_timer_check(engine); return TRUE; } @@ -419,21 +501,25 @@ mms_engine_handle_get_version( GDBusMethodInvocation* call, MMSEngine* engine) { + /* mms_engine_dbus_access_allowed completes the call if access is denied */ + if (mms_engine_dbus_access_allowed(engine, call, + MMS_ENGINE_ACTION_GET_VERSION)) { #ifdef MMS_VERSION_STRING - int v1 = 0, v2 = 0, v3 = 0; - char* s = g_malloc(strlen(MMS_VERSION_STRING)+1); - s[0] = 0; - if (sscanf(MMS_VERSION_STRING, "%d.%d.%d%s", &v1, &v2, &v3, s) < 3) { - GWARN_("unable to parse version %s", MMS_VERSION_STRING); - } else { - GDEBUG_("version %d.%d.%d%s", v1, v2, v3, s); - } - org_nemomobile_mms_engine_complete_get_version(proxy, call, v1, v2, v3, s); - g_free(s); + int v1 = 0, v2 = 0, v3 = 0; + char* s = g_malloc(strlen(MMS_VERSION_STRING)+1); + s[0] = 0; + if (sscanf(MMS_VERSION_STRING, "%d.%d.%d%s", &v1, &v2, &v3, s) < 3) { + GWARN_("unable to parse version %s", MMS_VERSION_STRING); + } else { + GDEBUG_("version %d.%d.%d%s", v1, v2, v3, s); + } + org_nemomobile_mms_engine_complete_get_version(proxy, call, v1, v2, v3, s); + g_free(s); #else - GDEBUG_("oops"); - org_nemomobile_mms_engine_complete_get_version(proxy, call, 0, 0, 0, ""); + GDEBUG_("oops"); + org_nemomobile_mms_engine_complete_get_version(proxy, call, 0, 0, 0, ""); #endif + } mms_engine_idle_timer_check(engine); return TRUE; } @@ -447,18 +533,22 @@ mms_engine_handle_migrate_settings( const char* imsi, MMSEngine* engine) { - char* tmp = NULL; - /* Querying settings will migrate per-SIM settings after upgrading - * from 1.0.21 or older version of mms-engine */ - GDEBUG_("%s", imsi); - if (!imsi || !imsi[0]) { - imsi = tmp = mms_connman_default_imsi(engine->cm); - } - if (imsi) { - mms_settings_get_sim_data(engine->settings, imsi); + /* mms_engine_dbus_access_allowed completes the call if access is denied */ + if (mms_engine_dbus_access_allowed(engine, call, + MMS_ENGINE_ACTION_MIGRATE_SETTINGS)) { + char* tmp = NULL; + /* Querying settings will migrate per-SIM settings after upgrading + * from 1.0.21 or older version of mms-engine */ + GDEBUG_("%s", imsi); + if (!imsi || !imsi[0]) { + imsi = tmp = mms_connman_default_imsi(engine->cm); + } + if (imsi) { + mms_settings_get_sim_data(engine->settings, imsi); + } + org_nemomobile_mms_engine_complete_migrate_settings(proxy, call); + g_free(tmp); } - org_nemomobile_mms_engine_complete_migrate_settings(proxy, call); - g_free(tmp); mms_engine_idle_timer_check(engine); return TRUE; } @@ -467,16 +557,18 @@ MMSEngine* mms_engine_new( const MMSConfig* config, const MMSSettingsSimData* defaults, - unsigned int flags, - MMSLogModule* log_modules[], - int log_count) + const MMSEngineDbusConfig* dbus, + MMSLogModule* log_modules[], /* NULL terminated */ + unsigned int flags) { MMSConnMan* cm = mms_connman_new(); if (cm) { MMSEngine* mms = g_object_new(MMS_TYPE_ENGINE, NULL); MMSHandler* handler = mms_handler_dbus_new(); MMSSettings* settings = mms_settings_dconf_new(config, defaults); - MMSTransferList* txlist = mms_transfer_list_dbus_new(); + MMSTransferList* txlist = mms_transfer_list_dbus_new + (dbus->tx_list_access, dbus->tx_access); + static const struct _mms_engine_settings_flags_map { #define MAP_(x) \ MMS_ENGINE_FLAG_OVERRIDE_##x, \ @@ -511,7 +603,10 @@ mms_engine_new( mms->config = config; mms->settings = settings; mms->log_modules = log_modules; - mms->log_count = log_count; + mms->dbus_access = da_policy_ref(dbus->engine_access); + mms->da_bus = (dbus->type == G_BUS_TYPE_SESSION) ? + DA_BUS_SESSION : DA_BUS_SYSTEM; + mms->proxy = org_nemomobile_mms_engine_skeleton_new(); mms->proxy_signal_id[MMS_ENGINE_METHOD_SEND_MESSAGE] = g_signal_connect(mms->proxy, "handle-send-message", @@ -682,6 +777,7 @@ mms_engine_dispose( mms_connman_unref(mms->cm); mms->cm = NULL; } + da_policy_unref(mms->dbus_access); G_OBJECT_CLASS(mms_engine_parent_class)->dispose(object); } diff --git a/mms-engine/mms_engine.h b/mms-engine/mms_engine.h index 9344452..822d71e 100644 --- a/mms-engine/mms_engine.h +++ b/mms-engine/mms_engine.h @@ -1,6 +1,7 @@ /* - * Copyright (C) 2013-2016 Jolla Ltd. - * Contact: Slava Monich + * Copyright (C) 2013-2019 Jolla Ltd. + * Copyright (C) 2013-2019 Slava Monich + * Copyright (C) 2019 Open Mobile Platform LLC. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,6 +17,8 @@ #define JOLLA_MMS_ENGINE_H #include +#include + #include "mms_settings.h" #include "mms_version.h" @@ -35,15 +38,42 @@ # define MMS_ENGINE_CONFIG_FILE "/etc/mms-engine.conf" #endif /* MMS_ENGINE_CONFIG_FILE */ +#define MMS_ENGINE_DBUS_METHODS(m) \ + m(CANCEL) \ + m(RECEIVE_MESSAGE) \ + m(SEND_READ_REPORT) \ + m(SEND_MESSAGE) \ + m(PUSH) \ + m(PUSH_NOTIFY) \ + m(SET_LOG_LEVEL) \ + m(SET_LOG_TYPE) \ + m(GET_VERSION) \ + m(MIGRATE_SETTINGS) + +typedef enum mms_engine_action { + /* Action ids must be non-zero, shift those by one */ + MMS_ENGINE_ACTION_NONE = 0, + #define MMS_ENGINE_ACTION_(id) MMS_ENGINE_ACTION_##id, + MMS_ENGINE_DBUS_METHODS(MMS_ENGINE_ACTION_) + #undef MMS_ENGINE_ACTION_ +} MMS_ENGINE_ACTION; + typedef struct mms_engine MMSEngine; +typedef struct engine_dbus_config { + GBusType type; + DAPolicy* engine_access; + DAPolicy* tx_list_access; + DAPolicy* tx_access; +} MMSEngineDbusConfig; + MMSEngine* mms_engine_new( const MMSConfig* config, const MMSSettingsSimData* defaults, - unsigned int flags, - MMSLogModule* log_modules[], - int log_count); + const MMSEngineDbusConfig* dbus_config, + MMSLogModule* log_modules[], /* NULL terminated */ + unsigned int flags); MMSEngine* mms_engine_ref( diff --git a/mms-lib/include/mms_settings.h b/mms-lib/include/mms_settings.h index 2d4378f..35ed901 100644 --- a/mms-lib/include/mms_settings.h +++ b/mms-lib/include/mms_settings.h @@ -1,6 +1,7 @@ /* - * Copyright (C) 2014-2018 Jolla Ltd. - * Copyright (C) 2014-2018 Slava Monich + * Copyright (C) 2014-2019 Jolla Ltd. + * Copyright (C) 2014-2019 Slava Monich + * Copyright (C) 2019 Open Mobile Platform LLC. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -117,6 +118,12 @@ mms_settings_load_defaults( MMSSettingsSimDataCopy* simconfig, GError** error); +void +mms_settings_parse( + GKeyFile* file, + MMSConfigCopy* config, + MMSSettingsSimDataCopy* data); + void mms_settings_set_sim_defaults( MMSSettings* settings, diff --git a/mms-lib/src/mms_settings.c b/mms-lib/src/mms_settings.c index f03e29e..905a9f3 100644 --- a/mms-lib/src/mms_settings.c +++ b/mms-lib/src/mms_settings.c @@ -1,6 +1,7 @@ /* - * Copyright (C) 2014-2018 Jolla Ltd. - * Copyright (C) 2014-2018 Slava Monich + * Copyright (C) 2014-2019 Jolla Ltd. + * Copyright (C) 2014-2019 Slava Monich + * Copyright (C) 2019 Open Mobile Platform LLC. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -187,18 +188,27 @@ mms_settings_load_defaults( MMSSettingsSimDataCopy* data, GError** error) { - gboolean ok = FALSE; GKeyFile* file = g_key_file_new(); - if (g_key_file_load_from_file(file, path, 0, error)) { + gboolean ok = g_key_file_load_from_file(file, path, 0, error); + + if (ok) { GDEBUG("Loading %s", path); - mms_settings_parse_global_config(config, file); - mms_settings_parse_sim_config(data, file); - ok = TRUE; + mms_settings_parse(file, config, data); } g_key_file_free(file); return ok; } +void +mms_settings_parse( + GKeyFile* file, + MMSConfigCopy* config, + MMSSettingsSimDataCopy* data) +{ + mms_settings_parse_global_config(config, file); + mms_settings_parse_sim_config(data, file); +} + void mms_settings_sim_data_copy( MMSSettingsSimDataCopy* dest, diff --git a/mms-transfer-list-dbus/Makefile b/mms-transfer-list-dbus/Makefile index d4aade9..8136236 100644 --- a/mms-transfer-list-dbus/Makefile +++ b/mms-transfer-list-dbus/Makefile @@ -3,7 +3,7 @@ .PHONY: clean all debug release # Required packages -PKGS = libglibutil glib-2.0 gio-2.0 gio-unix-2.0 +PKGS = libdbusaccess libglibutil glib-2.0 gio-2.0 gio-unix-2.0 # # Default target diff --git a/mms-transfer-list-dbus/include/mms_transfer_list_dbus.h b/mms-transfer-list-dbus/include/mms_transfer_list_dbus.h index 603de7a..d143a7b 100644 --- a/mms-transfer-list-dbus/include/mms_transfer_list_dbus.h +++ b/mms-transfer-list-dbus/include/mms_transfer_list_dbus.h @@ -1,6 +1,7 @@ /* - * Copyright (C) 2016 Jolla Ltd. - * Contact: Slava Monich + * Copyright (C) 2016-2019 Jolla Ltd. + * Copyright (C) 2016-2019 Slava Monich + * Copyright (C) 2019 Open Mobile Platform LLC. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,8 +19,39 @@ #include "mms_transfer_list.h" +#include + +#define MMS_TRANSFER_LIST_DBUS_METHODS(m) \ + m(GET) + +typedef enum mms_transfer_list_action { + /* Action ids must be non-zero, shift those by one */ + MMS_TRANSFER_LIST_ACTION_NONE = 0, + #define MMS_TRANSFER_LIST_ACTION_(id) MMS_TRANSFER_LIST_ACTION_##id, + MMS_TRANSFER_LIST_DBUS_METHODS(MMS_TRANSFER_LIST_ACTION_) + #undef MMS_TRANSFER_LIST_ACTION_ +} MMS_TRANSFER_LIST_ACTION; + +#define MMS_TRANSFER_DBUS_METHODS(m) \ + m(GET_ALL) \ + m(ENABLE_UPDATES) \ + m(DISABLE_UPDATES) \ + m(GET_INTERFACE_VERSION) \ + m(GET_SEND_PROGRESS) \ + m(GET_RECEIVE_PROGRESS) + +typedef enum mms_transfer_action { + /* Action ids must be non-zero, shift those by one */ + MMS_TRANSFER_ACTION_NONE = 0, + #define MMS_TRANSFER_ACTION_(id) MMS_TRANSFER_ACTION_##id, + MMS_TRANSFER_DBUS_METHODS(MMS_TRANSFER_ACTION_) + #undef MMS_TRANSFER_ACTION_ +} MMS_TRANSFER_ACTION; + MMSTransferList* -mms_transfer_list_dbus_new(void); +mms_transfer_list_dbus_new( + DAPolicy* tx_list_access, + DAPolicy* tx_access); #endif /* JOLLA_MMS_TRANSFER_LIST_DBUS_H */ diff --git a/mms-transfer-list-dbus/mms-transfer-list-dbus.pro b/mms-transfer-list-dbus/mms-transfer-list-dbus.pro index 5fc5238..c322ba9 100644 --- a/mms-transfer-list-dbus/mms-transfer-list-dbus.pro +++ b/mms-transfer-list-dbus/mms-transfer-list-dbus.pro @@ -2,7 +2,7 @@ TEMPLATE = lib CONFIG += staticlib CONFIG -= qt CONFIG += link_pkgconfig -PKGCONFIG += libglibutil glib-2.0 gio-2.0 gio-unix-2.0 +PKGCONFIG += libdbusaccess libglibutil glib-2.0 gio-2.0 gio-unix-2.0 DBUS_SPEC_DIR = $$_PRO_FILE_PWD_/spec INCLUDEPATH += . include INCLUDEPATH += ../mms-lib/include diff --git a/mms-transfer-list-dbus/src/mms_transfer_dbus.c b/mms-transfer-list-dbus/src/mms_transfer_dbus.c index e2597df..7fe47a3 100644 --- a/mms-transfer-list-dbus/src/mms_transfer_dbus.c +++ b/mms-transfer-list-dbus/src/mms_transfer_dbus.c @@ -18,9 +18,9 @@ #include -/* Logging */ -#define GLOG_MODULE_NAME mms_transfer_list_log -#include +#include +#include + /* Generated code */ #include "org.nemomobile.MmsEngine.TransferList.h" @@ -33,14 +33,11 @@ /* Class definition */ -enum mms_transfer_dbus_method { - MMS_TRANSFER_DBUS_METHOD_GET_ALL, - MMS_TRANSFER_DBUS_METHOD_ENABLE_UPDATES, - MMS_TRANSFER_DBUS_METHOD_DISABLE_UPDATES, - MMS_TRANSFER_DBUS_METHOD_GET_INTERFACE_VERSION, - MMS_TRANSFER_DBUS_METHOD_GET_SEND_PROGRESS, - MMS_TRANSFER_DBUS_METHOD_GET_RECEIVE_PROGRESS, - MMS_TRANSFER_DBUS_METHOD_COUNT +enum mms_transfer_dbus_methods { + #define MMS_TRANSFER_METHOD_(id) MMS_TRANSFER_METHOD_##id, + MMS_TRANSFER_DBUS_METHODS(MMS_TRANSFER_METHOD_) + #undef MMS_TRANSFER_METHOD_ + MMS_TRANSFER_METHOD_COUNT }; typedef enum mms_transfer_flags { @@ -57,7 +54,9 @@ struct mms_transfer_dbus_priv { char* path; GDBusConnection* bus; OrgNemomobileMmsEngineTransfer* skeleton; - gulong proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_COUNT]; + gulong proxy_signal_id[MMS_TRANSFER_METHOD_COUNT]; + DA_BUS da_bus; + DAPolicy* dbus_access; GHashTable* clients; guint last_update_cookie; MMS_TRANSFER_FLAGS flags; @@ -224,11 +223,36 @@ mms_transfer_dbus_client_vanished( MMSTransferDbus* self = MMS_TRANSFER_DBUS(user_data); MMSTransferDbusPriv* priv = self->priv; - GDEBUG("Name '%s' has disappeared", name); + GDEBUG("Client '%s' has disappeared", name); g_hash_table_remove(priv->clients, name); mms_transfer_dbus_update_flags(self); } +static +gboolean +mms_transfer_dbus_access_allowed( + MMSTransferDbusPriv* priv, + GDBusMethodInvocation* call, + MMS_TRANSFER_ACTION action) +{ + const char* sender = g_dbus_method_invocation_get_sender(call); + DAPeer* peer = da_peer_get(priv->da_bus, sender); + + if (peer && da_policy_check(priv->dbus_access, &peer->cred, action, 0, + DA_ACCESS_ALLOW) == DA_ACCESS_ALLOW) { + return TRUE; + } else { + const char* iface = g_dbus_method_invocation_get_interface_name(call); + const char* method = g_dbus_method_invocation_get_method_name(call); + + GWARN("Client %s is not allowed to call %s.%s", sender, iface, method); + g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "Client %s is not allowed to call %s.%s", + sender, iface, method); + return FALSE; + } +} + /* org.nemomobile.MmsEngine.Transfer.GetAll */ static gboolean @@ -239,12 +263,19 @@ mms_transfer_dbus_handle_get_all( { MMSTransferDbusPriv* priv = self->priv; - org_nemomobile_mms_engine_transfer_complete_get_all(proxy, call, - MMS_TRANSFER_DBUS_INTERFACE_VERSION, - priv->bytes_sent, - priv->bytes_to_send, - priv->bytes_received, - priv->bytes_to_receive); + /* + * mms_transfer_dbus_access_allowed() completes the call if access + * is denied. + */ + if (mms_transfer_dbus_access_allowed(priv, call, + MMS_TRANSFER_ACTION_GET_ALL)) { + org_nemomobile_mms_engine_transfer_complete_get_all(proxy, call, + MMS_TRANSFER_DBUS_INTERFACE_VERSION, + priv->bytes_sent, + priv->bytes_to_send, + priv->bytes_received, + priv->bytes_to_receive); + } return TRUE; } @@ -258,9 +289,12 @@ mms_transfer_dbus_handle_enable_updates( MMSTransferDbus* self) { MMSTransferDbusPriv* priv = self->priv; - guint cookie = 0; - if (flags) { + if (!mms_transfer_dbus_access_allowed(priv, call, + MMS_TRANSFER_ACTION_ENABLE_UPDATES)) { + /* mms_transfer_dbus_access_allowed() has completes the call */ + } else if (flags) { + guint cookie = 0; MMSTransferDbusClient* client = NULL; const char* sender = g_dbus_method_invocation_get_sender(call); @@ -278,7 +312,7 @@ mms_transfer_dbus_handle_enable_updates( } if (!client) { client = g_slice_new0(MMSTransferDbusClient); - client->requests = g_hash_table_new(g_direct_hash, g_direct_equal); + client->requests = g_hash_table_new(g_direct_hash,g_direct_equal); client->watch_id = g_bus_watch_name_on_connection(priv->bus, sender, G_BUS_NAME_WATCHER_FLAGS_NONE, NULL, mms_transfer_dbus_client_vanished, self, NULL); @@ -292,12 +326,13 @@ mms_transfer_dbus_handle_enable_updates( priv->flags |= flags; GDEBUG("Update flags => 0x%02x", priv->flags); } + org_nemomobile_mms_engine_transfer_complete_enable_updates + (proxy, call, cookie); } else { GWARN("Client provided no update flags!"); + org_nemomobile_mms_engine_transfer_complete_enable_updates + (proxy, call, 0); } - - org_nemomobile_mms_engine_transfer_complete_enable_updates(proxy, - call, cookie); return TRUE; } @@ -311,29 +346,36 @@ mms_transfer_dbus_handle_disable_updates( MMSTransferDbus* self) { MMSTransferDbusPriv* priv = self->priv; - MMSTransferDbusClient* client = NULL; - const char* sender = g_dbus_method_invocation_get_sender(call); - GVERBOSE_("%s %u", sender, cookie); - org_nemomobile_mms_engine_transfer_complete_disable_updates(proxy, call); - - if (priv->clients) { - client = g_hash_table_lookup(priv->clients, sender); - } - if (client) { - gpointer value; - GHashTableIter it; + /* + * mms_transfer_dbus_access_allowed() completes the call if access + * is denied. + */ + if (mms_transfer_dbus_access_allowed(priv, call, + MMS_TRANSFER_ACTION_DISABLE_UPDATES)) { + MMSTransferDbusClient* client = NULL; + const char* sender = g_dbus_method_invocation_get_sender(call); - /* Update client flags */ - client->flags = 0; - g_hash_table_remove(client->requests, GINT_TO_POINTER(cookie)); - g_hash_table_iter_init(&it, client->requests); - while (g_hash_table_iter_next(&it, NULL, &value)) { - client->flags |= GPOINTER_TO_INT(value); + GVERBOSE_("%s %u", sender, cookie); + if (priv->clients) { + client = g_hash_table_lookup(priv->clients, sender); } - mms_transfer_dbus_update_flags(self); + if (client) { + gpointer value; + GHashTableIter it; + + /* Update client flags */ + client->flags = 0; + g_hash_table_remove(client->requests, GINT_TO_POINTER(cookie)); + g_hash_table_iter_init(&it, client->requests); + while (g_hash_table_iter_next(&it, NULL, &value)) { + client->flags |= GPOINTER_TO_INT(value); + } + mms_transfer_dbus_update_flags(self); + } + org_nemomobile_mms_engine_transfer_complete_disable_updates + (proxy, call); } - return TRUE; } @@ -345,8 +387,15 @@ mms_transfer_dbus_handle_get_interface_version( GDBusMethodInvocation* call, MMSTransferDbus* self) { - org_nemomobile_mms_engine_transfer_complete_get_interface_version(proxy, - call, MMS_TRANSFER_DBUS_INTERFACE_VERSION); + /* + * mms_transfer_dbus_access_allowed() completes the call if access + * is denied. + */ + if (mms_transfer_dbus_access_allowed(self->priv, call, + MMS_TRANSFER_ACTION_GET_INTERFACE_VERSION)) { + org_nemomobile_mms_engine_transfer_complete_get_interface_version + (proxy, call, MMS_TRANSFER_DBUS_INTERFACE_VERSION); + } return TRUE; } @@ -360,8 +409,15 @@ mms_transfer_dbus_handle_get_send_progress( { MMSTransferDbusPriv* priv = self->priv; - org_nemomobile_mms_engine_transfer_complete_get_send_progress(proxy, - call, priv->bytes_sent, priv->bytes_to_send); + /* + * mms_transfer_dbus_access_allowed() completes the call if access + * is denied. + */ + if (mms_transfer_dbus_access_allowed(priv, call, + MMS_TRANSFER_ACTION_GET_SEND_PROGRESS)) { + org_nemomobile_mms_engine_transfer_complete_get_send_progress + (proxy, call, priv->bytes_sent, priv->bytes_to_send); + } return TRUE; } @@ -375,14 +431,23 @@ mms_transfer_dbus_handle_get_receive_progress( { MMSTransferDbusPriv* priv = self->priv; - org_nemomobile_mms_engine_transfer_complete_get_receive_progress(proxy, - call, priv->bytes_received, priv->bytes_to_receive); + /* + * mms_transfer_dbus_access_allowed() completes the call if access + * is denied. + */ + if (mms_transfer_dbus_access_allowed(priv, call, + MMS_TRANSFER_ACTION_GET_RECEIVE_PROGRESS)) { + org_nemomobile_mms_engine_transfer_complete_get_receive_progress + (proxy, call, priv->bytes_received, priv->bytes_to_receive); + } return TRUE; } MMSTransferDbus* mms_transfer_dbus_new( GDBusConnection* bus, + DA_BUS da_bus, + DAPolicy* access, const char* id, const char* type) { @@ -394,24 +459,26 @@ mms_transfer_dbus_new( self->key.type = priv->type = g_strdup(type); self->path = priv->path = g_strconcat("/msg/", id, "/", type, NULL); priv->bus = g_object_ref(bus); + priv->da_bus = da_bus; + priv->dbus_access = da_policy_ref(access); priv->skeleton = org_nemomobile_mms_engine_transfer_skeleton_new(); - priv->proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_GET_ALL] = + priv->proxy_signal_id[MMS_TRANSFER_METHOD_GET_ALL] = g_signal_connect(priv->skeleton, "handle-get-all", G_CALLBACK(mms_transfer_dbus_handle_get_all), self); - priv->proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_ENABLE_UPDATES] = + priv->proxy_signal_id[MMS_TRANSFER_METHOD_ENABLE_UPDATES] = g_signal_connect(priv->skeleton, "handle-enable-updates", G_CALLBACK(mms_transfer_dbus_handle_enable_updates), self); - priv->proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_DISABLE_UPDATES] = + priv->proxy_signal_id[MMS_TRANSFER_METHOD_DISABLE_UPDATES] = g_signal_connect(priv->skeleton, "handle-disable-updates", G_CALLBACK(mms_transfer_dbus_handle_disable_updates), self); - priv->proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_GET_INTERFACE_VERSION] = + priv->proxy_signal_id[MMS_TRANSFER_METHOD_GET_INTERFACE_VERSION] = g_signal_connect(priv->skeleton, "handle-get-interface-version", G_CALLBACK(mms_transfer_dbus_handle_get_interface_version), self); - priv->proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_GET_SEND_PROGRESS] = + priv->proxy_signal_id[MMS_TRANSFER_METHOD_GET_SEND_PROGRESS] = g_signal_connect(priv->skeleton, "handle-get-send-progress", G_CALLBACK(mms_transfer_dbus_handle_get_send_progress), self); - priv->proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_GET_RECEIVE_PROGRESS] = + priv->proxy_signal_id[MMS_TRANSFER_METHOD_GET_RECEIVE_PROGRESS] = g_signal_connect(priv->skeleton, "handle-get-receive-progress", G_CALLBACK(mms_transfer_dbus_handle_get_receive_progress), self); if (!g_dbus_interface_skeleton_export( @@ -450,6 +517,7 @@ mms_transfer_dbus_finalize( g_free(priv->id); g_free(priv->type); g_free(priv->path); + da_policy_unref(priv->dbus_access); G_OBJECT_CLASS(mms_transfer_dbus_parent_class)->finalize(object); } @@ -473,10 +541,8 @@ void mms_transfer_dbus_class_init( MMSTransferDbusClass* klass) { - GObjectClass* object_class = G_OBJECT_CLASS(klass); - g_type_class_add_private(klass, sizeof(MMSTransferDbusPriv)); - object_class->finalize = mms_transfer_dbus_finalize; + G_OBJECT_CLASS(klass)->finalize = mms_transfer_dbus_finalize; } /* diff --git a/mms-transfer-list-dbus/src/mms_transfer_dbus.h b/mms-transfer-list-dbus/src/mms_transfer_dbus.h index 5649c1a..6ff4012 100644 --- a/mms-transfer-list-dbus/src/mms_transfer_dbus.h +++ b/mms-transfer-list-dbus/src/mms_transfer_dbus.h @@ -1,6 +1,7 @@ /* - * Copyright (C) 2016 Jolla Ltd. - * Contact: Slava Monich + * Copyright (C) 2016-2019 Jolla Ltd. + * Copyright (C) 2016-2019 Slava Monich + * Copyright (C) 2019 Open Mobile Platform LLC. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,7 +17,7 @@ #ifndef JOLLA_MMS_TRANSFER_DBUS_H #define JOLLA_MMS_TRANSFER_DBUS_H -#include "mms_lib_types.h" +#include "mms_transfer_list_dbus.h" #include @@ -43,6 +44,8 @@ GType mms_transfer_dbus_get_type(void); MMSTransferDbus* mms_transfer_dbus_new( GDBusConnection* bus, + DA_BUS da_bus, + DAPolicy* access, const char* id, const char* type); diff --git a/mms-transfer-list-dbus/src/mms_transfer_list_dbus.c b/mms-transfer-list-dbus/src/mms_transfer_list_dbus.c index e234e54..5433703 100644 --- a/mms-transfer-list-dbus/src/mms_transfer_list_dbus.c +++ b/mms-transfer-list-dbus/src/mms_transfer_list_dbus.c @@ -19,6 +19,9 @@ #include +#include +#include + /* Generated code */ #include "org.nemomobile.MmsEngine.TransferList.h" @@ -27,12 +30,18 @@ #define MMS_TRANSFER_LIST_SIGNAL_TRANSFER_STARTED "TransferStarted" #define MMS_TRANSFER_LIST_SIGNAL_TRANSFER_FINISHED "TransferFinished" +#define MMS_TRANSFER_LIST_DBUS_PATH "/" +#define MMS_TRANSFER_LIST_DBUS_BUS G_BUS_TYPE_SYSTEM +#define MMS_TRANSFER_LIST_DA_BUS DA_BUS_SYSTEM + /* Class definition */ typedef MMSTransferListClass MMSTransferListDbusClass; struct mms_transfer_list_dbus { MMSTransferList super; GDBusConnection* bus; OrgNemomobileMmsEngineTransferList* skeleton; + DAPolicy* tx_list_access; + DAPolicy* tx_access; gulong list_transfers_id; GHashTable* transfers; GHashTable* clients; @@ -44,9 +53,6 @@ G_DEFINE_TYPE(MMSTransferListDbus, mms_transfer_list_dbus, \ #define MMS_TRANSFER_LIST_DBUS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ MMS_TYPE_TRANSFER_LIST_DBUS, MMSTransferListDbus)) -#define MMS_TRANSFER_LIST_DBUS_PATH "/" -#define MMS_TRANSFER_LIST_DBUS_BUS G_BUS_TYPE_SYSTEM - /* * Sends signals only to registered clients. That's not much of an overhead * because there's usually no more than one client (i.e. Messages app). @@ -160,10 +166,14 @@ mms_transfer_list_dbus_bus_cb( } MMSTransferList* -mms_transfer_list_dbus_new() +mms_transfer_list_dbus_new( + DAPolicy* tx_list_access, + DAPolicy* tx_access) { MMSTransferListDbus* self = g_object_new(MMS_TYPE_TRANSFER_LIST_DBUS, 0); + self->tx_list_access = da_policy_ref(tx_list_access); + self->tx_access = da_policy_ref(tx_access); g_bus_get(MMS_TRANSFER_LIST_DBUS_BUS, NULL, mms_transfer_list_dbus_bus_cb, g_object_ref(self)); return &self->super; @@ -177,7 +187,8 @@ mms_transfer_list_dbus_transfer_started( char* type) /* Transfer type */ { MMSTransferListDbus* self = MMS_TRANSFER_LIST_DBUS(list); - MMSTransferDbus* transfer = mms_transfer_dbus_new(self->bus, id, type); + MMSTransferDbus* transfer = mms_transfer_dbus_new(self->bus, + MMS_TRANSFER_LIST_DA_BUS, self->tx_access, id, type); GDEBUG("Transfer %s started", transfer->path); transfer->list = self; @@ -284,47 +295,62 @@ mms_transfer_list_dbus_handle_get( MMSTransferListDbus* self) { const char* sender = g_dbus_method_invocation_get_sender(call); - const char* null = NULL; - const gchar* const* list = &null; - const gchar** paths = NULL; - guint n = g_hash_table_size(self->transfers); - - /* Store the sender's name */ - if (!self->clients) { - self->clients = /* sender => watch id */ - g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); - } - if (!g_hash_table_contains(self->clients, sender)) { - /* New client */ - gulong watch_id = g_bus_watch_name_on_connection(self->bus, - sender, G_BUS_NAME_WATCHER_FLAGS_NONE, NULL, - mms_transfer_list_dbus_client_vanished, self, NULL); - - g_hash_table_insert(self->clients, g_strdup(sender), - GUINT_TO_POINTER(watch_id)); - } - - if (n) { - guint i = 0; - gpointer value; - GHashTableIter it; + DAPeer* peer = da_peer_get(MMS_TRANSFER_LIST_DA_BUS, sender); + + if (peer && da_policy_check(self->tx_list_access, &peer->cred, + MMS_TRANSFER_LIST_ACTION_GET, 0, DA_ACCESS_ALLOW) == + DA_ACCESS_ALLOW) { + const char* null = NULL; + const gchar* const* list = &null; + const gchar** paths = NULL; + guint n = g_hash_table_size(self->transfers); + + /* Store the sender's name */ + if (!self->clients) { + self->clients = /* sender => watch id */ + g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + } + if (!g_hash_table_contains(self->clients, sender)) { + /* New client */ + gulong watch_id = g_bus_watch_name_on_connection(self->bus, + sender, G_BUS_NAME_WATCHER_FLAGS_NONE, NULL, + mms_transfer_list_dbus_client_vanished, self, NULL); + + g_hash_table_insert(self->clients, g_strdup(sender), + GUINT_TO_POINTER(watch_id)); + } - g_hash_table_iter_init(&it, self->transfers); - paths = g_new(const char*, n+1); - GVERBOSE("%u transfer(s)", n); - while (i < n && g_hash_table_iter_next(&it, NULL, &value)) { - MMSTransferDbus* transfer = value; - GVERBOSE(" %s", transfer->path); - paths[i++] = transfer->path; + if (n) { + guint i = 0; + gpointer value; + GHashTableIter it; + + g_hash_table_iter_init(&it, self->transfers); + paths = g_new(const char*, n+1); + GVERBOSE("%u transfer(s)", n); + while (i < n && g_hash_table_iter_next(&it, NULL, &value)) { + MMSTransferDbus* transfer = value; + GVERBOSE(" %s", transfer->path); + paths[i++] = transfer->path; + } + paths[i++] = NULL; + list = paths; + } else { + GVERBOSE("No transfers"); + list = &null; } - paths[i++] = NULL; - list = paths; + org_nemomobile_mms_engine_transfer_list_complete_get + (skeleton, call, list); + g_free(paths); } else { - GVERBOSE("No transfers"); - list = &null; + const char* iface = g_dbus_method_invocation_get_interface_name(call); + const char* method = g_dbus_method_invocation_get_method_name(call); + + GWARN("Client %s is not allowed to call %s.%s", sender, iface, method); + g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "Client %s is not allowed to call %s.%s", + sender, iface, method); } - org_nemomobile_mms_engine_transfer_list_complete_get(skeleton, call, list); - g_free(paths); return TRUE; } @@ -348,6 +374,8 @@ mms_transfer_list_dbus_finalize( if (self->bus) { g_object_unref(self->bus); } + da_policy_unref(self->tx_list_access); + da_policy_unref(self->tx_access); G_OBJECT_CLASS(mms_transfer_list_dbus_parent_class)->finalize(object); } diff --git a/rpm/mms-engine.spec b/rpm/mms-engine.spec index 6e5441a..f9b647b 100644 --- a/rpm/mms-engine.spec +++ b/rpm/mms-engine.spec @@ -4,7 +4,7 @@ Version: 1.0.67 Release: 1 Group: Communications/Telephony and IM License: GPLv2 -URL: https://git.merproject.org/mer-core/mms-engine +URL: https://git.sailfishos.org/mer-core/mms-engine Source0: %{name}-%{version}.tar.bz2 Requires: dbus Requires: ofono @@ -13,6 +13,7 @@ Requires: libwspcodec >= 2.2 Requires: libgofono >= 2.0.0 Requires: libgofonoext >= 1.0.4 Requires: libglibutil >= 1.0.5 +Requires: libdbusaccess >= 1.0.10 Requires(post): glib2 Requires(postun): glib2 @@ -28,6 +29,7 @@ BuildRequires: pkgconfig(libwspcodec) >= 2.2 BuildRequires: pkgconfig(libgofono) >= 2.0.0 BuildRequires: pkgconfig(libgofonoext) >= 1.0.4 BuildRequires: pkgconfig(libglibutil) >= 1.0.11 +BuildRequires: pkgconfig(libdbusaccess) #BuildRequires: pkgconfig(ImageMagick) BuildRequires: pkgconfig(Qt5Gui)