Implement cynara API for check privilege 74/56474/8
authorJengHyun Kang <jhyuni.kang@samsung.com>
Mon, 1 Feb 2016 05:39:36 +0000 (14:39 +0900)
committerJengHyun Kang <jhyuni.kang@samsung.com>
Mon, 1 Feb 2016 12:05:12 +0000 (21:05 +0900)
Change-Id: I33b6522cae7aa3f10e373a132377bdc33cbb73e4

configure.ac
packaging/e-mod-tizen-keyrouter.spec
src/Makefile.am
src/e_mod_keyrouter_list.c
src/e_mod_main_wl.c
src/e_mod_main_wl.h

index d9f4106bcd1cea4fbbd0d665c91792ead2bed405..a03723629343b36af3e90cd3abbf1286f288a908 100644 (file)
@@ -129,6 +129,17 @@ AC_ARG_ENABLE(homedir-install,
        [ datadir="${HOME}/.e/e/modules/${PACKAGE}" ]
 )
 
+have_cynara=no
+AC_ARG_ENABLE(cynara,
+       AS_HELP_STRING([--enable-cynara], [enable cynara]),
+       [have_cynara=$enableval],
+       [have_cynara=no]
+)
+if test "x${have_cynara}" = "xyes"; then
+       PKG_CHECK_MODULES(CYNARA, [cynara-client, cynara-creds-socket, cynara-session])
+       AC_DEFINE([ENABLE_CYNARA],[1],[enable cynara])
+fi
+
 dnl ========================================================================
 # output files
 dnl ========================================================================
index 4fb3d9c6276b673b4e1bccb9fb660927807a25db..5783aa8e7d57f88f79e71036dba57294c75e799e 100644 (file)
@@ -21,6 +21,8 @@ BuildRequires:  pkgconfig(utilX)
 %if %{with wayland}
 BuildRequires:  pkgconfig(wayland-server)
 BuildRequires:  pkgconfig(tizen-extension-server)
+BuildRequires:  pkgconfig(cynara-client)
+BuildRequires:  pkgconfig(cynara-creds-socket)
 %endif
 BuildRequires:  pkgconfig(dlog)
 %if "%{?profile}" == "common"
index 44cdd1b6bcff88ecaf450ae0161013c48d314771..8a315fb63dabf34207ed6add85e43758bad9b017 100644 (file)
@@ -11,8 +11,8 @@ module_la_SOURCES      = e_mod_main_wl.c \
                          e_mod_keyrouter_list.c \
                          e_mod_keyrouter_events.c \
                          e_mod_keyrouter_conf.c
-module_la_CFLAGS       = @ENLIGHTENMENT_CFLAGS@ @WAYLAND_CFLAGS@ -DHAVE_WAYLAND_ONLY
-module_la_LDFLAGS      = -module -avoid-version @WAYLAND_LIBS@ @ENLIGHTENMENT_LIBS@
+module_la_CFLAGS       = @ENLIGHTENMENT_CFLAGS@ @WAYLAND_CFLAGS@ -DHAVE_WAYLAND_ONLY @CYNARA_CFLAGS@
+module_la_LDFLAGS      = -module -avoid-version @WAYLAND_LIBS@ @ENLIGHTENMENT_LIBS@ @CYNARA_LIBS@
 else
 module_la_SOURCES      = e_mod_main.c \
                          e_mod_main.h
index 9433981c8135b868763a7feec7530f39a21494ab..a444490665697808d76498200696eed1f9041690 100644 (file)
@@ -253,7 +253,13 @@ e_keyrouter_prepend_to_keylist(struct wl_resource *surface, struct wl_client *wc
              e_keyrouter_add_surface_destroy_listener(surface);
              /* TODO: if failed add surface_destory_listener, remove keygrabs */
           }
+        /* Add a client destroy listener if cynara is not enabled.
+           If cynara is enabled, client destroy listener is added at privilege checking time */
+#ifdef ENABLE_CYNARA
+        else if (!krt->p_cynara && wc)
+#else
         else if (wc)
+#endif
           {
              KLDBG("Add a client(%p) destory listener\n", wc);
              e_keyrouter_add_client_destroy_listener(wc);
index d7fa3266f2c37e36558bbe0b9faa57f1009a233b..fca84d4967fbb0cca8e4c4d431255474ab70b745 100644 (file)
@@ -21,12 +21,35 @@ static void _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data
 static int _e_keyrouter_keygrab_set(struct wl_client *client, struct wl_resource *surface, uint32_t key, uint32_t mode);
 static int _e_keyrouter_keygrab_unset(struct wl_client *client, struct wl_resource *surface, uint32_t key);
 
+#ifdef ENABLE_CYNARA
+static void _e_keyrouter_util_cynara_log(const char *func_name, int err);
+static Eina_Bool _e_keyrouter_util_do_privilege_check(struct wl_client *client, int socket_fd, uint32_t mode);
+
+#define E_KEYROUTER_CYNARA_ERROR_CHECK_GOTO(func_name, ret, label) \
+  do \
+    { \
+       if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret)) \
+          { \
+             _e_keyrouter_util_cynara_log(func_name, ret); \
+             goto label; \
+          } \
+    } \
+  while (0)
+#endif
 
 static int
 _e_keyrouter_keygrab_set(struct wl_client *client, struct wl_resource *surface, uint32_t key, uint32_t mode)
 {
    int res=0;
 
+#ifdef ENABLE_CYNARA
+   if (EINA_FALSE == _e_keyrouter_util_do_privilege_check(client,
+                       wl_client_get_fd(client), mode))
+     {
+        return TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
+     }
+#endif
+
    if (!surface)
      {
         /* Regarding topmost mode, a client must request to grab a key with a valid surface. */
@@ -75,6 +98,20 @@ _e_keyrouter_keygrab_set(struct wl_client *client, struct wl_resource *surface,
 static int
 _e_keyrouter_keygrab_unset(struct wl_client *client, struct wl_resource *surface, uint32_t key)
 {
+   /* Ungrab top position grabs first. This grab mode do not need privilege */
+   if (!surface)
+     e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_TOPMOST);
+   else
+     e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_TOPMOST);
+
+#ifdef ENABLE_CYNARA
+   if (EINA_FALSE == _e_keyrouter_util_do_privilege_check(client,
+                       wl_client_get_fd(client), TIZEN_KEYROUTER_MODE_NONE))
+     {
+        return TIZEN_KEYROUTER_ERROR_NONE;
+     }
+#endif
+
    if (!surface)
      {
         /* EXCLUSIVE grab */
@@ -83,9 +120,6 @@ _e_keyrouter_keygrab_unset(struct wl_client *client, struct wl_resource *surface
         /* OVERRIDABLE_EXCLUSIVE grab */
         e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE);
 
-        /* TOPMOST(TOP_POSITION) grab */
-        e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_TOPMOST);
-
         /* SHARED grab */
         e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_SHARED);
 
@@ -98,9 +132,6 @@ _e_keyrouter_keygrab_unset(struct wl_client *client, struct wl_resource *surface
    /* OVERRIDABLE_EXCLUSIVE grab */
    e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE);
 
-   /* TOPMOST(TOP_POSITION) grab */
-   e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_TOPMOST);
-
    /* SHARED grab */
    e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_SHARED);
 
@@ -226,7 +257,7 @@ e_keyrouter_add_client_destroy_listener(struct wl_client *client)
    Eina_List *l;
    struct wl_client *wc_data;
 
-   EINA_LIST_FOREACH(krt->none_surface_grab_client, l, wc_data)
+   EINA_LIST_FOREACH(krt->grab_client_list, l, wc_data)
      {
         if (wc_data)
           {
@@ -248,7 +279,7 @@ e_keyrouter_add_client_destroy_listener(struct wl_client *client)
 
    destroy_listener->notify = _e_keyrouter_wl_client_cb_destroy;
    wl_client_add_destroy_listener(client, destroy_listener);
-   krt->none_surface_grab_client = eina_list_append(krt->none_surface_grab_client, client);
+   krt->grab_client_list = eina_list_append(krt->grab_client_list, client);
 
    KLDBG("Add a wl_client(%p) destroy listener(%p)\n", client, destroy_listener);
 
@@ -263,7 +294,7 @@ e_keyrouter_add_surface_destroy_listener(struct wl_resource *surface)
    Eina_List *l;
    struct wl_resource *surface_data;
 
-   EINA_LIST_FOREACH(krt->surface_grab_client, l, surface_data)
+   EINA_LIST_FOREACH(krt->grab_surface_list, l, surface_data)
      {
         if (surface_data)
           {
@@ -285,7 +316,7 @@ e_keyrouter_add_surface_destroy_listener(struct wl_resource *surface)
 
    destroy_listener->notify = _e_keyrouter_wl_surface_cb_destroy;
    wl_resource_add_destroy_listener(surface, destroy_listener);
-   krt->surface_grab_client = eina_list_append(krt->surface_grab_client, surface);
+   krt->grab_surface_list = eina_list_append(krt->grab_surface_list, surface);
 
    KLDBG("Add a surface(%p) destroy listener(%p)\n", surface, destroy_listener);
 
@@ -353,6 +384,7 @@ _e_keyrouter_init(E_Module *m)
    E_Keyrouter_Config_Data *kconfig = NULL;
    krt = E_NEW(E_Keyrouter, 1);
    Eina_Bool res = EINA_FALSE;
+   int ret;
 
    if (!krt)
      {
@@ -390,6 +422,15 @@ _e_keyrouter_init(E_Module *m)
         goto err;
      }
 
+#ifdef ENABLE_CYNARA
+   ret = cynara_initialize(&krt->p_cynara, NULL);
+   if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
+     {
+        _e_keyrouter_util_cynara_log("cynara_initialize", ret);
+        krt->p_cynara = NULL;
+     }
+#endif
+
    return kconfig;
 
 err:
@@ -417,6 +458,10 @@ e_modapi_shutdown(E_Module *m)
    E_Keyrouter_Config_Data *kconfig = m->data;
    e_keyrouter_conf_deinit(kconfig);
    _e_keyrouter_deinit_handlers();
+
+#ifdef ENABLE_CYNARA
+   if (krt->p_cynara) cynara_finish(krt->p_cynara);
+#endif
    /* TODO: free allocated memory */
 
    return 1;
@@ -549,7 +594,7 @@ _e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data)
    E_FREE(l);
    l = NULL;
 
-   krt->none_surface_grab_client = eina_list_remove(krt->none_surface_grab_client, client);
+   krt->grab_client_list = eina_list_remove(krt->grab_client_list, client);
 }
 
 static void
@@ -563,5 +608,97 @@ _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data)
    E_FREE(l);
    l = NULL;
 
-   krt->surface_grab_client = eina_list_remove(krt->surface_grab_client, surface);
+   krt->grab_surface_list = eina_list_remove(krt->grab_surface_list, surface);
+}
+
+#ifdef ENABLE_CYNARA
+static void
+_e_keyrouter_util_cynara_log(const char *func_name, int err)
+{
+#define CYNARA_BUFSIZE 128
+   char buf[CYNARA_BUFSIZE] = "\0";
+   int ret;
+
+   ret = cynara_strerror(err, buf, CYNARA_BUFSIZE);
+   if (ret != CYNARA_API_SUCCESS)
+     {
+        KLDBG("Failed to cynara_strerror: %d (error log about %s: %d)\n", ret, func_name, err);
+        return;
+     }
+   KLDBG("%s is failed: %s\n", func_name, buf);
+}
+
+static Eina_Bool
+_e_keyrouter_util_do_privilege_check(struct wl_client *client, int socket_fd, uint32_t mode)
+{
+   int ret, pid, retry_cnt=0;
+   char *clientSmack=NULL, *uid=NULL, *client_session=NULL;
+   Eina_Bool res = EINA_FALSE;
+   Eina_List *l;
+   struct wl_client *wc_data;
+   static Eina_Bool retried = EINA_FALSE;
+
+   /* Top position grab is always allowed. This mode do not need privilege.*/
+   if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
+     return EINA_TRUE;
+
+   /* If initialize cynara is failed, allow keygrabs regardless of the previlege permition. */
+   if (krt->p_cynara == NULL)
+     {
+        if (retried == EINA_FALSE)
+          {
+             retried = EINA_TRUE;
+             for(retry_cnt = 0; retry_cnt < 5; retry_cnt++)
+               {
+                  KLDBG("Retry cynara initialize: %d\n", retry_cnt+1);
+                  ret = cynara_initialize(&krt->p_cynara, NULL);
+                  if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
+                    {
+                      _e_keyrouter_util_cynara_log("cynara_initialize", ret);
+                       krt->p_cynara = NULL;
+                    }
+                  else
+                    {
+                       KLDBG("Success cynara initialize to try %d times\n", retry_cnt+1);
+                       break;
+                    }
+               }
+          }
+        return EINA_TRUE;
+     }
+
+   EINA_LIST_FOREACH(krt->grab_client_list, l, wc_data)
+     {
+        if (wc_data == client)
+          {
+             res = EINA_TRUE;
+             goto finish;
+          }
+     }
+
+   ret = cynara_creds_socket_get_client(socket_fd, CLIENT_METHOD_SMACK, &clientSmack);
+   E_KEYROUTER_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_client", ret, finish);
+
+   ret = cynara_creds_socket_get_user(socket_fd, USER_METHOD_UID, &uid);
+   E_KEYROUTER_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_user", ret, finish);
+
+   ret = cynara_creds_socket_get_pid(socket_fd, &pid);
+   E_KEYROUTER_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_pid", ret, finish);
+
+   client_session = cynara_session_from_pid(pid);
+
+   ret = cynara_check(krt->p_cynara, clientSmack, client_session, uid, "http://tizen.org/privilege/keygrab");
+   if (CYNARA_API_ACCESS_ALLOWED == ret)
+     {
+        res = EINA_TRUE;
+        e_keyrouter_add_client_destroy_listener(client);
+     }
+
+finish:
+   E_FREE(client_session);
+   E_FREE(clientSmack);
+   E_FREE(uid);
+
+   return res;
 }
+#endif
index d4278ba08ed6c189518e3ba6f2c00ef2b1e38251..fe24886c259a9c477c6b7b409b9699d0afdb1dd6 100644 (file)
@@ -2,6 +2,11 @@
 #define E_MOD_MAIN_H
 
 #include <tizen-extension-server-protocol.h>
+#ifdef ENABLE_CYNARA
+#include <cynara-session.h>
+#include <cynara-client.h>
+#include <cynara-creds-socket.h>
+#endif
 
 /* Temporary value of maximum number of HWKeys */
 
@@ -84,14 +89,17 @@ struct _E_Keyrouter
    E_Keyrouter_Config_Data *conf;
 
    E_Keyrouter_Grabbed_Key *HardKeys;
-   Eina_List *surface_grab_client;
-   Eina_List *none_surface_grab_client;
+   Eina_List *grab_surface_list;
+   Eina_List *grab_client_list;
 
    Eina_List *registered_window_list;
 
    Eina_Bool isWindowStackChanged;
    int numTizenHWKeys;
    int max_tizen_hwkeys;
+#ifdef ENABLE_CYNARA
+   cynara *p_cynara;
+#endif
 };
 
 struct _E_Keyrouter_Grab_Request {