User level smack control added for notification
[apps/livebox/data-provider-master.git] / src / badge_service.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18
19 #include <Eina.h>
20
21 #include <dlog.h>
22 #include <livebox-errno.h>
23 #include <packet.h>
24
25 #include <sys/smack.h>
26
27 #include <badge.h>
28 #include <badge_db.h>
29 #include <security-server.h>
30
31 #include "service_common.h"
32 #include "debug.h"
33 #include "util.h"
34 #include "conf.h"
35
36 static struct info {
37         Eina_List *context_list;
38         struct service_context *svc_ctx;
39 } s_info = {
40         .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
41         .svc_ctx = NULL, /*!< \WARN: This is only used for MAIN THREAD */
42 };
43
44 #define ENABLE_BS_ACCESS_CONTROL 0
45
46 struct context {
47         struct tcb *tcb;
48         double seq;
49 };
50
51 struct badge_service {
52         const char *cmd;
53         void (*handler)(struct tcb *tcb, struct packet *packet, void *data);
54         const char *rule;
55         const char *access;
56 };
57
58 /*!
59  * FUNCTIONS to handle badge
60  */
61 static inline char *get_string(char *string)
62 {
63         if (string == NULL) {
64                 return NULL;
65         }
66         if (string[0] == '\0') {
67                 return NULL;
68         }
69
70         return string;
71 }
72
73 /*!
74  * SERVICE HANDLER
75  */
76 static void _handler_insert_badge(struct tcb *tcb, struct packet *packet, void *data)
77 {
78         int ret = 0, ret_p = 0;
79         struct packet *packet_reply = NULL;
80         struct packet *packet_service = NULL;
81         char *pkgname = NULL;
82         char *writable_pkg = NULL;
83         char *caller = NULL;
84
85         if (packet_get(packet, "sss", &pkgname, &writable_pkg, &caller) == 3) {
86                 pkgname = get_string(pkgname);
87                 writable_pkg = get_string(writable_pkg);
88                 caller = get_string(caller);
89
90                 if (pkgname != NULL && writable_pkg != NULL && caller != NULL) {
91                         ret = badge_db_insert(pkgname, writable_pkg, caller);
92
93                 } else {
94                         ret = BADGE_ERROR_INVALID_DATA;
95                 }
96
97                 packet_reply = packet_create_reply(packet, "i", ret);
98                 if (packet_reply) {
99                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
100                                 ErrPrint("Failed to send a reply packet:%d", ret_p);
101                         }
102                         packet_destroy(packet_reply);
103                 } else {
104                         ErrPrint("Failed to create a reply packet");
105                 }
106
107                 if (ret == BADGE_ERROR_NONE) {
108                         packet_service = packet_create("insert_badge", "is", ret, pkgname);
109                         if (packet_service != NULL) {
110                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
111                                         ErrPrint("Failed to send a muticast packet:%d", ret_p);
112                                 }
113                                 packet_destroy(packet_service);
114                         } else {
115                                 ErrPrint("Failed to create a multicast packet");
116                         }
117                 } else {
118                         ErrPrint("Failed to insert a badge:%d", ret);
119                 }
120         } else {
121                 ErrPrint("Failed to get data from the packet");
122         }
123 }
124
125 static void _handler_delete_badge(struct tcb *tcb, struct packet *packet, void *data)
126 {
127         int ret = 0, ret_p = 0;
128         struct packet *packet_reply = NULL;
129         struct packet *packet_service = NULL;
130         char *pkgname = NULL;
131         char *caller = NULL;
132
133         if (packet_get(packet, "ss", &pkgname, &caller) == 2) {
134                 pkgname = get_string(pkgname);
135                 caller = get_string(caller);
136
137                 if (pkgname != NULL && caller != NULL) {
138                         ret = badge_db_delete(pkgname, caller);
139
140                 } else {
141                         ret = BADGE_ERROR_INVALID_DATA;
142                 }
143
144                 packet_reply = packet_create_reply(packet, "i", ret);
145                 if (packet_reply) {
146                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
147                                 ErrPrint("Failed to send a reply packet:%d", ret_p);
148                         }
149                         packet_destroy(packet_reply);
150                 } else {
151                         ErrPrint("Failed to create a reply packet");
152                 }
153
154                 if (ret == BADGE_ERROR_NONE) {
155                         packet_service = packet_create("delete_badge", "is", ret, pkgname);
156                         if (packet_service != NULL) {
157                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
158                                         ErrPrint("Failed to send a muticast packet:%d", ret_p);
159                                 }
160                                 packet_destroy(packet_service);
161                         } else {
162                                 ErrPrint("Failed to create a multicast packet");
163                         }
164                 } else {
165                         ErrPrint("Failed to delete a badge:%d", ret);
166                 }
167         } else {
168                 ErrPrint("Failed to get data from the packet");
169         }
170 }
171
172 static void _handler_set_badge_count(struct tcb *tcb, struct packet *packet, void *data)
173 {
174         int ret = 0, ret_p = 0;
175         struct packet *packet_reply = NULL;
176         struct packet *packet_service = NULL;
177         char *pkgname = NULL;
178         char *caller = NULL;
179         int count = 0;
180
181         if (packet_get(packet, "ssi", &pkgname, &caller, &count) == 3) {
182                 pkgname = get_string(pkgname);
183                 caller = get_string(caller);
184
185                 if (pkgname != NULL && caller != NULL) {
186                         ret = badge_db_set_count(pkgname, caller, count);
187
188                 } else {
189                         ret = BADGE_ERROR_INVALID_DATA;
190                 }
191
192                 packet_reply = packet_create_reply(packet, "i", ret);
193                 if (packet_reply) {
194                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
195                                 ErrPrint("Failed to send a reply packet:%d", ret_p);
196                         }
197                         packet_destroy(packet_reply);
198                 } else {
199                         ErrPrint("Failed to create a reply packet");
200                 }
201
202                 if (ret == BADGE_ERROR_NONE) {
203                         packet_service = packet_create("set_badge_count", "isi", ret, pkgname, count);
204                         if (packet_service != NULL) {
205                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
206                                         ErrPrint("Failed to send a muticast packet:%d", ret_p);
207                                 }
208                                 packet_destroy(packet_service);
209                         } else {
210                                 ErrPrint("Failed to create a multicast packet");
211                         }
212                 } else {
213                         ErrPrint("Failed to set count of badge:%d", ret);
214                 }
215         } else {
216                 ErrPrint("Failed to get data from the packet");
217         }
218 }
219
220 static void _handler_set_display_option(struct tcb *tcb, struct packet *packet, void *data)
221 {
222         int ret = 0, ret_p = 0;
223         struct packet *packet_reply = NULL;
224         struct packet *packet_service = NULL;
225         char *pkgname = NULL;
226         char *caller = NULL;
227         int is_display = 0;
228
229         if (packet_get(packet, "ssi", &pkgname, &caller, &is_display) == 3) {
230                 pkgname = get_string(pkgname);
231                 caller = get_string(caller);
232
233                 if (pkgname != NULL && caller != NULL) {
234                         ret = badge_db_set_display_option(pkgname, caller, is_display);
235
236                 } else {
237                         ret = BADGE_ERROR_INVALID_DATA;
238                 }
239
240                 packet_reply = packet_create_reply(packet, "i", ret);
241                 if (packet_reply) {
242                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
243                                 ErrPrint("Failed to send a reply packet:%d", ret_p);
244                         }
245                         packet_destroy(packet_reply);
246                 } else {
247                         ErrPrint("Failed to create a reply packet");
248                 }
249
250                 if (ret == BADGE_ERROR_NONE) {
251                         packet_service = packet_create("set_disp_option", "isi", ret, pkgname, is_display);
252                         if (packet_service != NULL) {
253                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
254                                         ErrPrint("Failed to send a muticast packet:%d", ret_p);
255                                 }
256                                 packet_destroy(packet_service);
257                         } else {
258                                 ErrPrint("Failed to create a multicast packet");
259                         }
260                 } else {
261                         ErrPrint("Failed to set display option of badge:%d", ret);
262                 }
263         } else {
264                 ErrPrint("Failed to get data from the packet");
265         }
266 }
267
268 static void _handler_service_register(struct tcb *tcb, struct packet *packet, void *data)
269 {
270         int ret = 0;
271         struct packet *packet_reply;
272
273         ret = tcb_client_type_set(tcb, TCB_CLIENT_TYPE_SERVICE);
274         if (ret < 0) {
275                 ErrPrint("Failed to set the type of client:%d", ret);
276         }
277
278         packet_reply = packet_create_reply(packet, "i", ret);
279         if (packet_reply) {
280                 if ((ret = service_common_unicast_packet(tcb, packet_reply)) < 0) {
281                         ErrPrint("Failed to send a reply packet:%d", ret);
282                 }
283                 packet_destroy(packet_reply);
284         } else {
285                 ErrPrint("Failed to create a reply packet");
286         }
287 }
288
289 static int _is_valid_permission(int fd, struct badge_service *service)
290 {
291         int ret;
292
293         if (service->rule != NULL && service->access != NULL) {
294                 ret = security_server_check_privilege_by_sockfd(fd, service->rule, service->access);
295                 if (ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) {
296                         ErrPrint("SMACK:Access denied\n");
297                         return 0;
298                 }
299         }
300
301         return 1;
302 }
303
304 /*!
305  * SERVICE THREAD
306  */
307 static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
308 {
309         int i = 0;
310         const char *command;
311         static struct badge_service service_req_table[] = {
312                 {
313                         .cmd = "insert_badge",
314                         .handler = _handler_insert_badge,
315                         .rule = "data-provider-master::badge.client",
316                         .access = "w",
317                 },
318                 {
319                         .cmd = "delete_badge",
320                         .handler = _handler_delete_badge,
321                         .rule = "data-provider-master::badge.client",
322                         .access = "w",
323                 },
324                 {
325                         .cmd = "set_badge_count",
326                         .handler = _handler_set_badge_count,
327                         .rule = "data-provider-master::badge.client",
328                         .access = "w",
329                 },
330                 {
331                         .cmd = "set_disp_option",
332                         .handler = _handler_set_display_option,
333                         .rule = "data-provider-master::badge.client",
334                         .access = "w",
335                 },
336                 {
337                         .cmd = "service_register",
338                         .handler = _handler_service_register,
339                         .rule = NULL,
340                         .access = NULL,
341                 },
342                 {
343                         .cmd = NULL,
344                         .handler = NULL,
345                         .rule = NULL,
346                         .access = NULL,
347                 },
348         };
349
350         if (!packet) {
351                 DbgPrint("TCB: %p is terminated (NIL packet)\n", tcb);
352                 return 0;
353         }
354
355         command = packet_command(packet);
356         if (!command) {
357                 ErrPrint("Invalid command\n");
358                 return -EINVAL;
359         }
360         DbgPrint("Command: [%s], Packet type[%d]\n", command, packet_type(packet));
361
362         switch (packet_type(packet)) {
363         case PACKET_REQ:
364                 /* Need to send reply packet */
365                 for (i = 0; service_req_table[i].cmd; i++) {
366                         if (strcmp(service_req_table[i].cmd, command))
367                                 continue;
368
369 #if ENABLE_BS_ACCESS_CONTROL
370                         if (_is_valid_permission(tcb_fd(tcb), &(service_req_table[i])) == 1) {
371                                 service_req_table[i].handler(tcb, packet, data);
372                         }
373 #else
374                         _is_valid_permission(tcb_fd(tcb), &(service_req_table[i]));
375                         service_req_table[i].handler(tcb, packet, data);
376 #endif
377                         break;
378                 }
379
380                 break;
381         case PACKET_REQ_NOACK:
382                 break;
383         case PACKET_ACK:
384                 break;
385         default:
386                 ErrPrint("Packet type is not valid[%s]\n", command);
387                 return -EINVAL;
388         }
389
390         /*!
391          * return value has no meanning,
392          * it will be printed by dlogutil.
393          */
394         return 0;
395 }
396
397
398 /*!
399  * MAIN THREAD
400  * Do not try to do anyother operation in these functions
401  */
402 HAPI int badge_service_init(void)
403 {
404         if (s_info.svc_ctx) {
405                 ErrPrint("Already initialized\n");
406                 return LB_STATUS_ERROR_ALREADY;
407         }
408
409         s_info.svc_ctx = service_common_create(BADGE_SOCKET, service_thread_main, NULL);
410         if (!s_info.svc_ctx) {
411                 ErrPrint("Unable to activate service thread\n");
412                 return LB_STATUS_ERROR_FAULT;
413         }
414
415         if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), BADGE_SMACK_LABEL, SMACK_LABEL_IPOUT) != 0) {
416                 if (errno != EOPNOTSUPP) {
417                         ErrPrint("Unable to set SMACK label(%d)\n", errno);
418                         service_common_destroy(s_info.svc_ctx);
419                         s_info.svc_ctx = NULL;
420                         return LB_STATUS_ERROR_FAULT;
421                 }
422         }
423
424         if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), BADGE_SMACK_LABEL, SMACK_LABEL_IPIN) != 0) {
425                 if (errno != EOPNOTSUPP) {
426                         ErrPrint("Unable to set SMACK label(%d)\n", errno);
427                         service_common_destroy(s_info.svc_ctx);
428                         s_info.svc_ctx = NULL;
429                         return LB_STATUS_ERROR_FAULT;
430                 }
431         }
432
433         DbgPrint("Successfully initiated\n");
434         return LB_STATUS_SUCCESS;
435 }
436
437 HAPI int badge_service_fini(void)
438 {
439         if (!s_info.svc_ctx)
440                 return LB_STATUS_ERROR_INVALID;
441
442         service_common_destroy(s_info.svc_ctx);
443         s_info.svc_ctx = NULL;
444         DbgPrint("Successfully finalized\n");
445         return LB_STATUS_SUCCESS;
446 }
447
448 /* End of a file */