From: Zofia Abramowska Date: Wed, 20 May 2015 11:48:06 +0000 (+0200) Subject: Add cynara checks for socket communication X-Git-Tag: accepted/tizen/mobile/20151126.112920~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=857f0a39657847e188adba869e9f61758b3a6080;p=platform%2Fcore%2Fappfw%2Fnotification-service.git Add cynara checks for socket communication Add cynara permission check before any PACKET_REQ request is processed inside notification-service. Used privilege is http://tizen.org/privilege/notification. Change-Id: Ie68f7531deb464f7474d277198ac65daa3afad54 --- diff --git a/configure.ac b/configure.ac index ae138cc..62b9fcf 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ AC_CHECK_FUNC([dlopen], [], AC_CHECK_LIB([dl], [dlopen], DLOPEN_LIBS="-ldl")) AC_SUBST(DLOPEN_LIBS) -PKG_CHECK_MODULES([TIZEN], [eina ecore com-core notification dbus-1 bluetooth-api dlog libwlmessage vconf vconf-internal-keys]) +PKG_CHECK_MODULES([TIZEN], [eina ecore com-core notification dbus-1 bluetooth-api dlog libwlmessage vconf vconf-internal-keys cynara-client cynara-creds-socket cynara-session]) AC_SUBST(TIZEN_CFLAGS) AC_SUBST(TIZEN_LIBS) diff --git a/notification_service.c b/notification_service.c index 0ddf3f2..2a79941 100644 --- a/notification_service.c +++ b/notification_service.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (c) 2000 - 2015 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. @@ -318,6 +318,9 @@ static int service_thread_main(struct tcb *tcb, struct packet *packet, void *dat switch (packet_type(packet)) { case PACKET_REQ: /* Need to send reply packet */ + if (!check_cynara(tcb)) { + return -EPERM; + } for (i = 0; service_req_table[i].cmd; i++) { if (strcmp(service_req_table[i].cmd, command)) continue; diff --git a/packaging/notification-service.spec b/packaging/notification-service.spec index d0b9009..7d2f80f 100644 --- a/packaging/notification-service.spec +++ b/packaging/notification-service.spec @@ -11,6 +11,9 @@ Source0: %{name}-%{version}.tar.bz2 BuildRequires: pkgconfig(eina) BuildRequires: pkgconfig(ecore) BuildRequires: pkgconfig(com-core) +BuildRequires: pkgconfig(cynara-client) +BuildRequires: pkgconfig(cynara-session) +BuildRequires: pkgconfig(cynara-creds-socket) BuildRequires: pkgconfig(notification) BuildRequires: pkgconfig(dbus-1) BuildRequires: pkgconfig(dbus-glib-1) diff --git a/service_common.c b/service_common.c index fdf48c1..dfc24b7 100644 --- a/service_common.c +++ b/service_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (c) 2000 - 2015 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. @@ -27,6 +27,10 @@ #include #include +#include +#include +#include + #include "service_common.h" #define EVT_CH 'e' @@ -57,6 +61,8 @@ struct service_context { pthread_t server_thid; /*!< Server thread Id */ int fd; /*!< Server socket handle */ + cynara *p_cynara; /*!< Cynara handle */ + Eina_List *tcb_list; /*!< TCB list, list of every thread for client connections */ Eina_List *packet_list; @@ -85,6 +91,9 @@ struct tcb { /* Thread controll block */ struct service_context *svc_ctx; pthread_t thid; /*!< Thread Id */ int fd; /*!< Connection handle */ + char *client; /*!< Client socket credential */ + char *user; /*!< User socket credential */ + char *session; /*!< Session context for cynara */ enum tcb_type type; }; @@ -117,6 +126,13 @@ static void *client_packet_pump_main(void *data) ret = 0; recv_state = RECV_INIT; + + /* + * Fill connection credentials + */ + if (!fill_creds(tcb)) { + ret = -EPERM; + } /*! * \note * To escape from the switch statement, we use this ret value @@ -360,6 +376,9 @@ static inline void tcb_destroy(struct service_context *svc_ctx, struct tcb *tcb) * Close the connection, and then collecting the return value of thread */ secure_socket_destroy_handle(tcb->fd); + free(tcb->user); + free(tcb->client); + free(tcb->session); status = pthread_join(tcb->thid, &ret); @@ -564,8 +583,8 @@ static void *server_main(void *data) */ struct service_context *service_common_create(const char *addr, int (*service_thread_main)(struct tcb *tcb, struct packet *packet, void *data), void *data) { - int status; - struct service_context *svc_ctx; + int status, ret; + struct service_context *svc_ctx = NULL; if (!service_thread_main || !addr) { return NULL; @@ -611,12 +630,24 @@ struct service_context *service_common_create(const char *addr, int (*service_th return NULL; } + ret = cynara_initialize(&svc_ctx->p_cynara, NULL); + if (ret != CYNARA_API_SUCCESS) { + print_cynara_error("Cynara initialize failed", ret); + status = pthread_mutex_destroy(&svc_ctx->packet_list_lock); + CLOSE_PIPE(svc_ctx->evt_pipe); + CLOSE_PIPE(svc_ctx->tcb_pipe); + secure_socket_destroy_handle(svc_ctx->fd); + free(svc_ctx); + return NULL; + } + status = pthread_create(&svc_ctx->server_thid, NULL, server_main, svc_ctx); if (status != 0) { status = pthread_mutex_destroy(&svc_ctx->packet_list_lock); CLOSE_PIPE(svc_ctx->evt_pipe); CLOSE_PIPE(svc_ctx->tcb_pipe); secure_socket_destroy_handle(svc_ctx->fd); + cynara_finish(svc_ctx->p_cynara); free(svc_ctx); return NULL; } @@ -643,9 +674,10 @@ int service_common_destroy(struct service_context *svc_ctx) secure_socket_destroy_handle(svc_ctx->fd); status = pthread_join(svc_ctx->server_thid, &ret); - status = pthread_mutex_destroy(&svc_ctx->packet_list_lock); + (void)cynara_finish(svc_ctx->p_cynara); + CLOSE_PIPE(svc_ctx->evt_pipe); CLOSE_PIPE(svc_ctx->tcb_pipe); free(svc_ctx); @@ -795,4 +827,72 @@ int service_common_del_timer(struct service_context *svc_ctx, struct service_eve return 0; } + +void print_cynara_error(int ret, char *msg) { + char buff[255] = {0}; + if (cynara_strerror(ret, buff, sizeof(buff)) != CYNARA_API_SUCCESS) { + fprintf(stderr, "Cynara strerror failed\n"); + } + fprintf(stderr, "%s (%d) : %s\n", msg, ret, buff); +} + +int fill_creds(struct tcb *tcb) { + int ret; + char *client = NULL; + char *user = NULL; + char *session = NULL; + pid_t pid; + + ret = cynara_creds_socket_get_client(tcb->fd, CLIENT_METHOD_DEFAULT, &client); + if (ret != CYNARA_API_SUCCESS) { + print_cynara_error(ret, "Cynara creds socket get client failed"); + return 0; + } + + ret = cynara_creds_socket_get_user(tcb->fd, USER_METHOD_DEFAULT, &user); + if (ret != CYNARA_API_SUCCESS) { + free(client); + print_cynara_error(ret, "Cynara creds socket get user failed"); + return 0; + } + + ret = cynara_creds_socket_get_pid(tcb->fd, &pid); + if (ret != CYNARA_API_SUCCESS) { + free(client); + free(user); + print_cynara_error(ret, "Cynara creds socket get pid failed"); + return 0; + } + + session = cynara_session_from_pid(pid); + if (!session) { + free(client); + free(user); + fprintf(stderr, "Cynara session from pid failed"); + return 0; + } + + tcb->user = user; + tcb->client = client; + tcb->session = session; + return 1; +} + +int check_cynara(struct tcb *tcb) { + int fd = tcb->fd; + int ret; + static const char *privilege = "http://tizen.org/privilege/notification"; + + ret = cynara_check(tcb->svc_ctx->p_cynara, tcb->client, tcb->session, tcb->user, privilege); + + if (ret == CYNARA_API_ACCESS_ALLOWED) { + return 1; + } + if (ret != CYNARA_API_ACCESS_DENIED) { + print_cynara_error(ret, "Cynara check failed"); + } + + return 0; +} + /* End of a file */ diff --git a/service_common.h b/service_common.h index 6136018..11a5612 100644 --- a/service_common.h +++ b/service_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (c) 2000 - 2015 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. @@ -38,6 +38,9 @@ extern int service_common_unicast_packet(struct tcb *tcb, struct packet *packet) extern struct service_event_item *service_common_add_timer(struct service_context *svc_ctx, double timer, int (*timer_cb)(struct service_context *svc_cx, void *data), void *data); extern int service_common_del_timer(struct service_context *svc_ctx, struct service_event_item *item); +void print_cynara_error(int ret, char *msg); +int check_cynara(struct tcb *tcb); + #define CRITICAL_SECTION_BEGIN(handle) \ do { \ int ret; \