From b5a10feae9bf34a4e3ac11d7601507f5dbf39003 Mon Sep 17 00:00:00 2001 From: jeon Date: Tue, 23 Apr 2019 21:49:01 +0900 Subject: [PATCH] pepper-keyrouter: check a privilege using cynara APIs Change-Id: I5c9deb81355a79e0b8cc0ca20ceb97150940e2ad --- configure.ac | 8 + packaging/pepper.spec | 3 + src/lib/keyrouter/Makefile.am | 4 +- src/lib/keyrouter/pepper-keyrouter.c | 254 +++++++++++++++++++++++++-- 4 files changed, 253 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 2044aa3..537b4a3 100644 --- a/configure.ac +++ b/configure.ac @@ -45,6 +45,14 @@ if test "x${have_dlog}" = "xyes"; then fi AM_CONDITIONAL([HAVE_DLOG], [test "x${have_dlog}" = "xyes"]) +PKG_CHECK_MODULES(CYNARA, [cynara-client, cynara-creds-socket, cynara-session, libsmack], + [have_cynara="yes"], [have_cynara="no"]) +if test "x${have_cynara}" = "xyes"; then + AC_DEFINE([HAVE_CYNARA], [1], [Define to 1 if you have cynara]) + PEPPER_REQUIRES="$PEPPER_REQUIRES cynara-client cynara-creds-socket cynara-session libsmack" +fi +AM_CONDITIONAL([HAVE_CYNARA], [test "x${have_cynara}" = "xyes"]) + PEPPER_DIR="-I\$(top_srcdir)/src/lib/pepper" PEPPER_LIB="\$(top_srcdir)/src/lib/pepper/libpepper.la" diff --git a/packaging/pepper.spec b/packaging/pepper.spec index f580fef..9df7ca0 100644 --- a/packaging/pepper.spec +++ b/packaging/pepper.spec @@ -41,6 +41,9 @@ BuildRequires: pkgconfig(capi-system-peripheral-io) BuildRequires: pkgconfig(xdg-shell-unstable-v6-server) BuildRequires: pkgconfig(tizen-extension-server) %endif +BuildRequires: pkgconfig(cynara-client) +BuildRequires: pkgconfig(cynara-creds-socket) +BuildRequires: pkgconfig(libsmack) %description Pepper is a lightweight and flexible library for developing various types of wayland compositors. diff --git a/src/lib/keyrouter/Makefile.am b/src/lib/keyrouter/Makefile.am index fe36aff..4920e1c 100644 --- a/src/lib/keyrouter/Makefile.am +++ b/src/lib/keyrouter/Makefile.am @@ -5,8 +5,8 @@ AM_CFLAGS = $(GCC_CFLAGS) libpepper_keyrouter_includedir=$(includedir)/pepper libpepper_keyrouter_include_HEADERS = keyrouter.h pepper-keyrouter.h -libpepper_keyrouter_la_CFLAGS = $(AM_CFLAGS) $(PEPPER_KEYROUTER_CFLAGS) -libpepper_keyrouter_la_LIBADD = $(PEPPER_KEYROUTER_LIBS) +libpepper_keyrouter_la_CFLAGS = $(AM_CFLAGS) $(PEPPER_KEYROUTER_CFLAGS) $(CYNARA_CFLAGS) +libpepper_keyrouter_la_LIBADD = $(PEPPER_KEYROUTER_LIBS) $(CYNARA_LIBS) libpepper_keyrouter_la_SOURCES = keyrouter-internal.h \ keyrouter.c \ diff --git a/src/lib/keyrouter/pepper-keyrouter.c b/src/lib/keyrouter/pepper-keyrouter.c index 4ad9d69..53c2669 100644 --- a/src/lib/keyrouter/pepper-keyrouter.c +++ b/src/lib/keyrouter/pepper-keyrouter.c @@ -24,10 +24,19 @@ #include "pepper-keyrouter.h" #include "pepper-internal.h" #include +#ifdef HAVE_CYNARA +#include +#include +#include +#include +#include +#include +#endif #define MIN(a,b) ((a)<(b)?(a):(b)) typedef struct resources_data resources_data_t; +typedef struct clients_data clients_data_t; typedef struct grab_list_data grab_list_data_t; typedef struct ungrab_list_data ungrab_list_data_t; @@ -39,11 +48,15 @@ struct pepper_keyrouter { pepper_keyboard_t *keyboard; pepper_list_t resources; + pepper_list_t grabbed_clients; keyrouter_t *keyrouter; pepper_view_t *focus_view; pepper_view_t *top_view; +#ifdef HAVE_CYNARA + cynara *p_cynara; +#endif }; struct resources_data { @@ -51,6 +64,11 @@ struct resources_data { pepper_list_t link; }; +struct clients_data { + struct wl_client *client; + pepper_list_t link; +}; + struct grab_list_data { int key; int mode; @@ -62,6 +80,124 @@ struct ungrab_list_data { int err; }; +#ifdef HAVE_CYNARA +static void +_pepper_keyrouter_util_cynara_log(int err, const char *fmt, ...) +{ +#define CYNARA_BUFSIZE 128 + char buf[CYNARA_BUFSIZE] = "\0", tmp[CYNARA_BUFSIZE + CYNARA_BUFSIZE] = "\0"; + va_list args; + int ret; + + if (fmt) { + va_start(args, fmt); + vsnprintf(tmp, CYNARA_BUFSIZE + CYNARA_BUFSIZE, fmt, args); + va_end(args); + } + + ret = cynara_strerror(err, buf, CYNARA_BUFSIZE); + if (ret != CYNARA_API_SUCCESS) { + PEPPER_ERROR("Failed to cynara_strerror: %d (error log about %s: %d)\n", ret, tmp, err); + return; + } + + PEPPER_ERROR("%s is failed: %s\n", tmp, buf); +} +#endif + +static pepper_bool_t +_pepper_keyrouter_util_cynara_init(pepper_keyrouter_t *pepper_keyrouter) +{ +#ifdef HAVE_CYNARA + int ret; + if (pepper_keyrouter->p_cynara) return PEPPER_TRUE; + + ret = cynara_initialize(&pepper_keyrouter->p_cynara, NULL); + if (CYNARA_API_SUCCESS != ret) { + _pepper_keyrouter_util_cynara_log(ret, "cynara_initialize"); + return PEPPER_FALSE; + } +#endif + return PEPPER_TRUE; +} + +static void +_pepper_keyrouter_util_cynara_deinit(pepper_keyrouter_t *pepper_keyrouter) +{ +#ifdef HAVE_CYNARA + if (pepper_keyrouter->p_cynara) cynara_finish(pepper_keyrouter->p_cynara); +#else + ; +#endif +} + +static pepper_bool_t +_pepper_keyrouter_util_do_privilege_check(pepper_keyrouter_t *pepper_keyrouter, struct wl_client *client, uint32_t mode, uint32_t keycode) +{ + pepper_bool_t res = PEPPER_TRUE; +#ifdef HAVE_CYNARA + int ret, retry_cnt = 0, len = 0; + char *clientSmack = NULL, *client_session = NULL, uid2[16]={0, }; + clients_data_t *cdata; + static pepper_bool_t retried = PEPPER_FALSE; + pid_t pid = 0; + uid_t uid = 0; + gid_t gid = 0; + + res = PEPPER_FALSE; + + /* Top position grab is always allowed. This mode do not need privilege.*/ + if (mode == TIZEN_KEYROUTER_MODE_TOPMOST) return PEPPER_TRUE; + if (!client) return PEPPER_FALSE; + + /* If initialize cynara is failed, allow keygrabs regardless of the previlege permition. */ + if (pepper_keyrouter->p_cynara == NULL) { + if (retried == PEPPER_FALSE) { + retried = PEPPER_TRUE; + for(retry_cnt = 0; retry_cnt < 5; retry_cnt++) { + PEPPER_TRACE("Retry cynara initialize: %d\n", retry_cnt + 1); + + ret = cynara_initialize(&pepper_keyrouter->p_cynara, NULL); + if (CYNARA_API_SUCCESS != ret) { + _pepper_keyrouter_util_cynara_log(ret, "cynara_initialize retry.."); + pepper_keyrouter->p_cynara = NULL; + } else { + PEPPER_TRACE("Success cynara initialize to try %d times\n", retry_cnt + 1); + break; + } + } + } + if (!pepper_keyrouter->p_cynara) return PEPPER_TRUE; + } + + pepper_list_for_each(cdata, &pepper_keyrouter->grabbed_clients, link) { + if (cdata->client == client) return PEPPER_TRUE; + } + + wl_client_get_credentials(client, &pid, &uid, &gid); + + len = smack_new_label_from_process((int)pid, &clientSmack); + if (len <= 0) goto finish; + + snprintf(uid2, 15, "%d", (int)uid); + client_session = cynara_session_from_pid(pid); + + ret = cynara_check(pepper_keyrouter->p_cynara, clientSmack, client_session, uid2, "http://tizen.org/privilege/keygrab"); + if (CYNARA_API_ACCESS_ALLOWED == ret) { + res = PEPPER_TRUE; + PEPPER_TRACE("Success to check cynara, clientSmack: %s client_session: %s, uid2: %s\n", clientSmack, client_session, uid2); + } else { + //PEPPER_TRACE("Fail to check cynara, error : %d (pid : %d)", ret, pid); + _pepper_keyrouter_util_cynara_log(ret, "clientsmack: %s, pid: %d", clientSmack, pid); + } + +finish: + if (client_session) free(client_session); + if (clientSmack) free(clientSmack); +#endif + return res; +} + static struct wl_client * _pepper_keyrouter_get_client_from_view(pepper_view_t *view) { @@ -190,6 +326,29 @@ _pepper_keyrouter_remove_client_from_list(pepper_keyrouter_t *pepper_keyrouter, } } +static int +_pepper_keyrouter_add_client_to_list(pepper_keyrouter_t *pepper_keyrouter, struct wl_client *client) +{ + clients_data_t *cdata; + + pepper_list_for_each(cdata, &pepper_keyrouter->grabbed_clients, link) { + if (cdata->client == client) return TIZEN_KEYROUTER_ERROR_NONE; + } + + cdata = (clients_data_t *)calloc(1, sizeof(clients_data_t)); + if (!cdata) + { + PEPPER_ERROR("Failed to allocate memory !\n"); + return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES; + } + + cdata->client = client; + pepper_list_init(&cdata->link); + pepper_list_insert(&pepper_keyrouter->grabbed_clients, &cdata->link); + + return TIZEN_KEYROUTER_ERROR_NONE; +} + static void _pepper_keyrouter_cb_keygrab_set(struct wl_client *client, struct wl_resource *resource, @@ -199,12 +358,22 @@ _pepper_keyrouter_cb_keygrab_set(struct wl_client *client, { int res = TIZEN_KEYROUTER_ERROR_NONE; pepper_keyrouter_t *pepper_keyrouter = NULL; + pepper_bool_t ret; pepper_keyrouter = (pepper_keyrouter_t *)wl_resource_get_user_data(resource); PEPPER_CHECK(pepper_keyrouter, goto notify, "Invalid pepper_keyrouter_t\n"); + ret = _pepper_keyrouter_util_do_privilege_check(pepper_keyrouter, client, mode, key); + if (!ret) { + res = TIZEN_KEYROUTER_ERROR_NO_PERMISSION; + goto notify; + } + res = keyrouter_grab_key(pepper_keyrouter->keyrouter, mode, key, (void *)client); + if (res == TIZEN_KEYROUTER_ERROR_NONE) + res = _pepper_keyrouter_add_client_to_list(pepper_keyrouter, client); + notify: tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, res); } @@ -215,11 +384,24 @@ _pepper_keyrouter_cb_keygrab_unset(struct wl_client *client, struct wl_resource *surface, uint32_t key) { + int res = TIZEN_KEYROUTER_ERROR_NONE; pepper_keyrouter_t *pepper_keyrouter = NULL; + pepper_bool_t ret; pepper_keyrouter = (pepper_keyrouter_t *)wl_resource_get_user_data(resource); PEPPER_CHECK(pepper_keyrouter, goto notify, "Invalid pepper_keyrouter_t\n"); + /* ungrab TOP POSITION grab first, this grab mode is not check privilege */ + keyrouter_ungrab_key(pepper_keyrouter->keyrouter, + TIZEN_KEYROUTER_MODE_TOPMOST, + key, (void *)client); + + ret = _pepper_keyrouter_util_do_privilege_check(pepper_keyrouter, client, TIZEN_KEYROUTER_MODE_NONE, key); + if (!ret) { + res = TIZEN_KEYROUTER_ERROR_NO_PERMISSION; + goto notify; + } + keyrouter_ungrab_key(pepper_keyrouter->keyrouter, TIZEN_KEYROUTER_MODE_EXCLUSIVE, key, (void *)client); @@ -234,7 +416,7 @@ _pepper_keyrouter_cb_keygrab_unset(struct wl_client *client, key, (void *)client); notify: - tizen_keyrouter_send_keygrab_notify(resource, surface, key, TIZEN_KEYROUTER_MODE_NONE, TIZEN_KEYROUTER_ERROR_NONE); + tizen_keyrouter_send_keygrab_notify(resource, surface, key, TIZEN_KEYROUTER_MODE_NONE, res); } static void @@ -269,6 +451,7 @@ _pepper_keyrouter_cb_keygrab_set_list(struct wl_client *client, grab_list_data_t *grab_data = NULL; int res = TIZEN_KEYROUTER_ERROR_NONE; pepper_keyrouter_t *pepper_keyrouter = NULL; + pepper_bool_t ret; pepper_keyrouter = (pepper_keyrouter_t *)wl_resource_get_user_data(resource); @@ -278,8 +461,15 @@ _pepper_keyrouter_cb_keygrab_set_list(struct wl_client *client, "Invalid keycode and grab mode pair. Check arguments in a list\n"); wl_array_for_each(grab_data, grab_list) { - res = keyrouter_grab_key(pepper_keyrouter->keyrouter, grab_data->mode, grab_data->key, (void *)client); - grab_data->err = res; + ret = _pepper_keyrouter_util_do_privilege_check(pepper_keyrouter, client, grab_data->mode, grab_data->key); + if (!ret) { + grab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION; + } else { + res = keyrouter_grab_key(pepper_keyrouter->keyrouter, grab_data->mode, grab_data->key, (void *)client); + grab_data->err = res; + if (res == TIZEN_KEYROUTER_ERROR_NONE) + res = _pepper_keyrouter_add_client_to_list(pepper_keyrouter, client); + } } return_list = grab_list; @@ -296,6 +486,7 @@ _pepper_keyrouter_cb_keygrab_unset_list(struct wl_client *client, struct wl_array *return_list = NULL; ungrab_list_data_t *ungrab_data = NULL; pepper_keyrouter_t *pepper_keyrouter = NULL; + pepper_bool_t ret; pepper_keyrouter = (pepper_keyrouter_t *)wl_resource_get_user_data(resource); @@ -304,20 +495,32 @@ _pepper_keyrouter_cb_keygrab_unset_list(struct wl_client *client, "Invalid keycode and grab mode pair. Check arguments in a list\n"); wl_array_for_each(ungrab_data, ungrab_list) { - keyrouter_ungrab_key(pepper_keyrouter->keyrouter, - TIZEN_KEYROUTER_MODE_EXCLUSIVE, - ungrab_data->key, (void *)client); - keyrouter_ungrab_key(pepper_keyrouter->keyrouter, - TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, - ungrab_data->key, (void *)client); keyrouter_ungrab_key(pepper_keyrouter->keyrouter, TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)client); - keyrouter_ungrab_key(pepper_keyrouter->keyrouter, - TIZEN_KEYROUTER_MODE_SHARED, - ungrab_data->key, (void *)client); - ungrab_data->err = TIZEN_KEYROUTER_ERROR_NONE;; + ret = _pepper_keyrouter_util_do_privilege_check(pepper_keyrouter, client, TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key); + if (!ret) { + ungrab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION; + } else { + keyrouter_ungrab_key(pepper_keyrouter->keyrouter, + TIZEN_KEYROUTER_MODE_EXCLUSIVE, + ungrab_data->key, (void *)client); + + keyrouter_ungrab_key(pepper_keyrouter->keyrouter, + TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, + ungrab_data->key, (void *)client); + + keyrouter_ungrab_key(pepper_keyrouter->keyrouter, + TIZEN_KEYROUTER_MODE_TOPMOST, + ungrab_data->key, (void *)client); + + keyrouter_ungrab_key(pepper_keyrouter->keyrouter, + TIZEN_KEYROUTER_MODE_SHARED, + ungrab_data->key, (void *)client); + + ungrab_data->err = TIZEN_KEYROUTER_ERROR_NONE; + } } return_list = ungrab_list; @@ -385,6 +588,7 @@ static void _pepper_keyrouter_cb_resource_destory(struct wl_resource *resource) { resources_data_t *rdata, *rtmp; + clients_data_t *cdata, *ctmp; pepper_list_t *list; struct wl_client *client; pepper_keyrouter_t *pepper_keyrouter; @@ -395,7 +599,16 @@ _pepper_keyrouter_cb_resource_destory(struct wl_resource *resource) pepper_keyrouter = wl_resource_get_user_data(resource); PEPPER_CHECK(pepper_keyrouter, return, "Invalid pepper_keyrouter_t\n"); - _pepper_keyrouter_remove_client_from_list(pepper_keyrouter, client); + list = &pepper_keyrouter->grabbed_clients; + if (!pepper_list_empty(list)) { + pepper_list_for_each_safe(cdata, ctmp, list, link) { + if (cdata->client == client) { + _pepper_keyrouter_remove_client_from_list(pepper_keyrouter, client); + pepper_list_remove(&cdata->link); + free(cdata); + } + } + } list = &pepper_keyrouter->resources; @@ -475,6 +688,7 @@ pepper_keyrouter_create(pepper_compositor_t *compositor) struct wl_display *display = NULL; struct wl_global *global = NULL; pepper_keyrouter_t *pepper_keyrouter; + pepper_bool_t ret; PEPPER_CHECK(compositor, return PEPPER_FALSE, "Invalid compositor\n"); @@ -487,6 +701,7 @@ pepper_keyrouter_create(pepper_compositor_t *compositor) pepper_keyrouter->compositor = compositor; pepper_list_init(&pepper_keyrouter->resources); + pepper_list_init(&pepper_keyrouter->grabbed_clients); global = wl_global_create(display, &tizen_keyrouter_interface, 2, pepper_keyrouter, _pepper_keyrouter_cb_bind); PEPPER_CHECK(global, goto failed, "Failed to create wl_global for tizen_keyrouter\n"); @@ -494,6 +709,9 @@ pepper_keyrouter_create(pepper_compositor_t *compositor) pepper_keyrouter->keyrouter = keyrouter_create(); PEPPER_CHECK(pepper_keyrouter->keyrouter, goto failed, "Failed to create keyrouter\n"); + ret = _pepper_keyrouter_util_cynara_init(pepper_keyrouter); + if (!ret) PEPPER_TRACE("cynara initialize is failed, process keyrouter without cynara\n"); + return pepper_keyrouter; failed: @@ -512,9 +730,15 @@ PEPPER_API void pepper_keyrouter_destroy(pepper_keyrouter_t *pepper_keyrouter) { resources_data_t *rdata, *rtmp; + clients_data_t *cdata, *ctmp; PEPPER_CHECK(pepper_keyrouter, return, "Pepper keyrouter is not initialized\n"); + pepper_list_for_each_safe(cdata, ctmp, &pepper_keyrouter->grabbed_clients, link) { + pepper_list_remove(&cdata->link); + free(cdata); + } + pepper_list_for_each_safe(rdata, rtmp, &pepper_keyrouter->resources, link) { wl_resource_destroy(rdata->resource); pepper_list_remove(&rdata->link); @@ -529,6 +753,8 @@ pepper_keyrouter_destroy(pepper_keyrouter_t *pepper_keyrouter) if (pepper_keyrouter->global) wl_global_destroy(pepper_keyrouter->global); + _pepper_keyrouter_util_cynara_deinit(pepper_keyrouter); + free(pepper_keyrouter); pepper_keyrouter = NULL; } -- 2.34.1