From d5248e51cd922ca070b2bcfb6b341943416269b2 Mon Sep 17 00:00:00 2001 From: Donghee Ye Date: Sat, 7 Sep 2013 21:09:43 +0900 Subject: [PATCH] Add user space access control Check resource access permission Fix contacts_connect_on_thread - without calling contacts_connect2 module can use contacts APIs Change-Id: I592ec0c9c0096e1e6ad57f687c24f0042ba89b41 --- CMakeLists.txt | 5 +- client/ctsvc_client_ipc.c | 208 ++++++++++++++++++++----------- client/ctsvc_client_noti.c | 24 +++- client/ctsvc_client_service.c | 52 +++++--- common/ctsvc_inotify.c | 37 +++++- common/ctsvc_internal.h | 4 +- common/ctsvc_mutex.c | 4 + common/ctsvc_mutex.h | 1 + common/ctsvc_socket.c | 51 +++++--- contacts-service2.manifest | 52 +++++++- contacts-service2.rule | 18 +++ native/CMakeLists.txt | 2 +- native/ctsvc_activity.c | 167 +++++++++++++------------ native/ctsvc_db_access_control.c | 210 ++++++++++++++++++++++++++++++++ native/ctsvc_db_access_control.h | 39 ++++++ native/ctsvc_db_init.c | 121 +++++++++++------- native/ctsvc_db_init.h | 3 + native/ctsvc_db_plugin_addressbook.c | 1 + native/ctsvc_db_plugin_company_helper.c | 25 ++++ native/ctsvc_db_plugin_contact.c | 12 +- native/ctsvc_db_plugin_contact_helper.c | 10 +- native/ctsvc_db_plugin_contact_helper.h | 2 + native/ctsvc_db_plugin_group.c | 29 +++++ native/ctsvc_db_plugin_image.c | 18 ++- native/ctsvc_db_plugin_image_helper.c | 12 +- native/ctsvc_db_plugin_simple_contact.c | 18 +++ native/ctsvc_db_query.c | 32 +++++ native/ctsvc_group.c | 14 ++- native/ctsvc_person.c | 52 +++++++- native/ctsvc_phonelog.c | 5 + native/ctsvc_service.c | 115 +++++++++++++++-- native/ctsvc_setting.c | 10 ++ packaging/contacts-service.spec | 7 +- server/CMakeLists.txt | 3 +- server/ctsvc_ipc_server.c | 56 ++++++++- server/ctsvc_server.c | 4 + server/ctsvc_server_bg.c | 5 + server/ctsvc_server_socket.c | 23 +++- 38 files changed, 1180 insertions(+), 271 deletions(-) create mode 100644 contacts-service2.rule create mode 100644 native/ctsvc_db_access_control.c create mode 100644 native/ctsvc_db_access_control.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 90c0343..8fe4a08 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ SET(PC_REQUIRED "capi-base-common") SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -I${SRC_INCLUDE_DIR}") INCLUDE(FindPkgConfig) -pkg_check_modules(pkgs REQUIRED glib-2.0 capi-base-common vconf dlog db-util icu-i18n) +pkg_check_modules(pkgs REQUIRED glib-2.0 capi-base-common vconf dlog db-util icu-i18n security-server) FOREACH(flag ${pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") @@ -57,6 +57,9 @@ INSTALL(FILES ${HEADER_FILES} DESTINATION ${DEST_INCLUDE_DIR}) FILE(GLOB DB_FILES ${CMAKE_CURRENT_SOURCE_DIR}/build-util/.contacts-svc.db*) INSTALL(FILES ${DB_FILES} DESTINATION /opt/usr/dbspace) +#Install SMACK rule file +INSTALL(FILES ${CMAKE_SOURCE_DIR}/contacts-service2.rule DESTINATION /opt/etc/smack/accesses.d) + ADD_SUBDIRECTORY(client) ADD_SUBDIRECTORY(server) diff --git a/client/ctsvc_client_ipc.c b/client/ctsvc_client_ipc.c index 6d2bece..2475501 100644 --- a/client/ctsvc_client_ipc.c +++ b/client/ctsvc_client_ipc.c @@ -1,7 +1,25 @@ - +/* + * Contacts Service + * + * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ #include #include +#include #include "ctsvc_client_ipc.h" @@ -11,7 +29,6 @@ #include "ctsvc_query.h" #include "ctsvc_inotify.h" -#include "ctsvc_internal.h" #include "ctsvc_ipc_define.h" #include "ctsvc_ipc_marshal.h" #include "ctsvc_view.h" @@ -23,6 +40,63 @@ static pims_ipc_h __contacts_global_ipc = NULL; static __thread int __contacts_change_version = 0; static int __contacts_global_change_version = 0; +static int __ctsvc_ipc_get_cookie_for_access_control(pims_ipc_data_h *indata) +{ + int ret; + size_t cookie_size = 0; + pims_ipc_data_h data; + char *buf; + + // Access control : get cookie from security-server + cookie_size = security_server_get_cookie_size(); + if (cookie_size <= 0) { + CTS_ERR("security_server_get_cookie_size"); + return CONTACTS_ERROR_SYSTEM; + } + + char cookie[cookie_size]; + cookie[0] = '\0'; + ret = security_server_request_cookie(cookie, cookie_size); + if(ret < 0) { + CTS_ERR("security_server_request_cookie fail (%d)", ret); + return CONTACTS_ERROR_SYSTEM; + } + + // Access control : put cookie to indata + data = pims_ipc_data_create(0); + if (data == NULL) { + CTS_ERR("ipc data created fail!"); + return CONTACTS_ERROR_OUT_OF_MEMORY; + } + + ret = ctsvc_ipc_marshal_unsigned_int(cookie_size, data); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_ipc_marshal_int fail"); + pims_ipc_data_destroy(data); + return ret; + } + + buf = g_base64_encode((const guchar *)cookie, cookie_size); + if (buf) { + ret = ctsvc_ipc_marshal_string(buf, data); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_ipc_marshal_string fail"); + pims_ipc_data_destroy(data); + return ret; + } + free(buf); + } + else { + CTS_ERR("g_base64_encode fail"); + pims_ipc_data_destroy(data); + return CONTACTS_ERROR_INTERNAL; + } + + *indata = data; + + return CONTACTS_ERROR_NONE; +} + int ctsvc_ipc_connect_on_thread(void) { int ret = CONTACTS_ERROR_NONE; @@ -37,80 +111,83 @@ int ctsvc_ipc_connect_on_thread(void) return CONTACTS_ERROR_IPC_NOT_AVALIABLE; } } - else - { + else { CTS_DBG("contacts already connected"); return CONTACTS_ERROR_NONE; } + ret = __ctsvc_ipc_get_cookie_for_access_control(&indata); + if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("__ctsvc_ipc_get_cookie_for_access_control fail (%d)", ret); + goto DATA_FREE; + } + // ipc call - if (pims_ipc_call(__contacts_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_CONNECT, indata, &outdata) != 0) - { + if (pims_ipc_call(__contacts_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_CONNECT, indata, &outdata) != 0) { CTS_ERR("pims_ipc_call failed"); - return CONTACTS_ERROR_IPC; + pims_ipc_data_destroy(indata); + ret = CONTACTS_ERROR_IPC; + goto DATA_FREE; } - if (outdata) - { - // check outdata + pims_ipc_data_destroy(indata); + + if (outdata) { unsigned int size = 0; ret = *(int*) pims_ipc_data_get(outdata,&size); pims_ipc_data_destroy(outdata); - if (ret == CONTACTS_ERROR_NONE) - { - - } - else - { - pims_ipc_destroy(__contacts_ipc); - __contacts_ipc = NULL; + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_ipc_server_connect return(%d)", ret); + goto DATA_FREE; } } return ret; + +DATA_FREE: + pims_ipc_destroy(__contacts_ipc); + __contacts_ipc = NULL; + + return ret; } int ctsvc_ipc_disconnect_on_thread(void) { int ret = CONTACTS_ERROR_NONE; - pims_ipc_data_h indata = NULL; pims_ipc_data_h outdata = NULL; RETVM_IF(__contacts_ipc == NULL, CONTACTS_ERROR_IPC, "contacts not connected"); - // ipc call - if (pims_ipc_call(__contacts_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_DISCONNECT, indata, &outdata) != 0) - { + if (pims_ipc_call(__contacts_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_DISCONNECT, NULL, &outdata) != 0) { CTS_ERR("pims_ipc_call failed"); return CONTACTS_ERROR_IPC; } - if (outdata) - { - // check outdata + if (outdata) { unsigned int size = 0; ret = *(int*) pims_ipc_data_get(outdata,&size); - pims_ipc_data_destroy(outdata); - } - if (__contacts_ipc && ret != CONTACTS_ERROR_NONE) - { + if (ret != CONTACTS_ERROR_NONE) + CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc didn't destroyed!!!(%d)", ret); + pims_ipc_destroy(__contacts_ipc); __contacts_ipc = NULL; } + else { + CTS_ERR("pims_ipc_call out data is NULL"); + return CONTACTS_ERROR_IPC; + } return ret; } pims_ipc_h ctsvc_get_ipc_handle() { - if(__contacts_ipc == NULL) - { - if(__contacts_global_ipc == NULL ) - { + if(__contacts_ipc == NULL) { + if(__contacts_global_ipc == NULL ) { ASSERT_NOT_REACHED("IPC haven't been initialized yet."); return NULL; } @@ -125,20 +202,15 @@ bool ctsvc_ipc_is_busy() { bool ret = false; - if(__contacts_ipc != NULL) - { + if(__contacts_ipc != NULL) { ret = pims_ipc_is_call_in_progress(__contacts_ipc); - if(ret) - { + if (ret) CTS_ERR("thread local ipc channel is busy."); - } } else { ret = pims_ipc_is_call_in_progress(__contacts_global_ipc); - if(ret) - { + if (ret) CTS_ERR("global ipc channel is busy."); - } } return ret; @@ -163,29 +235,37 @@ int ctsvc_ipc_connect(void) return CONTACTS_ERROR_NONE; } + ret = __ctsvc_ipc_get_cookie_for_access_control(&indata); + if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("__ctsvc_ipc_get_cookie_for_access_control fail (%d)", ret); + goto DATA_FREE; + } + // ipc call if (pims_ipc_call(__contacts_global_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_CONNECT, indata, &outdata) != 0) { CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc_call failed"); - return CONTACTS_ERROR_IPC; + pims_ipc_data_destroy(indata); + ret = CONTACTS_ERROR_IPC; + goto DATA_FREE; } + pims_ipc_data_destroy(indata); + if (outdata) { - // check outdata unsigned int size = 0; ret = *(int*) pims_ipc_data_get(outdata,&size); pims_ipc_data_destroy(outdata); - if (ret == CONTACTS_ERROR_NONE) - { - - } - else - { - pims_ipc_destroy(__contacts_global_ipc); - __contacts_global_ipc = NULL; + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_ipc_server_connect return(%d)", ret); + goto DATA_FREE; } } + return ret; +DATA_FREE: + pims_ipc_destroy(__contacts_global_ipc); + __contacts_global_ipc = NULL; return ret; } @@ -193,35 +273,29 @@ int ctsvc_ipc_connect(void) int ctsvc_ipc_disconnect(void) { int ret = CONTACTS_ERROR_NONE; - pims_ipc_data_h indata = NULL; pims_ipc_data_h outdata = NULL; RETVM_IF(__contacts_global_ipc == NULL, CONTACTS_ERROR_IPC, "[GLOBAL_IPC_CHANNEL] contacts not connected"); - // ipc call - if (pims_ipc_call(__contacts_global_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_DISCONNECT, indata, &outdata) != 0) - { + if (pims_ipc_call(__contacts_global_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_DISCONNECT, NULL, &outdata) != 0) { CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc_call failed"); return CONTACTS_ERROR_IPC; } - if (outdata) - { - // check outdata + if (outdata) { unsigned int size = 0; ret = *(int*) pims_ipc_data_get(outdata,&size); - pims_ipc_data_destroy(outdata); - } - if (__contacts_global_ipc && ret == CONTACTS_ERROR_NONE) - { + if (ret != CONTACTS_ERROR_NONE) + CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc didn't destroyed!!!(%d)", ret); + pims_ipc_destroy(__contacts_global_ipc); __contacts_global_ipc = NULL; } - else - { - CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc didn't destroyed!!!(%d)", ret); + else { + CTS_ERR("pims_ipc_call out data is NULL"); + return CONTACTS_ERROR_IPC; } return ret; @@ -230,17 +304,13 @@ int ctsvc_ipc_disconnect(void) static void __ctsvc_ipc_lock() { if (__contacts_ipc == NULL) - { ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_CALL); - } } static void __ctsvc_ipc_unlock(void) { if (__contacts_ipc == NULL) - { ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_CALL); - } } int ctsvc_ipc_call(char *module, char *function, pims_ipc_h data_in, pims_ipc_data_h *data_out) diff --git a/client/ctsvc_client_noti.c b/client/ctsvc_client_noti.c index 4d7df5e..8bc9a11 100644 --- a/client/ctsvc_client_noti.c +++ b/client/ctsvc_client_noti.c @@ -38,6 +38,7 @@ typedef struct GSList *callbacks; }subscribe_info_s; +static int __ipc_pubsub_ref = 0; static pims_ipc_h __ipc = NULL; static GSList *__db_change_subscribe_list = NULL; @@ -74,6 +75,12 @@ int ctsvc_ipc_create_for_change_subscription() { ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB); + if (0 < __ipc_pubsub_ref) { + __ipc_pubsub_ref++; + ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB); + return CONTACTS_ERROR_NONE; + } + if (!__ipc) { __ipc = pims_ipc_create_for_subscribe(CTSVC_IPC_SOCKET_PATH_FOR_CHANGE_SUBSCRIPTION); if (!__ipc) { @@ -82,6 +89,7 @@ int ctsvc_ipc_create_for_change_subscription() return CONTACTS_ERROR_IPC; } } + __ipc_pubsub_ref++; ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB); return CONTACTS_ERROR_NONE; } @@ -90,8 +98,20 @@ int ctsvc_ipc_destroy_for_change_subscription() { ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_PUBSUB); - pims_ipc_destroy_for_subscribe(__ipc); - __ipc = NULL; + if (1 == __ipc_pubsub_ref) { + pims_ipc_destroy_for_subscribe(__ipc); + __ipc = NULL; + } + else if (1 < __ipc_pubsub_ref) { + CTS_DBG("ctsvc pubsub ipc ref count : %d", __ipc_pubsub_ref); + } + else { + CTS_DBG("System : please call connection APIs, connection count is (%d)", __ipc_pubsub_ref); + ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB); + return CONTACTS_ERROR_INVALID_PARAMETER; + } + + __ipc_pubsub_ref--; ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB); return CONTACTS_ERROR_NONE; diff --git a/client/ctsvc_client_service.c b/client/ctsvc_client_service.c index 54964a8..e940786 100644 --- a/client/ctsvc_client_service.c +++ b/client/ctsvc_client_service.c @@ -148,14 +148,33 @@ API int contacts_connect_on_thread() ctsvc_mutex_lock(CTS_MUTEX_CONNECTION); - ret = ctsvc_ipc_connect_on_thread(); - if (ret != CONTACTS_ERROR_NONE) { - CTS_ERR("ctsvc_ipc_connect_on_thread() Failed(%d)", ret); - ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); - return ret; - } + if (0 == ctsvc_connection_on_thread) { + ret = ctsvc_ipc_connect_on_thread(); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_ipc_connect_on_thread() Failed(%d)", ret); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); + return ret; + } + + ret = ctsvc_socket_init(); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_socket_init() Failed(%d)", ret); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); + return ret; + } - if (0 < ctsvc_connection_on_thread) + ret = ctsvc_inotify_init(); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_inotify_init() Failed(%d)", ret); + ctsvc_socket_final(); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); + return ret; + } + + ctsvc_view_uri_init(); + ctsvc_ipc_create_for_change_subscription(); + } + else if (0 < ctsvc_connection_on_thread) CTS_DBG("System : Contacts service has been already connected"); ctsvc_connection_on_thread++; @@ -171,14 +190,19 @@ API int contacts_disconnect_on_thread() ctsvc_mutex_lock(CTS_MUTEX_CONNECTION); - ret = ctsvc_ipc_disconnect_on_thread(); - if (ret != CONTACTS_ERROR_NONE) { - CTS_ERR("ctsvc_ipc_disconnect_on_thread() Failed(%d)", ret); - ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); - return ret; - } - if (1 == ctsvc_connection_on_thread) { + ctsvc_ipc_destroy_for_change_subscription(); + + ret = ctsvc_ipc_disconnect_on_thread(); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_ipc_disconnect_on_thread() Failed(%d)", ret); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); + return ret; + } + + ctsvc_view_uri_deinit(); + ctsvc_inotify_close(); + ctsvc_socket_final(); CTS_DBG("System : connection_on_thread was destroyed successfully"); } else if (1 < ctsvc_connection_on_thread) { diff --git a/common/ctsvc_inotify.c b/common/ctsvc_inotify.c index c479ba6..cddcbf6 100755 --- a/common/ctsvc_inotify.c +++ b/common/ctsvc_inotify.c @@ -44,6 +44,7 @@ typedef struct bool blocked; }noti_info; +static int __ctsvc_inoti_ref = 0; static int __inoti_fd = -1; static guint __inoti_handler = 0; static GSList *__noti_list = NULL; @@ -151,6 +152,11 @@ static inline int __ctsvc_inotify_attach_handler(int fd) int ctsvc_inotify_init(void) { int ret; + + if (0 < __ctsvc_inoti_ref) { + __ctsvc_inoti_ref++; + return CONTACTS_ERROR_NONE; + } __inoti_fd = inotify_init(); RETVM_IF(-1 == __inoti_fd, CONTACTS_ERROR_SYSTEM, "System: inotify_init() Failed(%d)", errno); @@ -169,6 +175,7 @@ int ctsvc_inotify_init(void) return CONTACTS_ERROR_SYSTEM; } + __ctsvc_inoti_ref++; return CONTACTS_ERROR_NONE; } @@ -266,8 +273,12 @@ int ctsvc_inotify_subscribe(const char *view_uri, "__ctsvc_noti_get_file_path(%s) Failed", view_uri); wd = __ctsvc_inotify_get_wd(__inoti_fd, path); - RETVM_IF(-1 == wd, CONTACTS_ERROR_SYSTEM, - "__ctsvc_inotify_get_wd() Failed(%d)", errno); + if (-1 == wd) { + CTS_ERR("__ctsvc_inotify_get_wd() Failed(errno : %d)", errno); + if (errno == EACCES) + return CONTACTS_ERROR_PERMISSION_DENIED; + return CONTACTS_ERROR_SYSTEM; + } for (it=__noti_list;it;it=it->next) { if (it->data) { @@ -282,7 +293,7 @@ int ctsvc_inotify_subscribe(const char *view_uri, if (same_noti) { __ctsvc_inotify_watch(__inoti_fd, path); - CTS_ERR("The same callback(%s) is already exist", path); + CTS_ERR("The same callback(%s) is already exist", view_uri); return CONTACTS_ERROR_SYSTEM; } @@ -352,8 +363,12 @@ int ctsvc_inotify_unsubscribe(const char *view_uri, contacts_db_changed_cb cb, v "__ctsvc_noti_get_file_path(%s) Failed", view_uri); wd = __ctsvc_inotify_get_wd(__inoti_fd, path); - RETVM_IF(-1 == wd, CONTACTS_ERROR_SYSTEM, - "System: __ctsvc_inotify_get_wd() Failed(%d)", errno); + if (-1 == wd) { + CTS_ERR("__ctsvc_inotify_get_wd() Failed(errno : %d)", errno); + if (errno == EACCES) + return CONTACTS_ERROR_PERMISSION_DENIED; + return CONTACTS_ERROR_SYSTEM; + } ret = __ctsvc_del_noti(&__noti_list, wd, view_uri, cb, user_data); WARN_IF(ret < CONTACTS_ERROR_NONE, "__ctsvc_del_noti() Failed(%d)", ret); @@ -379,6 +394,18 @@ static inline gboolean __ctsvc_inotify_detach_handler(guint id) void ctsvc_inotify_close(void) { + if (1 < __ctsvc_inoti_ref) { + CTS_DBG("inotify ref count : %d", __ctsvc_inoti_ref); + __ctsvc_inoti_ref--; + return; + } + else if (__ctsvc_inoti_ref < 1) { + CTS_DBG("Please call connection API. inotify ref count : %d", __ctsvc_inoti_ref); + return; + } + + __ctsvc_inoti_ref--; + if (__inoti_handler) { __ctsvc_inotify_detach_handler(__inoti_handler); __inoti_handler = 0; diff --git a/common/ctsvc_internal.h b/common/ctsvc_internal.h index 2180941..bc86fb4 100644 --- a/common/ctsvc_internal.h +++ b/common/ctsvc_internal.h @@ -32,9 +32,9 @@ #include "ctsvc_view.h" #ifdef API -#define API __attribute__ ((visibility("default"))) -//#undef API +#undef API #endif +#define API __attribute__ ((visibility("default"))) //#define CONTACTS_DEBUGGING //#define CONTACTS_TIMECHECK diff --git a/common/ctsvc_mutex.c b/common/ctsvc_mutex.c index bf7d8fd..9209f61 100755 --- a/common/ctsvc_mutex.c +++ b/common/ctsvc_mutex.c @@ -40,6 +40,7 @@ static pthread_mutex_t sockfd_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t trans_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t ipc_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t ipc_pubsub_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t access_control_mutex = PTHREAD_MUTEX_INITIALIZER; static inline pthread_mutex_t* cts_mutex_get_mutex(int type) { @@ -61,6 +62,9 @@ static inline pthread_mutex_t* cts_mutex_get_mutex(int type) case CTS_MUTEX_PIMS_IPC_PUBSUB: ret_val = &ipc_pubsub_mutex; break; + case CTS_MUTEX_ACCESS_CONTROL: + ret_val = &access_control_mutex; + break; default: CTS_ERR("unknown type(%d)", type); ret_val = NULL; diff --git a/common/ctsvc_mutex.h b/common/ctsvc_mutex.h index 21de5df..011785b 100755 --- a/common/ctsvc_mutex.h +++ b/common/ctsvc_mutex.h @@ -28,6 +28,7 @@ enum { CTS_MUTEX_TRANSACTION, CTS_MUTEX_PIMS_IPC_CALL, CTS_MUTEX_PIMS_IPC_PUBSUB, + CTS_MUTEX_ACCESS_CONTROL, }; void ctsvc_mutex_lock(int type); diff --git a/common/ctsvc_socket.c b/common/ctsvc_socket.c index 72312e3..2fd1255 100644 --- a/common/ctsvc_socket.c +++ b/common/ctsvc_socket.c @@ -28,37 +28,54 @@ #include "ctsvc_mutex.h" #include "ctsvc_inotify.h" -//static int ctsvc_conn_refcnt = 0; -static int cts_csockfd = -1; +static int ctsvc_conn_refcnt = 0; +static int cts_sockfd = -1; int ctsvc_socket_init(void) { int ret; struct sockaddr_un caddr; + if (0 < ctsvc_conn_refcnt) { + ctsvc_conn_refcnt++; + return CONTACTS_ERROR_NONE; + } + bzero(&caddr, sizeof(caddr)); caddr.sun_family = AF_UNIX; snprintf(caddr.sun_path, sizeof(caddr.sun_path), "%s", CTSVC_SOCKET_PATH); - cts_csockfd = socket(PF_UNIX, SOCK_STREAM, 0); - RETVM_IF(-1 == cts_csockfd, CONTACTS_ERROR_IPC, + cts_sockfd = socket(PF_UNIX, SOCK_STREAM, 0); + RETVM_IF(-1 == cts_sockfd, CONTACTS_ERROR_IPC, "socket() Failed(errno = %d)", errno); - ret = connect(cts_csockfd, (struct sockaddr *)&caddr, sizeof(caddr)); + ret = connect(cts_sockfd, (struct sockaddr *)&caddr, sizeof(caddr)); if (-1 == ret) { CTS_ERR("connect() Failed(errno = %d)", errno); - close(cts_csockfd); - cts_csockfd = -1; + close(cts_sockfd); + cts_sockfd = -1; return CONTACTS_ERROR_IPC; } + ctsvc_conn_refcnt++; return CONTACTS_ERROR_NONE; } void ctsvc_socket_final(void) { - close(cts_csockfd); - cts_csockfd = -1; + if (1 < ctsvc_conn_refcnt) { + CTS_DBG("socket ref count : %d", ctsvc_conn_refcnt); + ctsvc_conn_refcnt--; + return; + } + else if (ctsvc_conn_refcnt < 1) { + CTS_DBG("Please call connection API. socket ref count : %d", ctsvc_conn_refcnt); + return; + } + ctsvc_conn_refcnt--; + + close(cts_sockfd); + cts_sockfd = -1; } static inline int __ctsvc_safe_write(int fd, const char *buf, int buf_size) @@ -150,18 +167,18 @@ int ctsvc_request_sim_import(void) int i, ret; ctsvc_socket_msg_s msg = {0}; - RETVM_IF(-1 == cts_csockfd, CONTACTS_ERROR_IPC, "socket is not connected"); + RETVM_IF(-1 == cts_sockfd, CONTACTS_ERROR_IPC, "socket is not connected"); msg.type = CTSVC_SOCKET_MSG_TYPE_REQUEST_IMPORT_SIM; - ret = __ctsvc_safe_write(cts_csockfd, (char *)&msg, sizeof(msg)); + ret = __ctsvc_safe_write(cts_sockfd, (char *)&msg, sizeof(msg)); RETVM_IF(-1 == ret, CONTACTS_ERROR_IPC, "__ctsvc_safe_write() Failed(errno = %d)", errno); - ret = __ctsvc_socket_handle_return(cts_csockfd, &msg); + ret = __ctsvc_socket_handle_return(cts_sockfd, &msg); RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "__ctsvc_socket_handle_return() Failed(%d)", ret); CTS_DBG("attach_num = %d", msg.attach_num); for (i=0;i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/contacts-service2.rule b/contacts-service2.rule new file mode 100644 index 0000000..fc9dc81 --- /dev/null +++ b/contacts-service2.rule @@ -0,0 +1,18 @@ +contacts-service _ arwxt +contacts-service system::vconf arwx +contacts-service contacts-service::db rw +contacts-service contacts-service::svc rw +contacts-service contacts-service::phonelog rw +contacts-service contacts-service::vconf arwx +contacts-service contacts-service::vconf-private arwx +contacts-service calendar-service x +contacts-service device::sys_logging w +contacts-service device::app_logging w +contacts-service system::media arwxt +contacts-service system::ext_storage arwxt +contacts-service system::homedir arwxt +contacts-service system::share arwxt +contacts-service ail::db rw +contacts-service badge::db rw +contacts-service data-provider-master::badge rw + diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index 3192101..0bf0290 100755 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -6,7 +6,7 @@ SET(NATIVE contacts-service3) FILE(GLOB SRCS *.c ../common/*.c) INCLUDE(FindPkgConfig) -pkg_check_modules(service_pkgs REQUIRED sqlite3 db-util capi-media-image-util accounts-svc badge libexif) +pkg_check_modules(service_pkgs REQUIRED sqlite3 db-util capi-media-image-util accounts-svc badge libexif libsmack) FOREACH(flag ${service_pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") diff --git a/native/ctsvc_activity.c b/native/ctsvc_activity.c index 1c7cb25..ea3eef4 100644 --- a/native/ctsvc_activity.c +++ b/native/ctsvc_activity.c @@ -1,81 +1,86 @@ -/* - * Contacts Service - * - * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "contacts.h" -#include "ctsvc_internal.h" -#include "ctsvc_schema.h" -#include "ctsvc_sqlite.h" -#include "ctsvc_utils.h" -#include "ctsvc_db_plugin_contact_helper.h" -#include "ctsvc_notification.h" - -API int contacts_activity_delete_by_contact_id(int contact_id) -{ - char query[CTS_SQL_MAX_LEN] = {0}; - - RETV_IF(contact_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER); - - snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_ACTIVITIES" WHERE contact_id = %d", contact_id); - - int ret = ctsvc_begin_trans(); - RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_begin_trans() Failed(%d)", ret); - - ret = ctsvc_query_exec(query); - if (CONTACTS_ERROR_NONE != ret) { - CTS_ERR("cts_query_exec() Failed(%d)", ret); - ctsvc_end_trans(false); - return ret; - } - - ctsvc_set_activity_noti(); - ctsvc_set_person_noti(); - - ret = ctsvc_end_trans(true); - return ret; -} - -API int contacts_activity_delete_by_account_id(int account_id) -{ - char query[CTS_SQL_MAX_LEN] = {0}; - - RETV_IF(account_id < 0, CONTACTS_ERROR_INVALID_PARAMETER); - - snprintf(query, sizeof(query), "DELETE FROM %s WHERE contact_id IN " - "(SELECT C.contact_id FROM %s C, %s A ON C.addressbook_id = A.addressbook_id " - "WHERE A.account_id = %d)", - CTS_TABLE_ACTIVITIES, CTS_TABLE_CONTACTS, CTS_TABLE_ADDRESSBOOKS, account_id); - - int ret = ctsvc_begin_trans(); - RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_begin_trans() Failed(%d)", ret); - - ret = ctsvc_query_exec(query); - if (CONTACTS_ERROR_NONE != ret) { - CTS_ERR("cts_query_exec() Failed(%d)", ret); - ctsvc_end_trans(false); - return ret; - } - - ctsvc_set_activity_noti(); - ctsvc_set_person_noti(); - - ret = ctsvc_end_trans(true); - return ret; -} - - +/* + * Contacts Service + * + * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "contacts.h" +#include "ctsvc_internal.h" +#include "ctsvc_schema.h" +#include "ctsvc_sqlite.h" +#include "ctsvc_utils.h" +#include "ctsvc_db_plugin_contact_helper.h" +#include "ctsvc_notification.h" +#include "ctsvc_db_access_control.h" + +API int contacts_activity_delete_by_contact_id(int contact_id) +{ + char query[CTS_SQL_MAX_LEN] = {0}; + + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write (contact activity)"); + RETV_IF(contact_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER); + + snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_ACTIVITIES" WHERE contact_id = %d", contact_id); + + int ret = ctsvc_begin_trans(); + RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_begin_trans() Failed(%d)", ret); + + ret = ctsvc_query_exec(query); + if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("cts_query_exec() Failed(%d)", ret); + ctsvc_end_trans(false); + return ret; + } + + ctsvc_set_activity_noti(); + ctsvc_set_person_noti(); + + ret = ctsvc_end_trans(true); + return ret; +} + +API int contacts_activity_delete_by_account_id(int account_id) +{ + char query[CTS_SQL_MAX_LEN] = {0}; + + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write (contact activity)"); + RETV_IF(account_id < 0, CONTACTS_ERROR_INVALID_PARAMETER); + + snprintf(query, sizeof(query), "DELETE FROM %s WHERE contact_id IN " + "(SELECT C.contact_id FROM %s C, %s A ON C.addressbook_id = A.addressbook_id " + "WHERE A.account_id = %d)", + CTS_TABLE_ACTIVITIES, CTS_TABLE_CONTACTS, CTS_TABLE_ADDRESSBOOKS, account_id); + + int ret = ctsvc_begin_trans(); + RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_begin_trans() Failed(%d)", ret); + + ret = ctsvc_query_exec(query); + if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("cts_query_exec() Failed(%d)", ret); + ctsvc_end_trans(false); + return ret; + } + + ctsvc_set_activity_noti(); + ctsvc_set_person_noti(); + + ret = ctsvc_end_trans(true); + return ret; +} + + diff --git a/native/ctsvc_db_access_control.c b/native/ctsvc_db_access_control.c new file mode 100644 index 0000000..a210bd4 --- /dev/null +++ b/native/ctsvc_db_access_control.c @@ -0,0 +1,210 @@ +/* + * Contacts Service + * + * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "contacts.h" +#include "ctsvc_internal.h" +#include "ctsvc_schema.h" +#include "ctsvc_sqlite.h" +#include "ctsvc_db_access_control.h" +#include "ctsvc_mutex.h" + +typedef struct { + unsigned int thread_id; + char *smack_label; + int permission; +}ctsvc_permission_info_s; + +static GList *__thread_list = NULL; + +static int have_smack = -1; + +static int __ctsvc_have_smack(void) +{ + if (-1 == have_smack) { + if (NULL == smack_smackfs_path()) + have_smack = 0; + else + have_smack = 1; + } + return have_smack; +} + +// this function is called in mutex lock +static ctsvc_permission_info_s * __ctsvc_find_access_info(unsigned int thread_id) +{ + GList *cursor; + CTS_VERBOSE("thread id : %08x", thread_id); + for (cursor=__thread_list;cursor;cursor = cursor->next) { + ctsvc_permission_info_s *info = NULL; + info = cursor->data; + if (info->thread_id == thread_id) + return info; + } + return NULL; +} + +// success : CONTACTS_ERROR_NONE +// fail : return negative value +int ctsvc_have_file_read_permission(const char *path) +{ + int ret; + int permission = -1; + char *file_label = NULL; + ctsvc_permission_info_s *find = NULL; + const char *smack_label; + int have_smack; + unsigned int thread_id; + + have_smack = __ctsvc_have_smack(); + if (have_smack != 1) // smack disable + return CONTACTS_ERROR_NONE; + + ret = smack_getlabel(path, &file_label, SMACK_LABEL_ACCESS); + if(ret < 0) { + CTS_ERR("smack_getlabel Fail (%d)", ret); + return CONTACTS_ERROR_SYSTEM; + } + + ctsvc_mutex_lock(CTS_MUTEX_ACCESS_CONTROL); + thread_id = (unsigned int)pthread_self(); + find = __ctsvc_find_access_info(thread_id); + if (!find) { + CTS_ERR("does not have access info of the thread"); + free(file_label); + ctsvc_mutex_unlock(CTS_MUTEX_ACCESS_CONTROL); + return CONTACTS_ERROR_INTERNAL; + } + + smack_label = find->smack_label; + permission = smack_have_access(smack_label, file_label, "r"); + free(file_label); + if (permission == 0) { + CTS_ERR("smack_have_access Fail(%d) : does not have permission", permission); + ret = CONTACTS_ERROR_PERMISSION_DENIED; + } + else if (permission != 1) { + CTS_ERR("smack_have_access Fail(%d)", ret); + ret = CONTACTS_ERROR_SYSTEM; + } + else { + ret= CONTACTS_ERROR_NONE; + } + + ctsvc_mutex_unlock(CTS_MUTEX_ACCESS_CONTROL); + return ret; +} + +static void __ctsvc_set_permission_info(unsigned int thread_id, const char *cookie) +{ + ctsvc_permission_info_s *find = NULL; + const char *smack_label; + + find = __ctsvc_find_access_info(thread_id); + if (!find) { + CTS_ERR("does not have access info of the thread"); + return; + } + smack_label = find->smack_label; + + if (!find->permission) { // check once + if (smack_label && 0 == strcmp(smack_label, "contacts-service")) { + find->permission |= CTSVC_PERMISSION_CONTACT_READ; + find->permission |= CTSVC_PERMISSION_CONTACT_WRITE; + find->permission |= CTSVC_PERMISSION_PHONELOG_READ; + find->permission |= CTSVC_PERMISSION_PHONELOG_WRITE; + } + else if (cookie) { + if (SECURITY_SERVER_API_SUCCESS == security_server_check_privilege_by_cookie(cookie, "contacts-service::svc", "r")) + find->permission |= CTSVC_PERMISSION_CONTACT_READ; + if (SECURITY_SERVER_API_SUCCESS == security_server_check_privilege_by_cookie(cookie, "contacts-service::svc", "w")) + find->permission |= CTSVC_PERMISSION_CONTACT_WRITE; + if (SECURITY_SERVER_API_SUCCESS == security_server_check_privilege_by_cookie(cookie, "contacts-service::phonelog", "r")) + find->permission |= CTSVC_PERMISSION_PHONELOG_READ; + if (SECURITY_SERVER_API_SUCCESS == security_server_check_privilege_by_cookie(cookie, "contacts-service::phonelog", "w")) + find->permission |= CTSVC_PERMISSION_PHONELOG_WRITE; + } + } +} + +void ctsvc_unset_client_access_info() +{ + ctsvc_permission_info_s *find = NULL; + + ctsvc_mutex_lock(CTS_MUTEX_ACCESS_CONTROL); + find = __ctsvc_find_access_info(pthread_self()); + if (find) { + free(find->smack_label); + __thread_list = g_list_remove(__thread_list, find); + free(find); + } + ctsvc_mutex_unlock(CTS_MUTEX_ACCESS_CONTROL); +} + +void ctsvc_set_client_access_info(const char *smack_label, const char *cookie) +{ + unsigned int thread_id = (unsigned int)pthread_self(); + ctsvc_permission_info_s *info = NULL; + + ctsvc_mutex_lock(CTS_MUTEX_ACCESS_CONTROL); + info = __ctsvc_find_access_info(thread_id); + if (NULL == info) { + info = calloc(1, sizeof(ctsvc_permission_info_s)); + __thread_list = g_list_append(__thread_list, info); + } + info->thread_id = thread_id; + FREEandSTRDUP(info->smack_label, smack_label); + __ctsvc_set_permission_info(thread_id, cookie); + ctsvc_mutex_unlock(CTS_MUTEX_ACCESS_CONTROL); +} + +bool ctsvc_have_permission(int permission) +{ + ctsvc_permission_info_s *find = NULL; + + ctsvc_mutex_lock(CTS_MUTEX_ACCESS_CONTROL); + find = __ctsvc_find_access_info(pthread_self()); + if (!find) { + ctsvc_mutex_unlock(CTS_MUTEX_ACCESS_CONTROL); + return false; + } + + if (CTSVC_PERMISSION_CONTACT_NONE == permission) { + ctsvc_mutex_unlock(CTS_MUTEX_ACCESS_CONTROL); + return false; + } + + if ((find->permission & permission) == permission) { + ctsvc_mutex_unlock(CTS_MUTEX_ACCESS_CONTROL); + return true; + } + + ctsvc_mutex_unlock(CTS_MUTEX_ACCESS_CONTROL); + CTS_ERR("Does not have permission %d, this module has permission %d", + permission, find->permission); + return false; +} + diff --git a/native/ctsvc_db_access_control.h b/native/ctsvc_db_access_control.h new file mode 100644 index 0000000..ea6b5d7 --- /dev/null +++ b/native/ctsvc_db_access_control.h @@ -0,0 +1,39 @@ +/* + * Contacts Service + * + * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __TIZEN_SOCIAL_CTSVC_DB_ACCESS_CONTROL_H__ +#define __TIZEN_SOCIAL_CTSVC_DB_ACCESS_CONTROL_H__ + + +enum { + CTSVC_PERMISSION_CONTACT_NONE = 0x0, + CTSVC_PERMISSION_CONTACT_READ = 0x1, + CTSVC_PERMISSION_CONTACT_WRITE = 0x2, + CTSVC_PERMISSION_PHONELOG_READ = 0x4, + CTSVC_PERMISSION_PHONELOG_WRITE = 0x8, +}; + +int ctsvc_have_file_read_permission(const char *path); + +void ctsvc_set_client_access_info(const char *smack_label, const char *cookie); +void ctsvc_unset_client_access_info(void); + +bool ctsvc_have_permission(int permission); + +#endif // __TIZEN_SOCIAL_CTSVC_DB_ACCESS_CONTROL_H__ diff --git a/native/ctsvc_db_init.c b/native/ctsvc_db_init.c index 353dc3a..56fbe77 100644 --- a/native/ctsvc_db_init.c +++ b/native/ctsvc_db_init.c @@ -30,6 +30,7 @@ #include "ctsvc_utils.h" #include "ctsvc_view.h" #include "ctsvc_notification.h" +#include "ctsvc_db_access_control.h" #define MODULE_NAME_DB "DB" @@ -70,65 +71,65 @@ static bool __ctsvc_db_view_already_created = false; typedef struct { char *view_uri; const char * const table_name; + int read_permission; + int write_permission; }db_table_info_s; static const db_table_info_s __db_tables[] = { - {CTSVC_VIEW_URI_ADDRESSBOOK, CTS_TABLE_ADDRESSBOOKS}, - {CTSVC_VIEW_URI_GROUP, CTS_TABLE_GROUPS}, - {CTSVC_VIEW_URI_PERSON, CTSVC_DB_VIEW_PERSON}, - {CTSVC_VIEW_URI_SIMPLE_CONTACT, CTSVC_DB_VIEW_CONTACT}, - {CTSVC_VIEW_URI_CONTACT, CTSVC_DB_VIEW_CONTACT}, - {CTSVC_VIEW_URI_MY_PROFILE, CTSVC_DB_VIEW_MY_PROFILE}, - {CTSVC_VIEW_URI_ACTIVITY, CTSVC_DB_VIEW_ACTIVITY}, - {CTSVC_VIEW_URI_PHONELOG, CTS_TABLE_PHONELOGS}, - {CTSVC_VIEW_URI_SPEEDDIAL, CTSVC_DB_VIEW_SPEEDIDAL}, - {CTSVC_VIEW_URI_SDN, CTS_TABLE_SDN}, - - {CTSVC_VIEW_URI_NAME, CTSVC_DB_VIEW_NAME}, - {CTSVC_VIEW_URI_COMPANY, CTSVC_DB_VIEW_COMPANY}, - {CTSVC_VIEW_URI_NUMBER, CTSVC_DB_VIEW_NUMBER}, - {CTSVC_VIEW_URI_EMAIL, CTSVC_DB_VIEW_EMAIL}, - {CTSVC_VIEW_URI_URL, CTSVC_DB_VIEW_URL}, - {CTSVC_VIEW_URI_ADDRESS, CTSVC_DB_VIEW_ADDRESS}, - {CTSVC_VIEW_URI_PROFILE, CTSVC_DB_VIEW_PROFILE}, - {CTSVC_VIEW_URI_RELATIONSHIP, CTSVC_DB_VIEW_RELATIONSHIP}, - {CTSVC_VIEW_URI_IMAGE, CTSVC_DB_VIEW_IMAGE}, - {CTSVC_VIEW_URI_NOTE, CTSVC_DB_VIEW_NOTE}, - {CTSVC_VIEW_URI_NICKNAME, CTSVC_DB_VIEW_NICKNAME}, - {CTSVC_VIEW_URI_EVENT, CTSVC_DB_VIEW_EVENT}, - {CTSVC_VIEW_URI_MESSENGER, CTSVC_DB_VIEW_MESSENGER}, - {CTSVC_VIEW_URI_GROUP_RELATION, CTSVC_DB_VIEW_GROUP_RELATION}, - {CTSVC_VIEW_URI_EXTENSION, CTSVC_DB_VIEW_EXTENSION}, + {CTSVC_VIEW_URI_ADDRESSBOOK, CTS_TABLE_ADDRESSBOOKS, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_GROUP, CTS_TABLE_GROUPS, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_PERSON, CTSVC_DB_VIEW_PERSON, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_SIMPLE_CONTACT, CTSVC_DB_VIEW_CONTACT, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_CONTACT, CTSVC_DB_VIEW_CONTACT, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_MY_PROFILE, CTSVC_DB_VIEW_MY_PROFILE, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_ACTIVITY, CTSVC_DB_VIEW_ACTIVITY, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_PHONELOG, CTS_TABLE_PHONELOGS, CTSVC_PERMISSION_PHONELOG_READ, CTSVC_PERMISSION_PHONELOG_WRITE}, + {CTSVC_VIEW_URI_SPEEDDIAL, CTSVC_DB_VIEW_SPEEDIDAL, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_SDN, CTS_TABLE_SDN, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + + {CTSVC_VIEW_URI_NAME, CTSVC_DB_VIEW_NAME, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_COMPANY, CTSVC_DB_VIEW_COMPANY, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_NUMBER, CTSVC_DB_VIEW_NUMBER, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_EMAIL, CTSVC_DB_VIEW_EMAIL, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_URL, CTSVC_DB_VIEW_URL, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_ADDRESS, CTSVC_DB_VIEW_ADDRESS, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_PROFILE, CTSVC_DB_VIEW_PROFILE, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_RELATIONSHIP, CTSVC_DB_VIEW_RELATIONSHIP, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_IMAGE, CTSVC_DB_VIEW_IMAGE, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_NOTE, CTSVC_DB_VIEW_NOTE, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_NICKNAME, CTSVC_DB_VIEW_NICKNAME, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_EVENT, CTSVC_DB_VIEW_EVENT, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_MESSENGER, CTSVC_DB_VIEW_MESSENGER, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_GROUP_RELATION, CTSVC_DB_VIEW_GROUP_RELATION, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, + {CTSVC_VIEW_URI_EXTENSION, CTSVC_DB_VIEW_EXTENSION, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_WRITE}, // Do not support get_all_records, get_records_with_query, get_count, get_count_with_query // {CTSVC_VIEW_URI_GROUPS_UPDATED_INFO, CTSVC_DB_VIEW_GROUPS_UPDATED_INFO}, // {CTSVC_VIEW_URI_GROUPS_MEMBER_UPDATED_INFO, CTSVC_DB_VIEW_GROUPS_MEMBER_UPDATED_INFO}, // {CTSVC_VIEW_URI_CONTACTS_UPDATED_INFO, CTSVC_DB_VIEW_CONTACTS_UPDATED_INFO}, // {CTSVC_VIEW_URI_MY_PROFILE_UPDATED_INFO, NULL}, -// {CTSVC_VIEW_URI_GROUPRELS_UPDATED_INFO, NULL, NULL}, - - {CTSVC_VIEW_URI_READ_ONLY_PERSON_CONTACT, CTSVC_DB_VIEW_PERSON_CONTACT}, - {CTSVC_VIEW_URI_READ_ONLY_PERSON_NUMBER, CTSVC_DB_VIEW_PERSON_NUMBER}, - {CTSVC_VIEW_URI_READ_ONLY_PERSON_EMAIL, CTSVC_DB_VIEW_PERSON_EMAIL}, - {CTSVC_VIEW_URI_READ_ONLY_PERSON_GROUP, CTSVC_DB_VIEW_PERSON_GROUP}, - {CTSVC_VIEW_URI_READ_ONLY_PERSON_PHONELOG, CTSVC_DB_VIEW_PERSON_PHONELOG}, - {CTSVC_VIEW_URI_READ_ONLY_PERSON_USAGE, CTSVC_DB_VIEW_PERSON_USAGE}, - - {CTSVC_VIEW_URI_READ_ONLY_CONTACT_NUMBER, CTSVC_DB_VIEW_CONTACT_NUMBER}, - {CTSVC_VIEW_URI_READ_ONLY_CONTACT_EMAIL, CTSVC_DB_VIEW_CONTACT_EMAIL}, - {CTSVC_VIEW_URI_READ_ONLY_CONTACT_GROUP, CTSVC_DB_VIEW_CONTACT_GROUP}, - {CTSVC_VIEW_URI_READ_ONLY_CONTACT_ACTIVITY, CTSVC_DB_VIEW_CONTACT_ACTIVITY}, - - {CTSVC_VIEW_URI_READ_ONLY_PHONELOG_NUMBER, CTSVC_DB_VIEW_PHONELOG_NUMBER}, - {CTSVC_VIEW_URI_READ_ONLY_PHONELOG_STAT, CTS_TABLE_PHONELOG_STAT}, +// {CTSVC_VIEW_URI_GROUPRELS_UPDATED_INFO, NULL}, + + {CTSVC_VIEW_URI_READ_ONLY_PERSON_CONTACT, CTSVC_DB_VIEW_PERSON_CONTACT, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_NONE}, + {CTSVC_VIEW_URI_READ_ONLY_PERSON_NUMBER, CTSVC_DB_VIEW_PERSON_NUMBER, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_NONE}, + {CTSVC_VIEW_URI_READ_ONLY_PERSON_EMAIL, CTSVC_DB_VIEW_PERSON_EMAIL, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_NONE}, + {CTSVC_VIEW_URI_READ_ONLY_PERSON_GROUP, CTSVC_DB_VIEW_PERSON_GROUP, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_NONE}, + {CTSVC_VIEW_URI_READ_ONLY_PERSON_PHONELOG, CTSVC_DB_VIEW_PERSON_PHONELOG, CTSVC_PERMISSION_CONTACT_READ|CTSVC_PERMISSION_PHONELOG_READ, CTSVC_PERMISSION_CONTACT_NONE}, + {CTSVC_VIEW_URI_READ_ONLY_PERSON_USAGE, CTSVC_DB_VIEW_PERSON_USAGE, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_NONE}, + + {CTSVC_VIEW_URI_READ_ONLY_CONTACT_NUMBER, CTSVC_DB_VIEW_CONTACT_NUMBER, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_NONE}, + {CTSVC_VIEW_URI_READ_ONLY_CONTACT_EMAIL, CTSVC_DB_VIEW_CONTACT_EMAIL, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_NONE}, + {CTSVC_VIEW_URI_READ_ONLY_CONTACT_GROUP, CTSVC_DB_VIEW_CONTACT_GROUP, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_NONE}, + {CTSVC_VIEW_URI_READ_ONLY_CONTACT_ACTIVITY, CTSVC_DB_VIEW_CONTACT_ACTIVITY, CTSVC_PERMISSION_CONTACT_READ, CTSVC_PERMISSION_CONTACT_NONE}, + + {CTSVC_VIEW_URI_READ_ONLY_PHONELOG_NUMBER, CTSVC_DB_VIEW_PHONELOG_NUMBER, CTSVC_PERMISSION_PHONELOG_READ, CTSVC_PERMISSION_CONTACT_NONE}, + {CTSVC_VIEW_URI_READ_ONLY_PHONELOG_STAT, CTS_TABLE_PHONELOG_STAT, CTSVC_PERMISSION_PHONELOG_READ, CTSVC_PERMISSION_CONTACT_NONE}, }; // this function is called in mutex lock int ctsvc_db_plugin_init() { int i; -// pims_ipc_svc_init("/opt/CONTACT_SVC", getuid(), 0660); - if (__ctsvc_db_view_hash_table) { return CONTACTS_ERROR_NONE; } @@ -171,6 +172,38 @@ int ctsvc_db_get_table_name(const char *view_uri, const char **out_table) return CONTACTS_ERROR_INVALID_PARAMETER; } +int ctsvc_required_read_permission(const char *view_uri) +{ + db_table_info_s* db_view_info = NULL; + + if(__ctsvc_db_view_hash_table){ + db_view_info = g_hash_table_lookup(__ctsvc_db_view_hash_table, view_uri); + if (db_view_info) { + return db_view_info->read_permission; + } + } + else + CTS_ERR("Please check contact_connect2()"); + + return CTSVC_PERMISSION_CONTACT_NONE; +} + +int ctsvc_required_write_permission(const char *view_uri) +{ + db_table_info_s* db_view_info = NULL; + + if(__ctsvc_db_view_hash_table){ + db_view_info = g_hash_table_lookup(__ctsvc_db_view_hash_table, view_uri); + if (db_view_info) { + return db_view_info->write_permission; + } + } + else + CTS_ERR("Please check contact_connect2()"); + + return CTSVC_PERMISSION_CONTACT_NONE; +} + ctsvc_db_plugin_info_s* ctsvc_db_get_plugin_info(ctsvc_record_type_e type) { switch((int)type) { diff --git a/native/ctsvc_db_init.h b/native/ctsvc_db_init.h index 40ba650..034ea42 100644 --- a/native/ctsvc_db_init.h +++ b/native/ctsvc_db_init.h @@ -69,4 +69,7 @@ int ctsvc_db_plugin_deinit(); int ctsvc_db_get_table_name(const char *view_uri, const char **out_table); ctsvc_db_plugin_info_s* ctsvc_db_get_plugin_info(ctsvc_record_type_e type); +int ctsvc_required_read_permission(const char *view_uri); +int ctsvc_required_write_permission(const char *view_uri); + #endif // __TIZEN_SOCIAL_CTSVC_DB_INIT_H__ diff --git a/native/ctsvc_db_plugin_addressbook.c b/native/ctsvc_db_plugin_addressbook.c index 30df993..ab32cdb 100644 --- a/native/ctsvc_db_plugin_addressbook.c +++ b/native/ctsvc_db_plugin_addressbook.c @@ -30,6 +30,7 @@ #include "ctsvc_person.h" #include "ctsvc_record.h" #include "ctsvc_notification.h" +#include "ctsvc_db_access_control.h" static int __ctsvc_db_addressbook_insert_record( contacts_record_h record, int *id ); static int __ctsvc_db_addressbook_get_record( int id, contacts_record_h* record ); diff --git a/native/ctsvc_db_plugin_company_helper.c b/native/ctsvc_db_plugin_company_helper.c index b5db3f4..1eb90d9 100644 --- a/native/ctsvc_db_plugin_company_helper.c +++ b/native/ctsvc_db_plugin_company_helper.c @@ -30,6 +30,7 @@ #include "ctsvc_db_plugin_company_helper.h" #include "ctsvc_record.h" #include "ctsvc_notification.h" +#include "ctsvc_db_access_control.h" static int __ctsvc_company_bind_stmt(cts_stmt stmt, ctsvc_company_s *company, int start_cnt) { @@ -106,6 +107,12 @@ int ctsvc_db_company_insert(contacts_record_h record, int contact_id, bool is_my __ctsvc_company_bind_stmt(stmt, company, 1); if (company->logo) { char image[CTS_SQL_MAX_LEN] = {0}; + ret = ctsvc_have_file_read_permission(company->logo); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_have_file_read_permission Fail(%d)", ret); + cts_stmt_finalize(stmt); + return ret; + } ctsvc_utils_make_image_file_name(contact_id, company_id, company->logo, image, sizeof(image)); ret = ctsvc_utils_copy_image(CTS_LOGO_IMAGE_LOCATION, company->logo, image); if (CONTACTS_ERROR_NONE != ret) { @@ -212,6 +219,7 @@ int ctsvc_db_company_update(contacts_record_h record, int contact_id, bool is_my if (ctsvc_record_check_property_flag((ctsvc_record_s *)company, _contacts_company.logo, CTSVC_PROPERTY_FLAG_DIRTY)) { char *logo = ctsvc_stmt_get_text(stmt, 1); bool same = false; + bool check_permission = false; // delete current logo image if (logo) { @@ -223,6 +231,15 @@ int ctsvc_db_company_update(contacts_record_h record, int contact_id, bool is_my same = true; } else { + if (company->logo) { + ret = ctsvc_have_file_read_permission(company->logo); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_have_file_read_permission Fail(%d)", ret); + cts_stmt_finalize(stmt); + return ret; + } + check_permission = true; + } ret = unlink(full_path); if (ret < 0) { CTS_WARN("unlink Failed(%d)", errno); @@ -233,6 +250,14 @@ int ctsvc_db_company_update(contacts_record_h record, int contact_id, bool is_my // add new logo file if (!same && company->logo) { char dest[CTS_SQL_MAX_LEN] = {0}; + if (false == check_permission) { + ret = ctsvc_have_file_read_permission(company->logo); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_have_file_read_permission Fail(%d)", ret); + cts_stmt_finalize(stmt); + return ret; + } + } ctsvc_utils_make_image_file_name(contact_id, company->id, company->logo, dest, sizeof(dest)); ret = ctsvc_utils_copy_image(CTS_LOGO_IMAGE_LOCATION, company->logo, dest); if (CONTACTS_ERROR_NONE != ret) { diff --git a/native/ctsvc_db_plugin_contact.c b/native/ctsvc_db_plugin_contact.c index dac0d02..5441977 100644 --- a/native/ctsvc_db_plugin_contact.c +++ b/native/ctsvc_db_plugin_contact.c @@ -688,7 +688,7 @@ static inline int __ctsvc_contact_make_search_data(int contact_id, char **search char *temp_data=NULL; int buf_size=0; - ret = contacts_db_get_record(_contacts_contact._uri, contact_id, (contacts_record_h*)&contact); + ret = ctsvc_db_contact_get(contact_id, (contacts_record_h*)&contact); if (CONTACTS_ERROR_NO_DATA == ret) { int r; snprintf(query, sizeof(query), "DELETE FROM %s WHERE contact_id = %d", @@ -701,7 +701,7 @@ static inline int __ctsvc_contact_make_search_data(int contact_id, char **search return ret; } else if (CONTACTS_ERROR_NONE != ret) { - CTS_ERR("contacts_db_get_record() Failed(%d)", ret); + CTS_ERR("ctsvc_db_contact_get() Failed(%d)", ret); return ret; } @@ -936,9 +936,9 @@ static inline int __ctsvc_contact_refresh_lookup_data(int contact_id) return ret; } - ret = contacts_db_get_record(_contacts_contact._uri, contact_id, (contacts_record_h*)&contact); + ret = ctsvc_db_contact_get(contact_id, (contacts_record_h*)&contact); if (CONTACTS_ERROR_NONE != ret) { - CTS_ERR("contacts_db_get_record() Failed(%d)", ret); + CTS_ERR("ctsvc_db_contact_get() Failed(%d)", ret); return ret; } @@ -1363,9 +1363,9 @@ static int __ctsvc_db_contact_get_all_records( int offset, int limit, contacts_l return ret; } contact_id = ctsvc_stmt_get_int(stmt, 0); - ret = contacts_db_get_record(_contacts_contact._uri, contact_id, &record); + ret = ctsvc_db_contact_get(contact_id, &record); if (CONTACTS_ERROR_NONE != ret) { - CTS_ERR("DB error : contacts_db_get_record() Failed(%d)", ret); + CTS_ERR("DB error : ctsvc_db_contact_get() Failed(%d)", ret); cts_stmt_finalize(stmt); contacts_list_destroy(list, true); return CONTACTS_ERROR_NO_DATA; diff --git a/native/ctsvc_db_plugin_contact_helper.c b/native/ctsvc_db_plugin_contact_helper.c index f8dadb0..e4d23be 100644 --- a/native/ctsvc_db_plugin_contact_helper.c +++ b/native/ctsvc_db_plugin_contact_helper.c @@ -2019,8 +2019,8 @@ int ctsvc_contact_update_display_name(int contact_id, contacts_display_name_sour int ret = CONTACTS_ERROR_NONE; int display_name_type; contacts_record_h record; - ret = contacts_db_get_record(_contacts_contact._uri, contact_id, &record); - RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "contacts_db_get_record Fail(%d)", ret); + ret = ctsvc_db_contact_get(contact_id, (contacts_record_h*)&record); + RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "ctsvc_db_contact_get Fail(%d)", ret); contacts_record_get_int(record, _contacts_contact.display_source_type, &display_name_type); if (display_name_type <= changed_record_type) { @@ -2067,3 +2067,9 @@ int ctsvc_contact_update_display_name(int contact_id, contacts_display_name_sour return ret; } +extern ctsvc_db_plugin_info_s ctsvc_db_plugin_contact; +int ctsvc_db_contact_get( int id, contacts_record_h* out_record ) +{ + return ctsvc_db_plugin_contact.get_record(id, out_record); +} + diff --git a/native/ctsvc_db_plugin_contact_helper.h b/native/ctsvc_db_plugin_contact_helper.h index b0704c5..3074480 100644 --- a/native/ctsvc_db_plugin_contact_helper.h +++ b/native/ctsvc_db_plugin_contact_helper.h @@ -34,6 +34,8 @@ void ctsvc_make_contact_display_name(ctsvc_contact_s *contact); int ctsvc_db_contact_delete(int contact_id); int ctsvc_contact_delete_image_file_with_path(const unsigned char* image_path); +int ctsvc_db_contact_get( int id, contacts_record_h* out_record ); + int ctsvc_get_data_info_name(cts_stmt stmt, contacts_list_h name_list); int ctsvc_get_data_info_event(cts_stmt stmt, contacts_list_h list); int ctsvc_get_data_info_number(cts_stmt stmt, contacts_list_h number_list); diff --git a/native/ctsvc_db_plugin_group.c b/native/ctsvc_db_plugin_group.c index 0187fe6..2687c80 100644 --- a/native/ctsvc_db_plugin_group.c +++ b/native/ctsvc_db_plugin_group.c @@ -29,6 +29,7 @@ #include "ctsvc_db_init.h" #include "ctsvc_record.h" #include "ctsvc_notification.h" +#include "ctsvc_db_access_control.h" #include "ctsvc_db_plugin_group_helper.h" static int __ctsvc_db_group_insert_record( contacts_record_h record, int *id ); @@ -131,6 +132,14 @@ static int __ctsvc_db_group_insert_record( contacts_record_h record, int *id ) if(group->image_thumbnail_path) { char image[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0}; + ret = ctsvc_have_file_read_permission(group->image_thumbnail_path); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_have_file_read_permission Fail(%d)", ret); + cts_stmt_finalize(stmt); + ctsvc_end_trans(false); + return ret; + } + ctsvc_utils_make_image_file_name(0, group->id, group->image_thumbnail_path, image, sizeof(image)); ret = ctsvc_utils_copy_image(CTS_GROUP_IMAGE_LOCATION, group->image_thumbnail_path, image); if (CONTACTS_ERROR_NONE != ret) { @@ -231,6 +240,7 @@ static int __ctsvc_db_group_update_record( contacts_record_h record ) if (ctsvc_record_check_property_flag((ctsvc_record_s *)group, _contacts_group.image_path, CTSVC_PROPERTY_FLAG_DIRTY)) { bool same = false; + bool check_permission = 0; // delete current image if (image) { char full_path[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0}; @@ -242,6 +252,16 @@ static int __ctsvc_db_group_update_record( contacts_record_h record ) same = true; } else { + if (group->image_thumbnail_path) { + ret = ctsvc_have_file_read_permission(group->image_thumbnail_path); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("Your module does not have read permission of the image file()"); + ctsvc_end_trans(false); + free(image); + return ret; + } + check_permission = true; + } ret = unlink(full_path); if (ret < 0) { CTS_WARN("unlink Failed(%d)", errno); @@ -252,6 +272,15 @@ static int __ctsvc_db_group_update_record( contacts_record_h record ) // add new image file if (!same && group->image_thumbnail_path) { char dest[CTS_SQL_MAX_LEN] = {0}; + if (false == check_permission) { + ret = ctsvc_have_file_read_permission(group->image_thumbnail_path); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_have_file_read_permission Fail(%d)", ret); + ctsvc_end_trans(false); + free(image); + return ret; + } + } ctsvc_utils_make_image_file_name(0, group->id, group->image_thumbnail_path, dest, sizeof(dest)); ret = ctsvc_utils_copy_image(CTS_GROUP_IMAGE_LOCATION, group->image_thumbnail_path, dest); if (CONTACTS_ERROR_NONE != ret) { diff --git a/native/ctsvc_db_plugin_image.c b/native/ctsvc_db_plugin_image.c index 98a9f75..2d5b5a5 100644 --- a/native/ctsvc_db_plugin_image.c +++ b/native/ctsvc_db_plugin_image.c @@ -429,7 +429,11 @@ static int __ctsvc_db_image_delete_record( int id ) "SELECT contact_id, person_id FROM "CTSVC_DB_VIEW_CONTACT " " "WHERE contact_id = (SELECT contact_id FROM "CTS_TABLE_DATA" WHERE id = %d)", id); stmt = cts_query_prepare(query); - RETVM_IF(NULL == stmt, CONTACTS_ERROR_DB, "DB error : cts_query_prepare() Failed"); + if (NULL == stmt) { + CTS_ERR("DB error : cts_query_prepare() Failed"); + ctsvc_end_trans(false); + return CONTACTS_ERROR_DB; + } ret = cts_stmt_step(stmt); if (1 /*CTS_TRUE*/ != ret) { @@ -446,15 +450,23 @@ static int __ctsvc_db_image_delete_record( int id ) "SELECT is_default, is_primary_default FROM "CTS_TABLE_DATA" WHERE id = %d", id); stmt = cts_query_prepare(query); - RETVM_IF(NULL == stmt, CONTACTS_ERROR_DB , "DB error : cts_query_prepare() Failed"); + if (NULL == stmt) { + CTS_ERR("DB error : cts_query_prepare() Failed"); + ctsvc_end_trans(false); + return CONTACTS_ERROR_DB; + } ret = cts_stmt_step(stmt); if (1 != ret) { CTS_ERR("DB error : cts_stmt_step() Failed(%d)", ret); cts_stmt_finalize(stmt); ctsvc_end_trans(false); - return CONTACTS_ERROR_NO_DATA; + if (CONTACTS_ERROR_NONE == ret) + return CONTACTS_ERROR_NO_DATA; + else + return ret; } + is_default = ctsvc_stmt_get_int(stmt, 0); is_primary_default = ctsvc_stmt_get_int(stmt, 1); cts_stmt_finalize(stmt); diff --git a/native/ctsvc_db_plugin_image_helper.c b/native/ctsvc_db_plugin_image_helper.c index 449cced..28f5cd8 100644 --- a/native/ctsvc_db_plugin_image_helper.c +++ b/native/ctsvc_db_plugin_image_helper.c @@ -27,7 +27,7 @@ #include "ctsvc_db_plugin_contact_helper.h" #include "ctsvc_record.h" #include "ctsvc_notification.h" - +#include "ctsvc_db_access_control.h" int ctsvc_db_image_get_value_from_stmt(cts_stmt stmt, contacts_record_h *record, int start_count) { @@ -94,6 +94,9 @@ int ctsvc_db_image_insert(contacts_record_h record, int contact_id, bool is_my_p RETVM_IF(0 < image->id, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter : id(%d), This record is already inserted", image->id); + ret = ctsvc_have_file_read_permission(image->path); + RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "ctsvc_have_file_read_permission fail(%d)", ret); + image_id = cts_db_get_next_id(CTS_TABLE_DATA); ret = ctsvc_contact_add_image_file(contact_id, image_id, image->path, image_path, sizeof(image_path)); if (CONTACTS_ERROR_NONE != ret) { @@ -156,6 +159,13 @@ int ctsvc_db_image_update(contacts_record_h record, int contact_id, bool is_my_p if (ctsvc_record_check_property_flag((ctsvc_record_s *)record, _contacts_image.path, CTSVC_PROPERTY_FLAG_DIRTY)) { char image_path[CTS_SQL_MAX_LEN] = {0}; + if (image->path) { + ret = ctsvc_have_file_read_permission(image->path); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_have_file_read_permission Fail(%d)", ret); + return ret; + } + } ret = ctsvc_contact_update_image_file(contact_id, image->id, image->path, image_path, sizeof(image_path)); RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_contact_update_image_file() Failed(%d)", ret); diff --git a/native/ctsvc_db_plugin_simple_contact.c b/native/ctsvc_db_plugin_simple_contact.c index 2780e59..b05d133 100644 --- a/native/ctsvc_db_plugin_simple_contact.c +++ b/native/ctsvc_db_plugin_simple_contact.c @@ -31,6 +31,7 @@ #include "ctsvc_record.h" #include "ctsvc_db_query.h" #include "ctsvc_notification.h" +#include "ctsvc_db_access_control.h" static int __ctsvc_db_simple_contact_insert_record( contacts_record_h record, int *id ); static int __ctsvc_db_simple_contact_get_record( int id, contacts_record_h* out_record ); @@ -189,6 +190,16 @@ static int __ctsvc_db_simple_contact_update_record( contacts_record_h record ) // This code will be removed if (ctsvc_record_check_property_flag((ctsvc_record_s *)contact, _contacts_simple_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY)) { int img_id; + + if (contact->image_thumbnail_path) { + ret = ctsvc_have_file_read_permission(contact->image_thumbnail_path); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_have_file_read_permission Fail(%d)", ret); + ctsvc_end_trans(false); + return ret; + } + } + image[0] = '\0'; img_id = __ctsvc_db_simple_contact_get_default_image_id(contact->contact_id); @@ -460,6 +471,13 @@ static int __ctsvc_db_simple_contact_insert_record( contacts_record_h record, in if (contact->image_thumbnail_path) { int image_id; + ret = ctsvc_have_file_read_permission(contact->image_thumbnail_path); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_have_file_read_permission Fail(%d)", ret); + ctsvc_end_trans(false); + return ret; + } + image[0] = '\0'; image_id = __ctsvc_db_simple_contact_get_default_image_id(contact->contact_id); ret = ctsvc_contact_add_image_file(contact->contact_id, image_id, contact->image_thumbnail_path, diff --git a/native/ctsvc_db_query.c b/native/ctsvc_db_query.c index b6acab2..8336e60 100755 --- a/native/ctsvc_db_query.c +++ b/native/ctsvc_db_query.c @@ -37,6 +37,7 @@ #include "ctsvc_localize.h" #include "ctsvc_setting.h" +#include "ctsvc_db_access_control.h" #include "ctsvc_db_plugin_person_helper.h" typedef enum { @@ -1793,6 +1794,8 @@ API int contacts_db_get_records_with_query( contacts_query_h query, int offset, RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER); s_query = (ctsvc_query_s*)query; + RETVM_IF(!ctsvc_have_permission(ctsvc_required_read_permission(s_query->view_uri)), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : read(%s)", s_query->view_uri); if (( plugin_info = ctsvc_db_get_plugin_info(ctsvc_view_get_record_type(s_query->view_uri)))){ if( plugin_info->get_records_with_query ) { @@ -2137,6 +2140,9 @@ API int contacts_db_get_changes_by_version( const char* view_uri, int addressboo *out_list = NULL; RETV_IF(NULL == out_current_version, CONTACTS_ERROR_INVALID_PARAMETER); *out_current_version = 0; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_READ), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : read (%s)", view_uri); + if (0 == strcmp(view_uri, _contacts_contact_updated_info._uri)) { ret = __ctsvc_db_get_contact_changes(view_uri, addressbook_id, @@ -2171,6 +2177,8 @@ API int contacts_db_get_changes_by_version( const char* view_uri, int addressboo API int contacts_db_get_current_version( int* out_current_version ) { RETVM_IF(NULL == out_current_version, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter"); + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_READ) && !ctsvc_have_permission(CTSVC_PERMISSION_PHONELOG_READ), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : read (contact)"); return ctsvc_get_current_version(out_current_version); } @@ -2181,6 +2189,8 @@ API int contacts_db_search_records(const char* view_uri, const char *keyword, RETV_IF(NULL == out_list, CONTACTS_ERROR_INVALID_PARAMETER); *out_list = NULL; RETVM_IF(NULL == view_uri, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter"); + RETVM_IF(!ctsvc_have_permission(ctsvc_required_read_permission(view_uri)), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : read(%s)", view_uri); return __ctsvc_db_search_records(view_uri, keyword, offset, limit, out_list); } @@ -2192,6 +2202,8 @@ API int contacts_db_search_records_with_range(const char* view_uri, const char * *out_list = NULL; RETVM_IF(range == 0, CONTACTS_ERROR_INVALID_PARAMETER, "range is 0"); RETVM_IF(NULL == view_uri, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter"); + RETVM_IF(!ctsvc_have_permission(ctsvc_required_read_permission(view_uri)), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : read(%s)", view_uri); return __ctsvc_db_search_records_with_range(view_uri, keyword, offset, limit, range, out_list); } @@ -2202,6 +2214,8 @@ API int contacts_db_search_records_with_query( contacts_query_h query, const cha RETV_IF(NULL == out_list, CONTACTS_ERROR_INVALID_PARAMETER); *out_list = NULL; RETVM_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter"); + RETVM_IF(!ctsvc_have_permission(ctsvc_required_read_permission(((ctsvc_query_s*)query)->view_uri)), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : read (%s)", ((ctsvc_query_s*)query)->view_uri); return __ctsvc_db_search_records_with_query(query, keyword, offset, limit, out_list); } @@ -2214,6 +2228,8 @@ API int contacts_db_get_count( const char* view_uri, int *out_count) RETV_IF(NULL == out_count, CONTACTS_ERROR_INVALID_PARAMETER); *out_count = 0; RETVM_IF(NULL == view_uri, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter"); + RETVM_IF(!ctsvc_have_permission(ctsvc_required_read_permission(view_uri)), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : read (%s)", view_uri); if (( plugin_info = ctsvc_db_get_plugin_info(ctsvc_view_get_record_type(view_uri)))){ if( plugin_info->get_count ) { @@ -2237,6 +2253,8 @@ API int contacts_db_get_count_with_query( contacts_query_h query, int *out_count RETVM_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter"); s_query = (ctsvc_query_s*)query; + RETVM_IF(!ctsvc_have_permission(ctsvc_required_read_permission(s_query->view_uri)), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : read (%s)", s_query->view_uri); type = ctsvc_view_get_record_type(s_query->view_uri); plugin_info = ctsvc_db_get_plugin_info(type); @@ -2263,6 +2281,8 @@ API int contacts_db_insert_record(contacts_record_h record, int *id ) plugin_info = ctsvc_db_get_plugin_info(((ctsvc_record_s*)record)->r_type); RETVM_IF(NULL == plugin_info, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter"); RETVM_IF(NULL == plugin_info->insert_record, CONTACTS_ERROR_INVALID_PARAMETER, "Not permitted"); + RETVM_IF(!ctsvc_have_permission(ctsvc_required_write_permission(((ctsvc_record_s*)record)->view_uri)), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : write (%s)", ((ctsvc_record_s*)record)->view_uri); return plugin_info->insert_record(record, id); } @@ -2276,6 +2296,8 @@ API int contacts_db_update_record(contacts_record_h record) plugin_info = ctsvc_db_get_plugin_info(((ctsvc_record_s*)record)->r_type); RETVM_IF(NULL == plugin_info, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter"); RETVM_IF(NULL == plugin_info->update_record, CONTACTS_ERROR_INVALID_PARAMETER, "Not permitted"); + RETVM_IF(!ctsvc_have_permission(ctsvc_required_write_permission(((ctsvc_record_s*)record)->view_uri)), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : write (%s)", ((ctsvc_record_s*)record)->view_uri); return plugin_info->update_record(record); } @@ -2291,6 +2313,8 @@ API int contacts_db_delete_record(const char* view_uri, int id) plugin_info = ctsvc_db_get_plugin_info(type); RETVM_IF(NULL == plugin_info, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter"); RETVM_IF(NULL == plugin_info->delete_record, CONTACTS_ERROR_INVALID_PARAMETER, "Not permitted"); + RETVM_IF(!ctsvc_have_permission(ctsvc_required_write_permission(view_uri)), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : write (%s)", view_uri); return plugin_info->delete_record(id); } @@ -2309,6 +2333,8 @@ API int contacts_db_get_record(const char* view_uri, int id, contacts_record_h* RETVM_IF(NULL == plugin_info, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter"); RETVM_IF(NULL == plugin_info->get_record, CONTACTS_ERROR_INVALID_PARAMETER, "Not permitted"); + RETVM_IF(!ctsvc_have_permission(ctsvc_required_read_permission(view_uri)), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : read (%s)", view_uri); return plugin_info->get_record(id, out_record); } @@ -2322,6 +2348,8 @@ API int contacts_db_replace_record( contacts_record_h record, int id ) plugin_info = ctsvc_db_get_plugin_info(((ctsvc_record_s*)record)->r_type); RETVM_IF(NULL == plugin_info, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter"); RETVM_IF(NULL == plugin_info->replace_record, CONTACTS_ERROR_INVALID_PARAMETER, "Not permitted"); + RETVM_IF(!ctsvc_have_permission(ctsvc_required_write_permission(((ctsvc_record_s*)record)->view_uri)), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : write (%s)", ((ctsvc_record_s*)record)->view_uri); return plugin_info->replace_record(record, id); } @@ -2335,6 +2363,8 @@ API int contacts_db_get_all_records(const char* view_uri, int offset, int limit, RETV_IF(NULL == out_list, CONTACTS_ERROR_INVALID_PARAMETER); *out_list = NULL; RETVM_IF(NULL == view_uri, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter"); + RETVM_IF(!ctsvc_have_permission(ctsvc_required_read_permission(view_uri)), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : read (%s)", view_uri); type = ctsvc_view_get_record_type(view_uri); plugin_info = ctsvc_db_get_plugin_info(type); @@ -2589,6 +2619,8 @@ API int contacts_db_get_last_change_version(int* last_version) int ret = CONTACTS_ERROR_NONE; RETVM_IF(NULL == last_version, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter"); + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_READ) && !ctsvc_have_permission(CTSVC_PERMISSION_PHONELOG_READ), + CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied : read (contact)"); *last_version = ctsvc_get_transaction_ver(); return ret; } diff --git a/native/ctsvc_group.c b/native/ctsvc_group.c index 5ac41b6..eb07c46 100644 --- a/native/ctsvc_group.c +++ b/native/ctsvc_group.c @@ -25,6 +25,7 @@ #include "ctsvc_db_plugin_contact_helper.h" #include "ctsvc_group.h" #include "ctsvc_notification.h" +#include "ctsvc_db_access_control.h" int ctsvc_group_add_contact_in_transaction(int group_id, int contact_id) { @@ -90,11 +91,15 @@ int ctsvc_group_add_contact_in_transaction(int group_id, int contact_id) API int contacts_group_add_contact(int group_id, int contact_id) { + int ret; + + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write (group)"); RETVM_IF( group_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid Parameter: group_id should be greater than 0"); RETVM_IF( contact_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid Parameter: contact_id should be greater than 0"); /* BEGIN_TRANSACTION */ - int ret = ctsvc_begin_trans(); + ret = ctsvc_begin_trans(); RETVM_IF(ret, ret, "contacts_svc_begin_trans() Failed(%d)", ret); /* DOING JOB */ @@ -167,11 +172,14 @@ int ctsvc_group_remove_contact_in_transaction(int group_id, int contact_id) API int contacts_group_remove_contact(int group_id, int contact_id) { + int ret; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write (group)"); RETVM_IF( group_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid Parameter: group_id should be greater than 0"); RETVM_IF( contact_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid Parameter: contact_id should be greater than 0"); /* BEGIN_TRANSACTION */ - int ret = ctsvc_begin_trans(); + ret = ctsvc_begin_trans(); RETVM_IF(ret, ret, "contacts_svc_begin_trans() Failed(%d)", ret); /* DOING JOB */ @@ -219,6 +227,8 @@ API int contacts_group_set_group_order(int group_id, int previous_group_id, int cts_stmt stmt; char query[CTS_SQL_MAX_LEN] = {0}; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write (group)"); snprintf(query, sizeof(query), "SELECT group_prio, addressbook_id FROM "CTS_TABLE_GROUPS" WHERE group_id = ?"); stmt = cts_query_prepare(query); diff --git a/native/ctsvc_person.c b/native/ctsvc_person.c index 079efd8..f953d3c 100644 --- a/native/ctsvc_person.c +++ b/native/ctsvc_person.c @@ -25,6 +25,8 @@ #include "ctsvc_utils.h" #include "ctsvc_notification.h" #include "ctsvc_db_plugin_person_helper.h" +#include "ctsvc_db_plugin_contact_helper.h" +#include "ctsvc_db_access_control.h" #ifdef _CONTACTS_IPC_SERVER #include "ctsvc_server_change_subject.h" @@ -563,11 +565,40 @@ int ctsvc_person_aggregate(int person_id) ctsvc_person_s *person; bool person_is_favorite = false; - ret = contacts_db_get_record( _contacts_person._uri, person_id, (contacts_record_h*)&person); + // person aggregation : person link/unlink, contact insert (auto link), contact delete, garbage collection (addressbook delete) + // It should be get all contacts of person regardless of permission + // Get person info directly instead of contacts_db_get_record( _contacts_person._uri, person_id, (contacts_record_h*)&person); + snprintf(query, sizeof(query), + "SELECT person_id, " + "name_contact_id, " + "image_thumbnail_path, " + "ringtone_path, " + "vibration " + "FROM "CTS_TABLE_PERSONS" " + "WHERE persons.person_id = %d", person_id); + stmt = cts_query_prepare(query); + if (NULL == stmt) { + CTS_ERR("DB error : cts_query_prepare() Failed"); + return CONTACTS_ERROR_DB; + } + if (1 != cts_stmt_step(stmt)) { + CTS_ERR("cts_stmt_step() Failed\n"); + return CONTACTS_ERROR_DB; + } + ret = contacts_record_create(_contacts_person._uri, (contacts_record_h*)&person); if (CONTACTS_ERROR_NONE != ret) { - CTS_ERR("contacts_db_get_record() Failed\n"); + CTS_ERR("contacts_record_create() Failed\n"); return CONTACTS_ERROR_INTERNAL; } + person->person_id = ctsvc_stmt_get_int(stmt, 0); + person->name_contact_id = ctsvc_stmt_get_int(stmt, 1); + temp = ctsvc_stmt_get_text(stmt, 2); + person->image_thumbnail_path = SAFE_STRDUP(temp); + temp = ctsvc_stmt_get_text(stmt, 3); + person->ringtone_path = SAFE_STRDUP(temp); + temp = ctsvc_stmt_get_text(stmt, 4); + person->vibration = SAFE_STRDUP(temp); + cts_stmt_finalize(stmt); snprintf(query, sizeof(query), "SELECT contact_id FROM %s " @@ -813,6 +844,8 @@ API int contacts_person_link_person(int base_person_id, int person_id) bool is_favorite = false; double favorite_prio = 0.0; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write (person)"); RETVM_IF(base_person_id == person_id, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter : base_person_id(%d), person_id(%d)", base_person_id, person_id); @@ -1045,6 +1078,8 @@ API int contacts_person_unlink_contact(int person_id, int contact_id, int* out_p bool is_favorite = false; double priority = 0.0; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write (person)"); RETVM_IF(person_id <= 0 || contact_id <= 0 , CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter : person_id(%d), person_id(%d)", person_id, person_id); @@ -1068,9 +1103,9 @@ API int contacts_person_unlink_contact(int person_id, int contact_id, int* out_p return CONTACTS_ERROR_INVALID_PARAMETER; } - ret = contacts_db_get_record(_contacts_contact._uri, contact_id, &record); + ret = ctsvc_db_contact_get(contact_id, (contacts_record_h*)&record); if (CONTACTS_ERROR_NONE != ret) { - CTS_ERR("contacts_db_get_record() Failed(%d)", ret); + CTS_ERR("ctsvc_db_contact_get() Failed(%d)", ret); ctsvc_end_trans(false); return ret; } @@ -1163,6 +1198,8 @@ API int contacts_person_reset_usage(int person_id, contacts_usage_type_e type) int ret ; char query[CTS_SQL_MAX_LEN] = {0}; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write (person)"); RETVM_IF(person_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER,"contact_id should be greater than 0"); snprintf(query, sizeof(query), @@ -1198,6 +1235,9 @@ API int contacts_person_set_favorite_order(int person_id, int front_person_id, i cts_stmt stmt; char query[CTS_SQL_MAX_LEN] = {0}; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write"); + snprintf(query, sizeof(query), "SELECT favorite_prio FROM "CTS_TABLE_FAVORITES" WHERE person_id = ?"); stmt = cts_query_prepare(query); @@ -1253,6 +1293,8 @@ API int contacts_person_set_default_property(contacts_person_property_e property { int ret; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write (person)"); ret = ctsvc_begin_trans(); RETVM_IF(ret < CONTACTS_ERROR_NONE, CONTACTS_ERROR_DB, "ctsvc_begin_trans() Failed(%d)", ret); @@ -1296,6 +1338,8 @@ API int contacts_person_get_default_property(contacts_person_property_e property RETVM_IF(person_id <= 0 || id == NULL, CONTACTS_ERROR_INVALID_PARAMETER,"id should be greater than 0"); *id = 0; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_READ), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact read (contact)"); switch(property) { case CONTACTS_PERSON_PROPERTY_NAME_CONTACT: diff --git a/native/ctsvc_phonelog.c b/native/ctsvc_phonelog.c index b8017b0..938737e 100644 --- a/native/ctsvc_phonelog.c +++ b/native/ctsvc_phonelog.c @@ -23,6 +23,7 @@ #include "ctsvc_sqlite.h" #include "ctsvc_utils.h" #include "ctsvc_notification.h" +#include "ctsvc_db_access_control.h" #ifdef _CONTACTS_IPC_SERVER #include "ctsvc_server_change_subject.h" @@ -31,6 +32,8 @@ API int contacts_phone_log_reset_statistics() { char query[CTS_SQL_MIN_LEN] = {0}; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_PHONELOG_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write (phonelog)"); snprintf(query, sizeof(query),"DELETE FROM "CTS_TABLE_PHONELOG_STAT); return ctsvc_query_exec(query); } @@ -43,6 +46,8 @@ API int contacts_phone_log_delete(contacts_phone_log_delete_e op, ...) char *number = NULL; va_list args; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_PHONELOG_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write (phonelog)"); switch(op) { case CONTACTS_PHONE_LOG_DELETE_BY_ADDRESS: va_start(args, op); diff --git a/native/ctsvc_service.c b/native/ctsvc_service.c index dca23c1..70287fd 100644 --- a/native/ctsvc_service.c +++ b/native/ctsvc_service.c @@ -27,6 +27,10 @@ #include +#ifdef _CONTACTS_NATIVE +#include +#endif + #include "contacts.h" #include "ctsvc_internal.h" #include "ctsvc_socket.h" @@ -34,6 +38,7 @@ #include "ctsvc_inotify.h" #include "ctsvc_db_init.h" #include "ctsvc_setting.h" +#include "ctsvc_db_access_control.h" static int ctsvc_connection = 0; static __thread int thread_connection = 0; @@ -69,32 +74,68 @@ API int contacts_connect2() CTS_DBG("System : Contacts service has been already connected"); ctsvc_connection++; - ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); - if (0 == thread_connection) { ret = ctsvc_db_init(); if (ret != CONTACTS_ERROR_NONE) { CTS_ERR("ctsvc_db_init() Failed(%d)", ret); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); return ret; } +#ifdef _CONTACTS_NATIVE + // Access control : get cookie from security-server + char *smack_label = NULL; + size_t cookie_size = security_server_get_cookie_size(); + + if (cookie_size <= 0) { + CTS_ERR("security_server_get_cookie_size : cookie_size is %d", cookie_size); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); + return CONTACTS_ERROR_SYSTEM; + } + + char cookie[cookie_size]; + cookie[0] = '\0'; + ret = security_server_request_cookie(cookie, cookie_size); + if(ret < 0) { + CTS_ERR("security_server_request_cookie fail (%d)", ret); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); + return CONTACTS_ERROR_SYSTEM; + } + + smack_label = security_server_get_smacklabel_cookie(cookie); + if (NULL == smack_label) { + CTS_ERR("security_server_get_smacklabel_cookie fail"); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); + return CONTACTS_ERROR_SYSTEM; + } + + // In case of server, set SMACK label in ctsvc_ipc_server_connect() + ctsvc_set_client_access_info(smack_label, cookie); + free(smack_label); +#endif } thread_connection++; + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); + return CONTACTS_ERROR_NONE; } API int contacts_disconnect2() { int ret; - if (1 == thread_connection) + ctsvc_mutex_lock(CTS_MUTEX_CONNECTION); + + if (1 == thread_connection) { ctsvc_db_deinit(); + ctsvc_unset_client_access_info(); + } else if (thread_connection <= 0) { CTS_DBG("System : please call contacts_connect_on_thread(), thread_connection count is (%d)", thread_connection); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); return CONTACTS_ERROR_INVALID_PARAMETER; } thread_connection--; - ctsvc_mutex_lock(CTS_MUTEX_CONNECTION); if (1 == ctsvc_connection) { ctsvc_socket_final(); ctsvc_inotify_close(); @@ -151,8 +192,26 @@ API int contacts_connect_on_thread() ctsvc_mutex_lock(CTS_MUTEX_CONNECTION); - if (0 == thread_connection) - { + if (0 == thread_connection) { + ret = ctsvc_socket_init(); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_socket_init() Failed(%d)", ret); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); + return ret; + } + ret = ctsvc_inotify_init(); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_inotify_init() Failed(%d)", ret); + ctsvc_socket_final(); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); + return ret; + } + ctsvc_db_plugin_init(); + ctsvc_view_uri_init(); + ctsvc_register_vconf(); + ret = account_connect(); + if (ACCOUNT_ERROR_NONE != ret) + CTS_ERR("account_connect Failed(%d)", ret); ret = ctsvc_db_init(); if (ret != CONTACTS_ERROR_NONE) { @@ -160,6 +219,36 @@ API int contacts_connect_on_thread() ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); return ret; } + + // Access control : get cookie from security-server + char *smack_label = NULL; + size_t cookie_size = security_server_get_cookie_size(); + + if (cookie_size <= 0) { + CTS_ERR("security_server_get_cookie_size : cookie_size is %d", cookie_size); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); + return CONTACTS_ERROR_SYSTEM; + } + + char cookie[cookie_size]; + cookie[0] = '\0'; + ret = security_server_request_cookie(cookie, cookie_size); + if(ret < 0) { + CTS_ERR("security_server_request_cookie fail (%d)", ret); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); + return CONTACTS_ERROR_SYSTEM; + } + + smack_label = security_server_get_smacklabel_cookie(cookie); + if (NULL == smack_label) { + CTS_ERR("security_server_get_smacklabel_cookie fail"); + ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); + return CONTACTS_ERROR_SYSTEM; + } + + // In case of server, set SMACK label in ctsvc_ipc_server_connect() + ctsvc_set_client_access_info(smack_label, cookie); + free(smack_label); } else { @@ -176,12 +265,18 @@ API int contacts_disconnect_on_thread() { ctsvc_mutex_lock(CTS_MUTEX_CONNECTION); - if (1 == thread_connection) - { + if (1 == thread_connection) { ctsvc_db_deinit(); + ctsvc_unset_client_access_info(); + ctsvc_socket_final(); + ctsvc_inotify_close(); + ctsvc_deregister_vconf(); + ctsvc_view_uri_deinit(); + ctsvc_db_plugin_deinit(); + ret = account_disconnect(); + WARN_IF(ret != ACCOUNT_ERROR_NONE, "account_disconnect Fail(%d)", ret); } - else if (thread_connection <= 0) - { + else if (thread_connection <= 0) { CTS_DBG("System : please call contacts_connect_on_thread(), connection count is (%d)", thread_connection); ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION); return CONTACTS_ERROR_INVALID_PARAMETER; diff --git a/native/ctsvc_setting.c b/native/ctsvc_setting.c index 433847f..f0055b3 100644 --- a/native/ctsvc_setting.c +++ b/native/ctsvc_setting.c @@ -31,6 +31,7 @@ #include "ctsvc_setting.h" #include "ctsvc_normalize.h" #include "ctsvc_localize.h" +#include "ctsvc_db_access_control.h" #ifdef _CONTACTS_IPC_SERVER #include "ctsvc_server_change_subject.h" @@ -50,6 +51,9 @@ static const char *CTSVC_VCONF_PHONENUMBER_MIN_MATCH_DIGIT = VCONFKEY_CONTACTS_S API int contacts_setting_get_name_display_order(contacts_name_display_order_e *order) { int ret; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_READ), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact read"); + if (name_display_order < 0) { ret = vconf_get_int(CTSVC_VCONF_DISPLAY_ORDER, &name_display_order); RETVM_IF(ret<0, CONTACTS_ERROR_SYSTEM, "System : vconf_get_int() Failed(%d)", ret); @@ -63,6 +67,8 @@ API int contacts_setting_get_name_display_order(contacts_name_display_order_e *o API int contacts_setting_set_name_display_order(contacts_name_display_order_e order) { int ret; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write"); RETVM_IF(CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST != order && CONTACTS_NAME_DISPLAY_ORDER_LASTFIRST != order, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter : The parameter(order:%d) is Invalid", name_display_order); @@ -80,6 +86,8 @@ API int contacts_setting_set_name_display_order(contacts_name_display_order_e or API int contacts_setting_get_name_sorting_order(contacts_name_sorting_order_e *order) { int ret; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_READ), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact read"); if (name_sorting_order < 0) { ret = vconf_get_int(CTSVC_VCONF_SORTING_ORDER, &name_sorting_order); @@ -94,6 +102,8 @@ API int contacts_setting_get_name_sorting_order(contacts_name_sorting_order_e *o API int contacts_setting_set_name_sorting_order(contacts_name_sorting_order_e order) { int ret; + RETVM_IF(!ctsvc_have_permission(CTSVC_PERMISSION_CONTACT_WRITE), CONTACTS_ERROR_PERMISSION_DENIED, + "Permission denied : contact write"); RETVM_IF(CONTACTS_NAME_SORTING_ORDER_FIRSTLAST != order && CONTACTS_NAME_SORTING_ORDER_LASTFIRST != order, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter : The parameter(order:%d) is Invalid", name_sorting_order); diff --git a/packaging/contacts-service.spec b/packaging/contacts-service.spec index 2e8548c..f3fb4b4 100644 --- a/packaging/contacts-service.spec +++ b/packaging/contacts-service.spec @@ -22,9 +22,12 @@ BuildRequires: pkgconfig(pims-ipc) BuildRequires: pkgconfig(accounts-svc) BuildRequires: pkgconfig(badge) BuildRequires: pkgconfig(libexif) +BuildRequires: pkgconfig(libsmack) +BuildRequires: pkgconfig(security-server) Requires(post): /usr/bin/sqlite3, /bin/chmod, /bin/chown Requires(post): /usr/bin/vconftool Requires(post): /sbin/ldconfig +Requires(post): telephony-daemon Requires(postun): /sbin/ldconfig %description @@ -33,6 +36,8 @@ Contacts Service Library %package -n contacts-service2 Summary: New Contacts service library Group: Development/Libraries +Requires(post): telephony-daemon +Requires(post): libprivilege-control-conf %description -n contacts-service2 New Contact Serivce Library @@ -108,7 +113,7 @@ vconftool set -t int db/contacts-svc/phonenumber_min_match_digit 8 -g 6005 -s co /usr/lib/systemd/user/contacts-service.service /usr/lib/systemd/user/tizen-middleware.target.wants/contacts-service.service %config(noreplace) /opt/usr/dbspace/.contacts-svc.db* - +/opt/etc/smack/accesses.d/%{name}2.rule %files -n contacts-service2-devel %manifest %{name}.manifest diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 599b0dc..4d6bb23 100755 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -68,6 +68,7 @@ SET(SRCS ${CMAKE_SOURCE_DIR}/native/ctsvc_activity.c + ${CMAKE_SOURCE_DIR}/native/ctsvc_db_access_control.c ${CMAKE_SOURCE_DIR}/native/ctsvc_db_init.c ${CMAKE_SOURCE_DIR}/native/ctsvc_db_plugin_activity.c @@ -160,7 +161,7 @@ SET(SRCS ) INCLUDE(FindPkgConfig) -pkg_check_modules(ctsvc_server_pkgs REQUIRED glib-2.0 pims-ipc gobject-2.0 tapi dlog capi-media-image-util accounts-svc badge libexif) +pkg_check_modules(ctsvc_server_pkgs REQUIRED glib-2.0 pims-ipc gobject-2.0 tapi dlog capi-media-image-util accounts-svc badge libexif libsmack) FOREACH(flag ${ctsvc_server_pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") diff --git a/server/ctsvc_ipc_server.c b/server/ctsvc_ipc_server.c index 5d6eec9..dace8c5 100644 --- a/server/ctsvc_ipc_server.c +++ b/server/ctsvc_ipc_server.c @@ -18,10 +18,12 @@ */ #include +#include #include "ctsvc_service.h" #include "ctsvc_db_init.h" #include "ctsvc_db_query.h" +#include "ctsvc_db_access_control.h" #include "ctsvc_ipc_marshal.h" #include "ctsvc_internal.h" @@ -30,27 +32,75 @@ void ctsvc_ipc_server_connect(pims_ipc_h ipc, pims_ipc_data_h indata, pims_ipc_data_h *outdata, void *userdata) { + CTS_FN_CALL; int ret = CONTACTS_ERROR_NONE; + size_t cookie_size = 0; + char *smack_label = NULL; + char *cookie = NULL; + char *buf = NULL; + gsize buf_len; + + if (indata) { + // Access control : get cookie from indata + ret = ctsvc_ipc_unmarshal_unsigned_int(indata, &cookie_size); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_ipc_marshal_int fail"); + goto ERROR_RETURN; + } + + if (cookie_size <= 0) { + CTS_ERR("cookie size is %d", cookie_size); + ret = CONTACTS_ERROR_IPC; + goto ERROR_RETURN; + } + + ret = ctsvc_ipc_unmarshal_string(indata, &buf); + if (ret != CONTACTS_ERROR_NONE) { + CTS_ERR("ctsvc_ipc_unmarshal_string fail"); + goto ERROR_RETURN; + } + cookie = (char*)g_base64_decode((const gchar*)buf, &buf_len); + + smack_label = security_server_get_smacklabel_cookie(cookie); + if (NULL == smack_label) { + CTS_ERR("security_server_get_smacklabel_cookie fail"); + ret = CONTACTS_ERROR_SYSTEM; + goto ERROR_RETURN; + } + } + else { + CTS_ERR("There is no indata fail"); + ret = CONTACTS_ERROR_SYSTEM; + goto ERROR_RETURN; + } ret = contacts_connect2(); + if (CONTACTS_ERROR_NONE == ret) + ctsvc_set_client_access_info(smack_label, cookie); + +ERROR_RETURN: if (outdata) { *outdata = pims_ipc_data_create(0); if (!*outdata) { CTS_ERR("pims_ipc_data_create fail"); - return; + goto DATA_FREE; } + if (pims_ipc_data_put(*outdata,(void*)&ret,sizeof(int)) != 0) { pims_ipc_data_destroy(*outdata); *outdata = NULL; CTS_ERR("pims_ipc_data_put fail"); - return; + goto DATA_FREE; } } else { CTS_ERR("outdata is NULL"); } - return; +DATA_FREE: + free(smack_label); + free(cookie); + free(buf); } void ctsvc_ipc_server_disconnect(pims_ipc_h ipc, pims_ipc_data_h indata, pims_ipc_data_h *outdata, void *userdata) diff --git a/server/ctsvc_server.c b/server/ctsvc_server.c index fd0e7e4..0d3a5ab 100644 --- a/server/ctsvc_server.c +++ b/server/ctsvc_server.c @@ -30,6 +30,7 @@ #include "ctsvc_server_socket.h" #include "ctsvc_server_utils.h" #include "ctsvc_server_bg.h" +#include "ctsvc_db_access_control.h" #include "ctsvc_ipc_define.h" #include "ctsvc_ipc_server.h" @@ -98,6 +99,7 @@ static int __server_main(void) CTS_ERR("contacts_connect2 fail(%d)", ret); break; } + ctsvc_set_client_access_info("contacts-service", NULL); ctsvc_server_bg_add_cb(); ctsvc_server_bg_delete_start(); @@ -111,6 +113,8 @@ static int __server_main(void) ctsvc_server_bg_remove_cb(); + ctsvc_unset_client_access_info(); + ret = contacts_disconnect2(); if (CONTACTS_ERROR_NONE != ret) CTS_DBG("%d", ret); diff --git a/server/ctsvc_server_bg.c b/server/ctsvc_server_bg.c index 13072a9..dc29af5 100644 --- a/server/ctsvc_server_bg.c +++ b/server/ctsvc_server_bg.c @@ -30,6 +30,7 @@ #include "ctsvc_server_bg.h" #include "ctsvc_utils.h" #include "ctsvc_db_plugin_addressbook_helper.h" +#include "ctsvc_db_access_control.h" #define CTSVC_SERVER_BG_DELETE_COUNT 50 #define CTSVC_SERVER_BG_DELETE_STEP_TIME 1 @@ -332,6 +333,7 @@ static gpointer __ctsvc_server_bg_delete(gpointer user_data) free(callback_data); continue; } + ctsvc_set_client_access_info("contacts-service", NULL); while(1) { sleep(CTSVC_SERVER_BG_DELETE_STEP_TIME); // sleep 1 sec. @@ -341,6 +343,9 @@ static gpointer __ctsvc_server_bg_delete(gpointer user_data) break; } } + + ctsvc_unset_client_access_info(); + ret = contacts_disconnect2(); if (CONTACTS_ERROR_NONE != ret) CTS_ERR("contacts_disconnect2 Fail(%d)", ret); diff --git a/server/ctsvc_server_socket.c b/server/ctsvc_server_socket.c index b50147c..c23e9c8 100644 --- a/server/ctsvc_server_socket.c +++ b/server/ctsvc_server_socket.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "contacts.h" #include "ctsvc_internal.h" @@ -140,6 +141,10 @@ static gboolean __ctsvc_server_socket_request_handler(GIOChannel *src, GIOCondit gpointer data) { int ret; + int fd; + bool have_read_permission = false; + bool have_write_permission = false; + ctsvc_socket_msg_s msg = {0}; CTS_FN_CALL; @@ -148,16 +153,32 @@ static gboolean __ctsvc_server_socket_request_handler(GIOChannel *src, GIOCondit return FALSE; } - ret = __ctsvc_server_socket_safe_read(g_io_channel_unix_get_fd(src), (char *)&msg, sizeof(msg)); + fd = g_io_channel_unix_get_fd(src); + ret = __ctsvc_server_socket_safe_read(fd, (char *)&msg, sizeof(msg)); RETVM_IF(-1 == ret, TRUE, "__ctsvc_server_socket_safe_read() Failed(errno = %d)", errno); CTS_DBG("attach number = %d", msg.attach_num); + if (SECURITY_SERVER_API_SUCCESS == security_server_check_privilege_by_sockfd(fd, "contacts-service::svc", "r")) + have_read_permission = true; + if (SECURITY_SERVER_API_SUCCESS == security_server_check_privilege_by_sockfd(fd, "contacts-service::svc", "w")) + have_write_permission = true; + switch (msg.type) { case CTSVC_SOCKET_MSG_TYPE_REQUEST_IMPORT_SIM: + if (!have_write_permission) { + CTS_ERR("write permission denied"); + ctsvc_server_socket_return(src, CONTACTS_ERROR_PERMISSION_DENIED, 0, NULL); + return TRUE; + } __ctsvc_server_socket_import_sim(src); break; case CTSVC_SOCKET_MSG_TYPE_REQUEST_SIM_INIT_COMPLETE: + if (!have_read_permission) { + CTS_ERR("read permission denied"); + ctsvc_server_socket_return(src, CONTACTS_ERROR_PERMISSION_DENIED, 0, NULL); + return TRUE; + } __ctsvc_server_socket_get_sim_init_status(src); break; default: -- 2.7.4