Add checker for feature and privilege to engine API
[platform/core/uifw/stt.git] / server / stte.c
index c2b1ae1..59caa14 100755 (executable)
 #include <aul.h>
 #include <Ecore.h>
 #include <vconf.h>
+#include <stdatomic.h>
+#include <system_info.h>
+#include <cynara-client.h>
+#include <cynara-error.h>
+#include <cynara-session.h>
+#include <pthread.h>
 
 #include "stt_engine.h"
 #include "stt_defs.h"
 #include "sttd_dbus.h"
 #include "sttd_server.h"
 #include "sttd_engine_agent.h"
+#include "stt_dlog.h"
 
 #include "stte.h"
 
+static atomic_int g_feature_enabled = -1;
+static cynara *p_cynara = NULL;
+static pthread_mutex_t g_cynara_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static bool is_feature_enabled()
+{
+       if (1 == g_feature_enabled) {
+               return true;
+       }
+
+       if (0 == g_feature_enabled) {
+               SLOG(LOG_ERROR, TAG_STTD, "[ERROR] TTS feature NOT supported");
+               return false;
+       }
+
+       bool stt_supported = false;
+       if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_bool(STT_FEATURE_PATH, &stt_supported)) {
+               SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Fail to get feature value");
+               return false;
+       }
+
+       bool mic_supported = false;
+       if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_bool(STT_MIC_FEATURE_PATH, &mic_supported)) {
+               SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Fail to get feature value");
+               return false;
+       }
+
+       if (false == stt_supported || false == mic_supported) {
+               SLOG(LOG_ERROR, TAG_STTD, "[ERROR] STT NOT supported");
+               g_feature_enabled = 0;
+               return false;
+       }
+
+       g_feature_enabled = 1;
+       return true;
+}
+
+static bool initialize_privilege_checker()
+{
+       int ret = cynara_initialize(&p_cynara, NULL);
+       if (CYNARA_API_SUCCESS != ret)
+               SLOG(LOG_ERROR, TAG_STTD, "[ERROR] fail to initialize"); //LCOV_EXCL_LINE
+
+       return ret == CYNARA_API_SUCCESS;
+}
+
+static bool is_privilege_allowed(const char* uid, const char * privilege)
+{
+       FILE *fp = NULL;
+       char label_path[1024] = "/proc/self/attr/current";
+       char smack_label[1024] = {'\0',};
+
+       if (!p_cynara) {
+               return false;
+       }
+
+       fp = fopen(label_path, "r");
+       if (fp != NULL) {
+               if (0 >= fread(smack_label, 1, sizeof(smack_label), fp))
+
+               fclose(fp);
+       }
+
+       pid_t pid = getpid();
+       char *session = cynara_session_from_pid(pid);
+       int ret = cynara_check(p_cynara, smack_label, session, uid, privilege);
+       free(session);
+
+       if (ret != CYNARA_API_ACCESS_ALLOWED) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Client]cynara_check returned %d(Denied)", ret);
+               return false;
+       }
+       return true;
+}
+
+static void deinitialize_privilege_checker()
+{
+       if (p_cynara)
+               cynara_finish(p_cynara);
+       p_cynara = NULL;
+}
+
+static bool is_stt_privilege_allowed()
+{
+       pthread_mutex_lock(&g_cynara_mutex);
+       bool is_initialized = initialize_privilege_checker();
+       if (false == is_initialized) {
+               pthread_mutex_unlock(&g_cynara_mutex);
+               return false;
+       }
+
+       char uid[16];
+       snprintf(uid, 16, "%d", getuid());
+       bool is_allowed = is_privilege_allowed(uid, STT_PRIVILEGE_RECORDER);
+       deinitialize_privilege_checker();
+       if (false == is_allowed) {
+               pthread_mutex_unlock(&g_cynara_mutex);
+               return false;
+       }
+
+       pthread_mutex_unlock(&g_cynara_mutex);
+       return true;
+}
+
+static inline int check_feature_and_privilege()
+{
+       RETV_IF(false == is_feature_enabled(), STTE_ERROR_NOT_SUPPORTED);
+       RETV_IF(false == is_stt_privilege_allowed(), STTE_ERROR_PERMISSION_DENIED);
+
+       return STTE_ERROR_NONE;
+}
+
 static bool __is_default_engine()
 {
        char* engine = NULL;
@@ -50,8 +169,11 @@ static bool __is_default_engine()
 int stte_main(int argc, char**argv, stte_request_callback_s *callback)
 {
        SLOG(LOG_DEBUG, TAG_STTD, "===== Start engine");
-
-       int ret = STTE_ERROR_NONE;
+       int ret = check_feature_and_privilege();
+       if (STTE_ERROR_NONE != ret) {
+               SLOG(LOG_ERROR, TAG_STTD, "Precondition is not met (%s)", get_error_message(ret));
+               return ret;
+       }
 
        if (!ecore_init()) {
                SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Fail to initialize Ecore");
@@ -88,13 +210,14 @@ int stte_main(int argc, char**argv, stte_request_callback_s *callback)
 int stte_send_result(stte_result_event_e event, const char* type, const char** result, int result_count,
                                const char* msg, void* time_info, void* user_data)
 {
+       RETV_IF(false == is_feature_enabled(), STTE_ERROR_NOT_SUPPORTED);
+
        if (NULL == type || NULL == result) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Invalid parameter");
        }
 
-       int ret = STTE_ERROR_NONE;
        stt_engine_result_cb result_cb = NULL;
-       ret = stt_engine_get_recognition_result_cb(&result_cb);
+       int ret = stt_engine_get_recognition_result_cb(&result_cb);
        if (STTE_ERROR_NONE == ret && NULL != result_cb) {
                ret = result_cb(event, type, result, result_count, msg, time_info, user_data);
        } else {
@@ -109,8 +232,9 @@ int stte_send_result(stte_result_event_e event, const char* type, const char** r
 
 int stte_send_error(stte_error_e error, const char* msg)
 {
-       int ret = STTE_ERROR_NONE;
-       ret = sttd_engine_agent_send_error(error, msg);
+       RETV_IF(false == is_feature_enabled(), STTE_ERROR_NOT_SUPPORTED);
+
+       int ret = sttd_engine_agent_send_error(error, msg);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to send error info");
        }
@@ -119,8 +243,9 @@ int stte_send_error(stte_error_e error, const char* msg)
 
 int stte_send_speech_status(stte_speech_status_e status, void* user_data)
 {
-       int ret = STTE_ERROR_NONE;
-       ret = sttd_engine_agent_send_speech_status(status, user_data);
+       RETV_IF(false == is_feature_enabled(), STTE_ERROR_NOT_SUPPORTED);
+
+       int ret = sttd_engine_agent_send_speech_status(status, user_data);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to send speech status");
        }
@@ -129,7 +254,12 @@ int stte_send_speech_status(stte_speech_status_e status, void* user_data)
 
 int stte_set_private_data_set_cb(stte_private_data_set_cb callback)
 {
-       int ret = STTE_ERROR_NONE;
+       int ret = check_feature_and_privilege();
+       if (STTE_ERROR_NONE != ret) {
+               SLOG(LOG_ERROR, TAG_STTD, "Precondition is not met (%s)", get_error_message(ret));
+               return ret;
+       }
+
        ret = stt_engine_set_private_data_set_cb(callback, NULL);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to set private data set callback");
@@ -139,7 +269,12 @@ int stte_set_private_data_set_cb(stte_private_data_set_cb callback)
 
 int stte_set_private_data_requested_cb(stte_private_data_requested_cb callback)
 {
-       int ret = STTE_ERROR_NONE;
+       int ret = check_feature_and_privilege();
+       if (STTE_ERROR_NONE != ret) {
+               SLOG(LOG_ERROR, TAG_STTD, "Precondition is not met (%s)", get_error_message(ret));
+               return ret;
+       }
+
        ret = stt_engine_set_private_data_requested_cb(callback, NULL);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to set private data requested callback");
@@ -150,9 +285,9 @@ int stte_set_private_data_requested_cb(stte_private_data_requested_cb callback)
 int stte_set_audio_type_set_cb(stte_audio_type_cb callback, void* user_data)
 {
        SLOG(LOG_INFO, TAG_STTD, "[Server Info] Set audio type set callback");
+       RETV_IF(false == is_feature_enabled(), STTE_ERROR_NOT_SUPPORTED);
 
-       int ret = STTE_ERROR_NONE;
-       ret = stt_engine_set_audio_type_set_cb(callback, user_data);
+       int ret = stt_engine_set_audio_type_set_cb(callback, user_data);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to set audio type set");
        }
@@ -162,9 +297,9 @@ int stte_set_audio_type_set_cb(stte_audio_type_cb callback, void* user_data)
 int stte_unset_audio_type_set_cb(void)
 {
        SLOG(LOG_INFO, TAG_STTD, "[Server Info] Unset audio type set callback");
+       RETV_IF(false == is_feature_enabled(), STTE_ERROR_NOT_SUPPORTED);
 
-       int ret = STTE_ERROR_NONE;
-       ret = stt_engine_unset_audio_type_set_cb();
+       int ret = stt_engine_unset_audio_type_set_cb();
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to unset audio type set");
        }