From fc468ef9c026c6fc4910de018f81d90cb905d617 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Wed, 11 May 2022 16:45:58 +0900 Subject: [PATCH] add security api which uses cynara The keyrouter and devicemgr has to check the privilege when display server gets the requests from these extensions. For this, security api support the previlege check with cynara. Change-Id: I6086e60e9d611de219b05856da6668bd7510cdc4 --- src/libds-tizen/meson.build | 1 + src/libds-tizen/util.h | 17 ++++ src/libds-tizen/util/meson.build | 1 + src/libds-tizen/util/security.c | 162 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 src/libds-tizen/util.h create mode 100644 src/libds-tizen/util/meson.build create mode 100644 src/libds-tizen/util/security.c diff --git a/src/libds-tizen/meson.build b/src/libds-tizen/meson.build index 4f76b68..81370e6 100644 --- a/src/libds-tizen/meson.build +++ b/src/libds-tizen/meson.build @@ -12,6 +12,7 @@ libds_tizen_deps = [ subdir('allocator') subdir('backend') +subdir('util') lib_libds_tizen = shared_library('ds-tizen', libds_tizen_files, dependencies: libds_tizen_deps, diff --git a/src/libds-tizen/util.h b/src/libds-tizen/util.h new file mode 100644 index 0000000..18ad811 --- /dev/null +++ b/src/libds-tizen/util.h @@ -0,0 +1,17 @@ +#ifndef DS_UTIL_H +#define DS_UTIL_H + +#include + +#define MIN(a,b) ((a)<(b)?(a):(b)) + +int +tizen_security_init(void); + +void +tizen_security_finish(void); + +bool +tizen_security_check_privilege(pid_t pid, uid_t uid, const char *privilege); + +#endif diff --git a/src/libds-tizen/util/meson.build b/src/libds-tizen/util/meson.build new file mode 100644 index 0000000..3d34ab8 --- /dev/null +++ b/src/libds-tizen/util/meson.build @@ -0,0 +1 @@ +libds_tizen_files += files('security.c') diff --git a/src/libds-tizen/util/security.c b/src/libds-tizen/util/security.c new file mode 100644 index 0000000..735caf5 --- /dev/null +++ b/src/libds-tizen/util/security.c @@ -0,0 +1,162 @@ + +#include +#include +#include + +#include "libds/log.h" + +#include "util.h" + +#ifdef HAVE_CYNARA +#include +#include +#include +#include +#include +#include + +#define CYNARA_BUFSIZE 128 + +static cynara *g_cynara = NULL; +static int g_cynara_refcount = 0; + +static void +__security_log_print(int err, const char *fmt, ...) +{ + int ret; + va_list args; + char buf[CYNARA_BUFSIZE] = "\0"; + char tmp[CYNARA_BUFSIZE + CYNARA_BUFSIZE] = "\0"; + + 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) { + ds_err("Failed to get cynara_strerror. error : %d (error log about %s: %d)\n", ret, tmp, err); + return; + } + + ds_err("%s is failed. (%s)\n", tmp, buf); +} +#endif + +bool +tizen_security_check_privilege(pid_t pid, uid_t uid, const char *privilege) +{ +#ifdef HAVE_CYNARA + bool res = false; + char *client_smack = NULL; + char *client_session = NULL; + char uid_str[16] = { 0, }; + int len = -1; + int ret = -1; + + /* If cynara_initialize() has been (retried) and failed, we suppose that cynara is not available. */ + /* Then we return true as if there is no security check available. */ + if (!g_cynara) + return true; + + if (!g_cynara) { + ds_err("security has not been initialized.\n"); + return false; + } + + ret = smack_new_label_from_process((int)pid, &client_smack); + if (ret <= 0) + goto finish; + + snprintf(uid_str, 15, "%d", (int)uid); + + client_session = cynara_session_from_pid(pid); + if (!client_session) + goto finish; + + ret = cynara_check(g_cynara, client_smack, client_session, + uid_str, privilege); + + if (ret == CYNARA_API_ACCESS_ALLOWED) + res = true; + else + __security_log_print(ret, "privilege: %s, client_smack: %s, pid: %d", privilege, client_smack, pid); + +finish: + ds_dbg("Privilege Check For '%s' %s pid:%u uid:%u client_smack:%s(len:%d) client_session:%s ret:%d", + privilege, res ? "SUCCESS" : "FAIL", pid, uid, + client_smack ? client_smack : "N/A", len, + client_session ? client_session: "N/A", ret); + + if (client_session) + free(client_session); + if (client_smack) + free(client_smack); + + return res; +#else + return true; +#endif +} + +int +tizen_security_init(void) +{ +#ifdef HAVE_CYNARA + int ret = CYNARA_API_SUCCESS; + int retry_cnt = 0; + static bool retried = false; + + if (++g_cynara_refcount != 1) + return g_cynara_refcount; + + if (!g_cynara && false == retried) { + retried = true; + + for (retry_cnt = 0; retry_cnt < 5; retry_cnt++) { + ds_dbg("Retry cynara initialize: %d\n", retry_cnt + 1); + + ret = cynara_initialize(&g_cynara, NULL); + + if (CYNARA_API_SUCCESS == ret) { + ds_dbg("Succeed to initialize cynara !\n"); + return 1; + } + + __security_log_print(ret, "cynara_initialize"); + g_cynara = NULL; + } + } + + ds_err("Failed to initialize _security ! (error:%d, retry_cnt=%d)\n", + ret, retry_cnt); + --g_cynara_refcount; + + return 0; +#else + return 1; +#endif +} + +void +tizen_security_finish(void) +{ +#ifdef HAVE_CYNARA + if (g_cynara_refcount < 1) { + ds_err("%s called without tizen_security_init\n", __FUNCTION__); + return 0; + } + + if (--g_cynara_refcount != 0) + return 1; + + if (g_cynara) { + cynara_finish(g_cynara); + g_cynara = NULL; + } +#endif + + return 1; +} + -- 2.7.4