Change/check privilege 27/62627/3
authortaesubkim <taesub.kim@samsung.com>
Thu, 17 Mar 2016 06:22:18 +0000 (15:22 +0900)
committerDeepak Kumar Sahu <deepak.sahu@samsung.com>
Mon, 21 Mar 2016 08:26:21 +0000 (13:56 +0530)
Change-Id: I730cfb16b375d8d87137a7178014fbe96805168f
Signed-off-by: Taesub Kim <taesub.kim@samsung.com>
Signed-off-by: Deepak Kumar Sahu <deepak.sahu@samsung.com>
daemon/CMakeLists.txt
daemon/include/vpnsvc.h
daemon/src/vpnsvc.c
framework/src/capi_vpn_service.c
include/vpn_service.h
packaging/capi-vpn-service.spec

index e94f838..14e080d 100755 (executable)
@@ -9,7 +9,7 @@ SET(INCLUDEDIR "\${prefix}/include")
 SET(DAEMON_DIR "${CMAKE_SOURCE_DIR}/daemon")
 SET(VERSION 0.1)
 
-SET(requires "dlog dbus-1 glib-2.0 gio-2.0 gio-unix-2.0 capi-base-common capi-appfw-package-manager")
+SET(requires "dlog dbus-1 glib-2.0 gio-2.0 gio-unix-2.0 capi-base-common capi-appfw-package-manager cynara-client cynara-creds-gdbus cynara-session")
 SET(pc_requires "capi-base-common")
 
 SET(SRCS
index b6467a8..99c037f 100755 (executable)
@@ -30,8 +30,17 @@ extern "C" {
 
 #include "generated-code.h"
 
+typedef enum _net_vpn_service_privilege_e
+{
+       PRIVILEGE_VPN_SERVICE = 0x00,
+       PRIVILEGE_VPN_SERVICE_ADMIN,
+       PRIVILEGE_INTERNET,
+} net_vpn_service_privilege_e;
+
 void vpnsvc_create_and_init(void);
 Vpnsvc *get_vpnsvc_object(void);
+gboolean vpn_service_gdbus_check_privilege(GDBusMethodInvocation *invocation,
+       net_vpn_service_privilege_e _privilege);
 
 #ifdef __cplusplus
 }
index 4df05ae..be80c9f 100755 (executable)
 #include "vpndbus.h"
 #include "vpn_service_daemon.h"
 
+#include "cynara-client.h"
+#include "cynara-creds-gdbus.h"
+#include "cynara-session.h"
+
 #ifdef LOG_TAG
 #undef LOG_TAG
 #endif
@@ -43,8 +47,17 @@ gboolean handle_vpn_init(Vpnsvc *object,
 {
        LOGD("handle_vpn_init");
 
-       vpnsvc_tun_s handle_s;
        int result = VPNSVC_ERROR_NONE;
+
+       /* check privilege */
+       if (vpn_service_gdbus_check_privilege(invocation, PRIVILEGE_VPN_SERVICE_ADMIN) == false
+               || vpn_service_gdbus_check_privilege(invocation, PRIVILEGE_INTERNET) == false) {
+               LOGE("permission denied, and finished request.");
+               result = VPNSVC_ERROR_PERMISSION_DENIED;
+               goto done;
+       }
+
+       vpnsvc_tun_s handle_s;
        GDBusMessage *msg;
        GUnixFDList *fd_list;
        int fd_list_length;
@@ -66,6 +79,8 @@ gboolean handle_vpn_init(Vpnsvc *object,
        LOGD("handle_s.fd : %d, handle_s.index : %d, handle_s.name : %s",
                        handle_s.fd, handle_s.index, handle_s.name);
 
+done:
+
        vpnsvc_complete_vpn_init(object, invocation, result, handle_s.index, handle_s.name);
 
        return TRUE;
@@ -75,13 +90,23 @@ gboolean handle_vpn_deinit(Vpnsvc *object,
                                                                        GDBusMethodInvocation *invocation,
                                                                        const gchar *arg_dev_name)
 {
+       LOGD("handle_vpn_deinit");
+
        int result = VPNSVC_ERROR_NONE;
 
-       LOGD("handle_vpn_deinit");
+       /* check privilege */
+       if (vpn_service_gdbus_check_privilege(invocation, PRIVILEGE_VPN_SERVICE_ADMIN) == false
+               || vpn_service_gdbus_check_privilege(invocation, PRIVILEGE_INTERNET) == false) {
+               LOGE("permission denied, and finished request.");
+               result = VPNSVC_ERROR_PERMISSION_DENIED;
+               goto done;
+       }
+
        LOGD("vpn_deinit, %s\n", arg_dev_name);
 
        result = vpn_daemon_deinit(arg_dev_name);
 
+done:
        vpnsvc_complete_vpn_deinit(object, invocation, result);
 
        return TRUE;
@@ -91,15 +116,24 @@ gboolean handle_vpn_protect(Vpnsvc *object,
                                                                        GDBusMethodInvocation *invocation,
                                                                        const gchar *arg_dev_name)
 {
+       LOGD("handle_vpn_protect");
+
        int result = VPNSVC_ERROR_NONE;
+
+       /* check privilege */
+       if (vpn_service_gdbus_check_privilege(invocation, PRIVILEGE_VPN_SERVICE_ADMIN) == false
+               || vpn_service_gdbus_check_privilege(invocation, PRIVILEGE_INTERNET) == false) {
+               LOGE("permission denied, and finished request.");
+               result = VPNSVC_ERROR_PERMISSION_DENIED;
+               goto done;
+       }
+
        int socket;
        GDBusMessage *msg;
        GUnixFDList *fd_list;
        int fd_list_length;
        const int *fds;
 
-       LOGD("handle_vpn_protect");
-
        msg = g_dbus_method_invocation_get_message(invocation);
        fd_list = g_dbus_message_get_unix_fd_list(msg);
        fds = g_unix_fd_list_peek_fds(fd_list, &fd_list_length);
@@ -111,6 +145,7 @@ gboolean handle_vpn_protect(Vpnsvc *object,
 
        result = vpn_daemon_protect(socket, arg_dev_name);
 
+done:
        vpnsvc_complete_vpn_protect(object, invocation, result);
 
        return TRUE;
@@ -128,10 +163,10 @@ gboolean handle_vpn_up(Vpnsvc *object,
                                                                const gchar *arg_dns_suffix,
                                                                guint arg_mtu)
 {
-       int result = VPNSVC_ERROR_NONE;
-
        LOGD("handle_vpn_up");
 
+       int result = VPNSVC_ERROR_NONE;
+
        char* routes[arg_nr_routes];
        int prefix[arg_nr_routes];
        char **dns_servers = NULL;
@@ -144,6 +179,13 @@ gboolean handle_vpn_up(Vpnsvc *object,
        gchar* route_dest;
        gint route_prefix;
 
+       /* check privilege */
+       if (vpn_service_gdbus_check_privilege(invocation, PRIVILEGE_VPN_SERVICE_ADMIN) == false) {
+               LOGE("permission denied, and finished request.");
+               result = VPNSVC_ERROR_PERMISSION_DENIED;
+               goto done;
+       }
+
        LOGD("iface_index : %d", arg_iface_index);
        LOGD("local ip : %s", arg_local_ip);
        LOGD("remote ip : %s", arg_remote_ip);
@@ -222,12 +264,22 @@ gboolean handle_vpn_down(Vpnsvc *object,
                                                                        gint arg_iface_index)
 {
        LOGD("handle_vpn_down");
+
        int result = VPNSVC_ERROR_NONE;
 
+       /* check privilege */
+       if (vpn_service_gdbus_check_privilege(invocation, PRIVILEGE_VPN_SERVICE_ADMIN) == false) {
+               LOGE("permission denied, and finished request.");
+               result = VPNSVC_ERROR_PERMISSION_DENIED;
+               goto done;
+       }
+
        LOGD("vpn_down, %d\n", arg_iface_index);
 
        result = vpn_daemon_down(arg_iface_index);
 
+done:
+
        vpnsvc_complete_vpn_down(object, invocation, result);
 
        return TRUE;
@@ -241,6 +293,7 @@ gboolean handle_vpn_block_networks(Vpnsvc *object,
                                                                                        guint arg_nr_nets_orig)
 {
        LOGD("handle_vpn_block_networks");
+
        int result = VPNSVC_ERROR_NONE;
 
        char *nets_vpn[arg_nr_nets_vpn];
@@ -254,6 +307,14 @@ gboolean handle_vpn_block_networks(Vpnsvc *object,
        gchar* route_dest;
        gint route_prefix;
 
+       /* check privilege */
+       if (vpn_service_gdbus_check_privilege(invocation, PRIVILEGE_VPN_SERVICE_ADMIN) == false
+               || vpn_service_gdbus_check_privilege(invocation, PRIVILEGE_INTERNET) == false) {
+               LOGE("permission denied, and finished request.");
+               result = VPNSVC_ERROR_PERMISSION_DENIED;
+               goto done;
+       }
+
        LOGD("vpn_block_networks");
 
        /* arg_nets_vpn check */
@@ -299,6 +360,8 @@ gboolean handle_vpn_block_networks(Vpnsvc *object,
        /* call function */
        result = vpn_daemon_block_networks(nets_vpn, prefix_vpn, arg_nr_nets_vpn, nets_orig, prefix_orig, arg_nr_nets_orig);
 
+done:
+
        vpnsvc_complete_vpn_block_networks(object, invocation, result);
 
        return TRUE;
@@ -307,13 +370,23 @@ gboolean handle_vpn_block_networks(Vpnsvc *object,
 gboolean handle_vpn_unblock_networks(Vpnsvc *object,
                                                                                        GDBusMethodInvocation *invocation)
 {
+       LOGD("handle_vpn_unblock_networks");
+
        int result = VPNSVC_ERROR_NONE;
 
-       LOGD("handle_vpn_unblock_networks");
+       /* check privilege */
+       if (vpn_service_gdbus_check_privilege(invocation, PRIVILEGE_VPN_SERVICE_ADMIN) == false
+               || vpn_service_gdbus_check_privilege(invocation, PRIVILEGE_INTERNET) == false) {
+               LOGE("permission denied, and finished request.");
+               result = VPNSVC_ERROR_PERMISSION_DENIED;
+               goto done;
+       }
+
        LOGD("vpn_unblock_networks");
 
        result = vpn_daemon_unblock_networks();
 
+done:
        vpnsvc_complete_vpn_unblock_networks(object, invocation, result);
 
        return TRUE;
@@ -367,3 +440,71 @@ void vpnsvc_create_and_init(void)
        return;
 }
 
+
+gboolean vpn_service_gdbus_check_privilege(GDBusMethodInvocation *invocation, net_vpn_service_privilege_e _privilege)
+{
+
+       int ret = 0;
+       int pid = 0;
+       char *user;
+       char *client;
+       char *client_session;
+       char *privilege = NULL;
+       cynara *p_cynara = NULL;
+       const char *sender_unique_name;
+       GDBusConnection *connection;
+
+       connection = g_dbus_method_invocation_get_connection(invocation);
+       sender_unique_name = g_dbus_method_invocation_get_sender(invocation);
+
+       ret = cynara_initialize(&p_cynara, NULL);
+       if (ret != CYNARA_API_SUCCESS) {
+               LOGD("cynara_initialize() failed");
+               return FALSE;
+       }
+
+       ret =   cynara_creds_gdbus_get_pid(connection, sender_unique_name, &pid);
+       if (ret != CYNARA_API_SUCCESS) {
+               LOGD("cynara_creds_gdbus_get_pid() failed");
+               return FALSE;
+       }
+
+       ret = cynara_creds_gdbus_get_user(connection, sender_unique_name, USER_METHOD_DEFAULT, &user);
+       if (ret != CYNARA_API_SUCCESS) {
+               LOGD("cynara_creds_gdbus_get_user() failed");
+               return FALSE;
+       }
+
+       ret = cynara_creds_gdbus_get_client(connection, sender_unique_name, CLIENT_METHOD_DEFAULT, &client);
+       if (ret != CYNARA_API_SUCCESS) {
+               LOGD("cynara_creds_gdbus_get_client() failed");
+               return FALSE;
+       }
+
+       switch (_privilege)
+       {
+       case PRIVILEGE_VPN_SERVICE:
+               privilege = "http://tizen.org/privilege/vpnservice";
+       break;
+
+       case PRIVILEGE_VPN_SERVICE_ADMIN :
+               privilege = "http://tizen.org/privilege/vpnservice.admin";
+       break;
+
+       case PRIVILEGE_INTERNET :
+               privilege = "http://tizen.org/privilege/internet";
+       break;
+       default :
+               LOGD("Undifined privilege");
+               return FALSE;
+       break;
+       }
+
+       client_session = cynara_session_from_pid(pid);
+
+       ret = cynara_check(p_cynara, client, client_session, user, privilege);
+       if (ret == CYNARA_API_ACCESS_ALLOWED);
+               LOGD("cynara PASS");
+
+       return (ret == CYNARA_API_ACCESS_ALLOWED) ? TRUE : FALSE;
+}
index 2afd277..08e6aa6 100755 (executable)
@@ -145,13 +145,20 @@ GVariant *_vpnsvc_invoke_dbus_method(GDBusConnection *connection,
 
        if (reply == NULL) {
                if (error != NULL) {
-                       LOGE("g_dbus_connection_call_sync() failed" //LCOV_EXCL_LINE
-                                       "error [%d: %s]", error->code, error->message);
-                       *dbus_error = VPNSVC_ERROR_IO_ERROR; //LCOV_EXCL_LINE
-                       g_error_free(error); //LCOV_EXCL_LINE
+                       if (error->code == G_DBUS_ERROR_ACCESS_DENIED){
+                               LOGE("g_dbus_connection_call_sync() failed"
+                                       "error [%d: %s]", error->code, error->message);//LCOV_EXCL_LINE
+                               *dbus_error = VPNSVC_ERROR_PERMISSION_DENIED;//LCOV_EXCL_LINE
+                               g_error_free(error);//LCOV_EXCL_LINE
+                       } else {
+                               LOGE("g_dbus_connection_call_sync() failed"
+                                               "error [%d: %s]", error->code, error->message);//LCOV_EXCL_LINE
+                               *dbus_error = VPNSVC_ERROR_IO_ERROR;//LCOV_EXCL_LINE
+                               g_error_free(error);//LCOV_EXCL_LINE
+                       }
                } else {
-                       LOGE("g_dbus_connection_call_sync() failed"); //LCOV_EXCL_LINE
-                       *dbus_error = VPNSVC_ERROR_IPC_FAILED; //LCOV_EXCL_LINE
+                       LOGE("g_dbus_connection_call_sync() failed");//LCOV_EXCL_LINE
+                       *dbus_error = VPNSVC_ERROR_IPC_FAILED;//LCOV_EXCL_LINE
                }
 
                return NULL;
@@ -257,6 +264,10 @@ EXPORT_API int vpnsvc_init(const char* iface_name, vpnsvc_h *handle)
                                                                        g_variant_new("(su)", VPNSVC_DBUS_SERVICE_NAME, 0),
                                                                        &dbus_result);
 
+       if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED){
+               return VPNSVC_ERROR_PERMISSION_DENIED;
+       }
+
        if (op == NULL) {
                _vpnsvc_deinit_vpnsvc_tun_s(tmp_s); //LCOV_EXCL_LINE
                LOGD("Service [%s] Start Failed!", VPNSVC_DBUS_SERVICE_NAME); //LCOV_EXCL_LINE
@@ -355,6 +366,10 @@ EXPORT_API int vpnsvc_deinit(vpnsvc_h handle)
                                                                        g_variant_new("(s)", tun_s->name),
                                                                        &dbus_result);
 
+               if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED){
+                       return VPNSVC_ERROR_PERMISSION_DENIED;
+               }
+
                if (op == NULL) {
                        return VPNSVC_ERROR_IPC_FAILED; //LCOV_EXCL_LINE
                } else {
@@ -410,6 +425,10 @@ EXPORT_API int vpnsvc_protect(vpnsvc_h handle, int socket_fd, const char* iface_
                                                socket_fd,
                                                &dbus_result);
 
+       if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED){
+               return VPNSVC_ERROR_PERMISSION_DENIED;
+       }
+
        if (op == NULL) {
                return VPNSVC_ERROR_IPC_FAILED; //LCOV_EXCL_LINE
        } else {
@@ -688,6 +707,10 @@ EXPORT_API int vpnsvc_block_networks(vpnsvc_h handle,
                                                                nets_param_orig, num_allow_routes_orig),
                                                                &dbus_result);
 
+       if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED){
+               return VPNSVC_ERROR_PERMISSION_DENIED;
+       }
+
        if (op == NULL) {
                return VPNSVC_ERROR_IPC_FAILED; //LCOV_EXCL_LINE
        } else {
@@ -734,6 +757,10 @@ EXPORT_API int vpnsvc_unblock_networks(vpnsvc_h handle)
                                                                        g_variant_new("()"),
                                                                        &dbus_result);
 
+       if (dbus_result == VPNSVC_ERROR_PERMISSION_DENIED){
+               return VPNSVC_ERROR_PERMISSION_DENIED;
+       }
+
        if (op == NULL) {
                return VPNSVC_ERROR_IPC_FAILED; //LCOV_EXCL_LINE
        } else {
index c1091ef..adefef3 100755 (executable)
@@ -108,11 +108,15 @@ int vpnsvc_init(const char* iface_name, vpnsvc_h *handle);
 /**
  * @brief De-Initializes VPN interface.
  * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/vpnservice \n
+ *            %http://tizen.org/privilege/internet
  * @param[in] handle The VPN interface handle
  * @return 0 on success. otherwise, a negative error value.
  * @retval #VPNSVC_ERROR_NONE                  Success
  * @retval #VPNSVC_ERROR_INVALID_PARAMETER     Invalid parameter
  * @retval #VPNSVC_ERROR_IPC_FAILED            Cannot connect to service daemon
+ * @retval #VPNSVC_ERROR_PERMISSION_DENIED     Permission Denied
  * @retval #VPNSVC_ERROR_NOT_SUPPORTED         Not Supported
  * @pre Before calling this function, VPN interface should be initialized already.
  * @see vpnsvc_init()
@@ -123,6 +127,9 @@ int vpnsvc_deinit(vpnsvc_h handle);
  * @brief Protect a socket from VPN connections.
  * @details After protecting, data sent through this socket will go directly to the underlying network.
  * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/vpnservice \n
+ *            %http://tizen.org/privilege/internet
  * @param[in] handle    The VPN interface handle
  * @param[in] socket_fd The opened socket file descriptor
  * @param[in] iface_name  The network interface name (e.g., interface name such as eth0, ppp0, etc) through which the VPN is working
@@ -131,6 +138,7 @@ int vpnsvc_deinit(vpnsvc_h handle);
  * @retval #VPNSVC_ERROR_INVALID_PARAMETER     Invalid parameter
  * @retval #VPNSVC_ERROR_IO_ERROR              I/O Error (e.g. socket I/O error)
  * @retval #VPNSVC_ERROR_IPC_FAILED            Cannot connect to service daemon
+ * @retval #VPNSVC_ERROR_PERMISSION_DENIED     Permission Denied
  * @retval #VPNSVC_ERROR_NOT_SUPPORTED         Not Supported
  */
 int vpnsvc_protect(vpnsvc_h handle, int socket_fd, const char* iface_name);
@@ -170,6 +178,9 @@ int vpnsvc_write(vpnsvc_h handle, const char* data, size_t size);
 /**
  * @brief Blocks all traffics except specified allowing networks.
  * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/vpnservice \n
+ *            %http://tizen.org/privilege/internet
  * @param[in] handle                  The VPN interface handle
  * @param[in] routes_dest_vpn_addr    Destination address of the routes, the list of allowing networks over VPN interface (e.g., VPN interface such as tun0, etc).
  * @param[in] routes_vpn_prefix       The prefix of VPN interface, netmask length (also called a prefix, e.g. 8, 16, 24, 32).
@@ -181,6 +192,7 @@ int vpnsvc_write(vpnsvc_h handle, const char* data, size_t size);
  * @retval #VPNSVC_ERROR_NONE                  Success
  * @retval #VPNSVC_ERROR_INVALID_PARAMETER     Invalid parameter
  * @retval #VPNSVC_ERROR_IPC_FAILED            Cannot connect to service daemon
+ * @retval #VPNSVC_ERROR_PERMISSION_DENIED     Permission Denied
  * @retval #VPNSVC_ERROR_NOT_SUPPORTED         Not Supported
  * @post Please call vpnsvc_unblock_networks() if you want to allow all traffics.
  * @see vpnsvc_unblock_networks()
@@ -196,11 +208,15 @@ int vpnsvc_block_networks(vpnsvc_h handle,
 /**
  * @brief Removes any restrictions imposed by vpnsvc_block_networks().
  * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/vpnservice \n
+ *            %http://tizen.org/privilege/internet
  * @param[in] handle The VPN interface handle
  * @return 0 on success. otherwise, a negative error value.
  * @retval #VPNSVC_ERROR_NONE                  Success
  * @retval #VPNSVC_ERROR_INVALID_PARAMETER     Invalid parameter
  * @retval #VPNSVC_ERROR_IPC_FAILED            Cannot connect to service daemon
+ * @retval #VPNSVC_ERROR_PERMISSION_DENIED     Permission Denied
  * @retval #VPNSVC_ERROR_NOT_SUPPORTED         Not Supported
  */
 int vpnsvc_unblock_networks(vpnsvc_h handle);
index 9c6c00c..f2bcd0b 100755 (executable)
@@ -19,6 +19,9 @@ BuildRequires:  pkgconfig(capi-appfw-application)
 BuildRequires:  pkgconfig(capi-appfw-package-manager)
 BuildRequires:  pkgconfig(capi-appfw-app-manager)
 BuildRequires: pkgconfig(capi-system-info)
+BuildRequires: pkgconfig(cynara-client)
+BuildRequires: pkgconfig(cynara-creds-gdbus)
+BuildRequires: pkgconfig(cynara-session)
 Requires(post): /sbin/ldconfig
 Requires(postun): /sbin/ldconfig