4 * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
24 #include <sys/socket.h>
27 #include <pims-ipc-svc.h>
29 #include <cynara-client.h>
30 #include <cynara-error.h>
31 #include <cynara-session.h>
32 #include <cynara-creds-socket.h>
35 #include "ctsvc_internal.h"
36 #include "ctsvc_struct.h"
37 #include "ctsvc_db_schema.h"
38 #include "ctsvc_db_sqlite.h"
39 #include "ctsvc_socket.h"
40 #include "ctsvc_server_socket.h"
41 #include "ctsvc_server_utils.h"
43 #include "ctsvc_mutex.h"
44 #include "ctsvc_server_sim.h"
45 #include "ctsvc_db_access_control.h"
50 static int sockfd = -1;
58 /* key : socket_fd, value : struct client_info* */
59 static GHashTable *_client_info_table = NULL;
61 static inline int __ctsvc_server_socket_safe_write(int fd, char *buf, int buf_size)
65 ret = write(fd, buf+writed, buf_size);
79 static inline int __ctsvc_server_socket_safe_read(int fd, char *buf, int buf_size)
81 int ret, read_size = 0;
83 ret = read(fd, buf+read_size, buf_size);
96 int ctsvc_server_socket_return(GIOChannel *src, int value, int attach_num, int *attach_size)
100 ctsvc_socket_msg_s msg = {0};
102 RETV_IF(NULL == src, CONTACTS_ERROR_INVALID_PARAMETER);
104 /* RETVM_IF(CONTACTS_ERROR_SYSTEM == value, value, "Socket has problems"); */
105 RETVM_IF(CTSVC_SOCKET_MSG_REQUEST_MAX_ATTACH < attach_num, CONTACTS_ERROR_INTERNAL,
106 "Invalid msg(attach_num = %d)", attach_num);
108 msg.type = CTSVC_SOCKET_MSG_TYPE_REQUEST_RETURN_VALUE;
110 msg.attach_num = attach_num;
112 memcpy(msg.attach_sizes, attach_size, attach_num * sizeof(int));
114 DBG("fd = %d, MSG_TYPE=%d, MSG_VAL=%d, MSG_ATTACH_NUM=%d,"
115 "MSG_ATTACH1=%d, MSG_ATTACH2=%d, MSG_ATTACH3=%d, MSG_ATTACH4=%d",
116 g_io_channel_unix_get_fd(src), msg.type, msg.val, msg.attach_num,
117 msg.attach_sizes[0], msg.attach_sizes[1], msg.attach_sizes[2],
118 msg.attach_sizes[3]);
120 ret = __ctsvc_server_socket_safe_write(g_io_channel_unix_get_fd(src), (char *)&msg, sizeof(msg));
121 RETVM_IF(-1 == ret, CONTACTS_ERROR_SYSTEM,
122 "__ctsvc_server_socket_safe_write() Fail(errno = %d)", errno);
124 return CONTACTS_ERROR_NONE;
127 int ctsvc_server_socket_invoke_cb(GIOChannel *src, int total, int imported_cnt)
131 ctsvc_socket_msg_s msg = {0};
133 RETV_IF(NULL == src, CONTACTS_ERROR_INVALID_PARAMETER);
135 msg.type = CTSVC_SOCKET_MSG_TYPE_REQUEST_INVOKE_CB;
137 msg.data = imported_cnt;
139 DBG("fd = %d, MSG_TYPE=%d, MSG_VAL=%d, MSG_ATTACH_NUM=%d,"
140 "MSG_ATTACH1=%d, MSG_ATTACH2=%d, MSG_ATTACH3=%d, MSG_ATTACH4=%d",
141 g_io_channel_unix_get_fd(src), msg.type, msg.val, msg.attach_num,
142 msg.attach_sizes[0], msg.attach_sizes[1], msg.attach_sizes[2],
143 msg.attach_sizes[3]);
145 ret = __ctsvc_server_socket_safe_write(g_io_channel_unix_get_fd(src), (char *)&msg, sizeof(msg));
146 RETVM_IF(-1 == ret, CONTACTS_ERROR_SYSTEM,
147 "__ctsvc_server_socket_safe_write() Fail(errno = %d)", errno);
149 return CONTACTS_ERROR_NONE;
153 static void __ctsvc_server_socket_import_sim(GIOChannel *src, int size)
159 char receiver[CTS_SQL_MAX_LEN] = {0};
162 g_io_channel_read_chars(src, receiver, size, &len, &gerr);
164 ERR("g_io_channel_read_chars() Fail(%s)", gerr->message);
168 DBG("Receiver = %s(%d), read_size = %d", receiver, len, size);
172 receiver[len] = '\0';
173 DBG("sim_id %d", atoi(receiver));
174 ret = ctsvc_server_sim_import_contact(src, atoi(receiver));
176 ret = ctsvc_server_sim_import_contact(src, 0);
179 if (CONTACTS_ERROR_NONE != ret) {
180 ERR("ctsvc_server_sim_import_contact() Fail(%d)", ret);
181 ctsvc_server_socket_return(src, ret, 0, NULL);
185 static void __ctsvc_server_socket_get_sim_init_status(GIOChannel *src, int size)
192 char receiver[CTS_SQL_MAX_LEN] = {0};
195 g_io_channel_read_chars(src, receiver, size, &len, &gerr);
197 ERR("g_io_channel_read_chars() Fail(%s)", gerr->message);
201 DBG("Receiver = %s(%d), read_size = %d", receiver, len, size);
205 receiver[len] = '\0';
206 DBG("sim_id : %d", atoi(receiver));
207 ret = ctsvc_server_socket_get_sim_init_status(src, atoi(receiver));
209 ret = ctsvc_server_socket_get_sim_init_status(src, 0);
212 if (CONTACTS_ERROR_NONE != ret) {
213 ERR("ctsvc_server_socket_get_sim_init_status() Fail(%d)", ret);
214 ctsvc_server_socket_return(src, ret, 0, NULL);
218 int ctsvc_server_socket_return_sim_int(GIOChannel *src, int value)
223 char count_str[CTS_SQL_MAX_LEN] = {0};
225 str_len = snprintf(count_str, sizeof(count_str), "%d", value);
226 ret = ctsvc_server_socket_return(src, CONTACTS_ERROR_NONE, 1, &str_len);
227 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_server_socket_return() Fail(%d)", ret);
228 DBG("count_str : %s", count_str);
229 ret = __ctsvc_server_socket_safe_write(g_io_channel_unix_get_fd(src), count_str, str_len);
230 RETVM_IF(-1 == ret, CONTACTS_ERROR_SYSTEM, "__ctsvc_server_socket_safe_write() Fail(errno = %d)", errno);
232 return CONTACTS_ERROR_NONE;
235 static void __ctsvc_server_socket_read_flush(GIOChannel *src, int size)
239 char receiver[CTS_SQL_MAX_LEN] = {0};
244 g_io_channel_read_chars(src, receiver, size, &len, &gerr);
246 ERR("g_io_channel_read_chars() Fail(%s)", gerr->message);
252 static cynara *_cynara = NULL;
253 static int _ctsvc_server_initialize_cynara()
256 ctsvc_mutex_lock(CTS_MUTEX_CYNARA);
257 ret = cynara_initialize(&_cynara, NULL);
258 ctsvc_mutex_unlock(CTS_MUTEX_CYNARA);
259 if (CYNARA_API_SUCCESS != ret) {
260 /* LCOV_EXCL_START */
261 char errmsg[1024] = {0};
262 cynara_strerror(ret, errmsg, sizeof(errmsg));
263 ERR("cynara_initialize() Fail(%d,%s)", ret, errmsg);
264 return CONTACTS_ERROR_SYSTEM;
267 return CONTACTS_ERROR_NONE;
270 static void _ctsvc_server_finalize_cynara()
274 ctsvc_mutex_lock(CTS_MUTEX_CYNARA);
275 ret = cynara_finish(_cynara);
277 ctsvc_mutex_unlock(CTS_MUTEX_CYNARA);
278 if (CYNARA_API_SUCCESS != ret) {
279 /* LCOV_EXCL_START */
280 char errmsg[1024] = {0};
281 cynara_strerror(ret, errmsg, sizeof(errmsg));
282 ERR("cynara_finish() Fail(%d,%s)", ret, errmsg);
286 /* LCOV_EXCL_START */
287 static bool _ctsvc_server_check_privilege(struct client_info *info, const char *privilege)
289 RETV_IF(NULL == info, false);
291 ctsvc_mutex_lock(CTS_MUTEX_CYNARA);
292 int ret = cynara_check(_cynara, info->smack, info->client_session, info->uid, privilege);
293 ctsvc_mutex_unlock(CTS_MUTEX_CYNARA);
294 if (CYNARA_API_ACCESS_ALLOWED == ret)
300 static gboolean __ctsvc_server_socket_request_handler(GIOChannel *src, GIOCondition condition,
305 bool have_read_permission = false;
306 bool have_write_permission = false;
308 ctsvc_socket_msg_s msg = {0};
310 fd = g_io_channel_unix_get_fd(src);
312 if (G_IO_HUP & condition) {
313 ctsvc_mutex_lock(CTS_MUTEX_SOCKET_CLIENT_INFO);
314 if (_client_info_table)
315 g_hash_table_remove(_client_info_table, GINT_TO_POINTER(fd));
316 ctsvc_mutex_unlock(CTS_MUTEX_SOCKET_CLIENT_INFO);
320 /* LCOV_EXCL_START */
321 ret = __ctsvc_server_socket_safe_read(fd, (char *)&msg, sizeof(msg));
322 RETVM_IF(-1 == ret, TRUE, "__ctsvc_server_socket_safe_read() Fail(errno = %d)", errno);
324 DBG("attach number = %d", msg.attach_num);
326 bool have_telephony_feature = false;
327 have_telephony_feature = ctsvc_server_have_telephony_feature();
328 if (false == have_telephony_feature) {
329 ERR("Telephony feature disabled");
330 __ctsvc_server_socket_read_flush(src, msg.attach_sizes[0]); /* sim_id */
331 ctsvc_server_socket_return(src, CONTACTS_ERROR_NOT_SUPPORTED, 0, NULL);
335 ctsvc_mutex_lock(CTS_MUTEX_SOCKET_CLIENT_INFO);
336 struct client_info *info = g_hash_table_lookup(_client_info_table, GINT_TO_POINTER(fd));
337 have_read_permission = _ctsvc_server_check_privilege(info, CTSVC_PRIVILEGE_CONTACT_READ);
338 if (!have_read_permission)
339 INFO("fd(%d) : does not have contact read permission", fd);
341 have_write_permission = _ctsvc_server_check_privilege(info, CTSVC_PRIVILEGE_CONTACT_WRITE);
342 if (!have_write_permission)
343 INFO("fd(%d) : does not have contact write permission", fd);
344 ctsvc_mutex_unlock(CTS_MUTEX_SOCKET_CLIENT_INFO);
347 case CTSVC_SOCKET_MSG_TYPE_REQUEST_IMPORT_SIM:
348 if (false == have_write_permission) {
349 ERR("write permission denied");
350 __ctsvc_server_socket_read_flush(src, msg.attach_sizes[0]); /* sim_id */
351 ctsvc_server_socket_return(src, CONTACTS_ERROR_PERMISSION_DENIED, 0, NULL);
354 __ctsvc_server_socket_import_sim(src, msg.attach_sizes[0]);
356 case CTSVC_SOCKET_MSG_TYPE_REQUEST_SIM_INIT_COMPLETE:
357 if (false == have_read_permission) {
358 ERR("read permission denied");
359 __ctsvc_server_socket_read_flush(src, msg.attach_sizes[0]); /* sim_id */
360 ctsvc_server_socket_return(src, CONTACTS_ERROR_PERMISSION_DENIED, 0, NULL);
363 __ctsvc_server_socket_get_sim_init_status(src, msg.attach_sizes[0]);
365 case CTSVC_SOCKET_MSG_TYPE_CANCEL_IMPORT_SIM:
366 ctsvc_server_sim_cancel_import();
370 ERR("Unknown request type(%d)", msg.type);
377 static void _ctsvc_server_destroy_client_info(gpointer p)
379 struct client_info *info = p;
385 free(info->client_session);
389 static int _ctsvc_server_create_client_info(int fd, struct client_info **p_info)
393 char errmsg[1024] = {0};
395 struct client_info *info = calloc(1, sizeof(struct client_info));
397 /* LCOV_EXCL_START */
398 ERR("calloc() return NULL");
399 return CONTACTS_ERROR_SYSTEM;
403 ret = cynara_creds_socket_get_client(fd, CLIENT_METHOD_SMACK, &(info->smack));
404 if (CYNARA_API_SUCCESS != ret) {
405 /* LCOV_EXCL_START */
406 cynara_strerror(ret, errmsg, sizeof(errmsg));
407 ERR("cynara_creds_socket_get_client() Fail(%d,%s)", ret, errmsg);
408 _ctsvc_server_destroy_client_info(info);
409 return CONTACTS_ERROR_SYSTEM;
413 ret = cynara_creds_socket_get_user(fd, USER_METHOD_UID, &(info->uid));
414 if (CYNARA_API_SUCCESS != ret) {
415 /* LCOV_EXCL_START */
416 cynara_strerror(ret, errmsg, sizeof(errmsg));
417 ERR("cynara_creds_socket_get_user() Fail(%d,%s)", ret, errmsg);
418 _ctsvc_server_destroy_client_info(info);
419 return CONTACTS_ERROR_SYSTEM;
423 ret = cynara_creds_socket_get_pid(fd, &pid);
424 if (CYNARA_API_SUCCESS != ret) {
425 /* LCOV_EXCL_START */
426 cynara_strerror(ret, errmsg, sizeof(errmsg));
427 ERR("cynara_creds_socket_get_pid() Fail(%d,%s)", ret, errmsg);
428 _ctsvc_server_destroy_client_info(info);
429 return CONTACTS_ERROR_SYSTEM;
433 info->client_session = cynara_session_from_pid(pid);
434 if (NULL == info->client_session) {
435 /* LCOV_EXCL_START */
436 WARN("cynara_session_from_pid() return NULL");
437 info->client_session = strdup("");
442 return CONTACTS_ERROR_NONE;
446 static gboolean __ctsvc_server_socket_handler(GIOChannel *src,
447 GIOCondition condition, gpointer data)
453 int client_sockfd, sockfd = (int)data;
454 struct sockaddr_un clientaddr;
455 socklen_t client_len = sizeof(clientaddr);
457 client_sockfd = accept(sockfd, (struct sockaddr *)&clientaddr, &client_len);
458 RETVM_IF(-1 == client_sockfd, TRUE, "accept() Fail(errno = %d)", errno);
460 if (NULL == _client_info_table)
461 _client_info_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, _ctsvc_server_destroy_client_info);
462 struct client_info *info = NULL;
463 ret = _ctsvc_server_create_client_info(client_sockfd, &info);
464 if (CONTACTS_ERROR_NONE != ret)
465 /* LCOV_EXCL_START */
466 ERR("_create_client_info() Fail(%d)", ret);
469 g_hash_table_insert(_client_info_table, GINT_TO_POINTER(client_sockfd), info);
471 channel = g_io_channel_unix_new(client_sockfd);
472 g_io_add_watch(channel, G_IO_IN|G_IO_HUP, __ctsvc_server_socket_request_handler, NULL);
473 g_io_channel_unref(channel);
478 int ctsvc_server_socket_init(void)
484 struct sockaddr_un addr;
487 _ctsvc_server_initialize_cynara();
489 char sock_file[CTSVC_PATH_MAX_LEN] = {0};
490 snprintf(sock_file, sizeof(sock_file), CTSVC_SOCK_PATH"/%s", getuid(), CTSVC_SOCKET_FILE);
493 bzero(&addr, sizeof(addr));
494 addr.sun_family = AF_UNIX;
496 wrn = snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", sock_file);
499 /* LCOV_EXCL_START */
500 WARN("Error writing in sock file (%s)", sock_file);
503 sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
504 RETVM_IF(-1 == sockfd, CONTACTS_ERROR_SYSTEM, "socket() Fail(errno = %d)", errno);
506 ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
508 /* LCOV_EXCL_START */
510 ERR("bind() Fail(errno = %d)", errno);
511 return CONTACTS_ERROR_SYSTEM;
515 ret = chown(sock_file, getuid(), CTS_SECURITY_FILE_GROUP);
517 /* LCOV_EXCL_START */
518 ERR("chown(%s) Fail(%d) errno = %d", sock_file, ret, errno);
521 ret = chmod(sock_file, CTS_SECURITY_DEFAULT_PERMISSION);
523 /* LCOV_EXCL_START */
524 ERR("chmod(%s) Fail(%d)", sock_file, ret);
527 ret = listen(sockfd, 30);
529 /* LCOV_EXCL_START */
531 ERR("listen() Fail(errno = %d)", errno);
532 return CONTACTS_ERROR_SYSTEM;
536 gio = g_io_channel_unix_new(sockfd);
537 g_io_add_watch(gio, G_IO_IN, __ctsvc_server_socket_handler, (gpointer)sockfd);
539 return CONTACTS_ERROR_NONE;
542 int ctsvc_server_socket_deinit(void)
544 _ctsvc_server_finalize_cynara();
547 return CONTACTS_ERROR_NONE;