2b1dc0b8afd3c105462ce07b115dd37bf241ab15
[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 #if defined(HAVE_LIVEBOX)
23 #include <livebox-errno.h>
24 #else
25 #include "lite-errno.h"
26 #endif
27 #include <packet.h>
28
29 #include <sys/smack.h>
30
31 #include <badge.h>
32 #include <badge_db.h>
33 #include <badge_setting_service.h>
34 #include <security-server.h>
35
36 #include "service_common.h"
37 #include "debug.h"
38 #include "util.h"
39 #include "conf.h"
40
41 static struct info {
42         Eina_List *context_list;
43         struct service_context *svc_ctx;
44 } s_info = {
45         .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
46         .svc_ctx = NULL, /*!< \WARN: This is only used for MAIN THREAD */
47 };
48
49 #define ENABLE_BS_ACCESS_CONTROL 1
50
51 struct context {
52         struct tcb *tcb;
53         double seq;
54 };
55
56 struct badge_service {
57         const char *cmd;
58         void (*handler)(struct tcb *tcb, struct packet *packet, void *data);
59         const char *rule;
60         const char *access;
61 };
62
63 /*!
64  * FUNCTIONS to check smack permission
65  */
66 static int _is_valid_permission(int fd, struct badge_service *service)
67 {
68         int ret;
69
70         if (service->rule != NULL && service->access != NULL) {
71                 ret = security_server_check_privilege_by_sockfd(fd, service->rule, service->access);
72                 if (ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) {
73                         ErrPrint("SMACK:Access denied\n");
74                         return 0;
75                 }
76         }
77
78         return 1;
79 }
80
81 static int _is_manager_permission(int fd)
82 {
83         int ret;
84
85         ret = security_server_check_privilege_by_sockfd(fd,
86                         "data-provider-master::badge.manager", "w");
87         if (ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) {
88                 ErrPrint("SMACK:not a manager\n");
89                 return 0;
90         }
91
92         return 1;
93 }
94
95 /*!
96  * FUNCTIONS to handle badge
97  */
98 static inline char *get_string(char *string)
99 {
100         if (string == NULL) {
101                 return NULL;
102         }
103         if (string[0] == '\0') {
104                 return NULL;
105         }
106
107         return string;
108 }
109
110 /*!
111  * SERVICE HANDLER
112  */
113 static void _handler_insert_badge(struct tcb *tcb, struct packet *packet, void *data)
114 {
115         int ret = 0, ret_p = 0;
116         struct packet *packet_reply = NULL;
117         struct packet *packet_service = NULL;
118         char *pkgname = NULL;
119         char *writable_pkg = NULL;
120         char *caller = NULL;
121
122         if (packet_get(packet, "sss", &pkgname, &writable_pkg, &caller) == 3) {
123                 pkgname = get_string(pkgname);
124                 writable_pkg = get_string(writable_pkg);
125                 caller = get_string(caller);
126
127                 if (pkgname != NULL && writable_pkg != NULL && caller != NULL) {
128                         ret = badge_db_insert(pkgname, writable_pkg, caller);
129                 } else {
130                         ret = BADGE_ERROR_INVALID_DATA;
131                 }
132
133                 packet_reply = packet_create_reply(packet, "i", ret);
134                 if (packet_reply) {
135                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
136                                 ErrPrint("Failed to send a reply packet:%d", ret_p);
137                         }
138                         packet_destroy(packet_reply);
139                 } else {
140                         ErrPrint("Failed to create a reply packet");
141                 }
142
143                 if (ret == BADGE_ERROR_NONE) {
144                         packet_service = packet_create("insert_badge", "is", ret, pkgname);
145                         if (packet_service != NULL) {
146                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
147                                         ErrPrint("Failed to send a muticast packet:%d", ret_p);
148                                 }
149                                 packet_destroy(packet_service);
150                         } else {
151                                 ErrPrint("Failed to create a multicast packet");
152                         }
153                 } else {
154                         ErrPrint("Failed to insert a badge:%d", ret);
155                 }
156         } else {
157                 ErrPrint("Failed to get data from the packet");
158         }
159 }
160
161 static void _handler_delete_badge(struct tcb *tcb, struct packet *packet, void *data)
162 {
163         int ret = 0, ret_p = 0;
164         struct packet *packet_reply = NULL;
165         struct packet *packet_service = NULL;
166         char *pkgname = NULL;
167         char *caller = NULL;
168
169         if (packet_get(packet, "ss", &pkgname, &caller) == 2) {
170                 pkgname = get_string(pkgname);
171                 caller = get_string(caller);
172
173                 if (pkgname != NULL && caller != NULL) {
174                         if (_is_manager_permission(tcb_fd(tcb)) == 1) {
175                                 ret = badge_db_delete(pkgname, pkgname);
176                         } else {
177                                 ret = badge_db_delete(pkgname, caller);
178                         }
179                 } else {
180                         ret = BADGE_ERROR_INVALID_DATA;
181                 }
182
183                 packet_reply = packet_create_reply(packet, "i", ret);
184                 if (packet_reply) {
185                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
186                                 ErrPrint("Failed to send a reply packet:%d", ret_p);
187                         }
188                         packet_destroy(packet_reply);
189                 } else {
190                         ErrPrint("Failed to create a reply packet");
191                 }
192
193                 if (ret == BADGE_ERROR_NONE) {
194                         packet_service = packet_create("delete_badge", "is", ret, pkgname);
195                         if (packet_service != NULL) {
196                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
197                                         ErrPrint("Failed to send a muticast packet:%d", ret_p);
198                                 }
199                                 packet_destroy(packet_service);
200                         } else {
201                                 ErrPrint("Failed to create a multicast packet");
202                         }
203                 } else {
204                         ErrPrint("Failed to delete a badge:%d", ret);
205                 }
206         } else {
207                 ErrPrint("Failed to get data from the packet");
208         }
209 }
210
211 static void _handler_set_badge_count(struct tcb *tcb, struct packet *packet, void *data)
212 {
213         int ret = 0, ret_p = 0;
214         struct packet *packet_reply = NULL;
215         struct packet *packet_service = NULL;
216         char *pkgname = NULL;
217         char *caller = NULL;
218         int count = 0;
219
220         if (packet_get(packet, "ssi", &pkgname, &caller, &count) == 3) {
221                 pkgname = get_string(pkgname);
222                 caller = get_string(caller);
223
224                 if (pkgname != NULL && caller != NULL) {
225                         ret = badge_db_set_count(pkgname, caller, count);
226                 } else {
227                         ret = BADGE_ERROR_INVALID_DATA;
228                 }
229
230                 packet_reply = packet_create_reply(packet, "i", ret);
231                 if (packet_reply) {
232                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
233                                 ErrPrint("Failed to send a reply packet:%d", ret_p);
234                         }
235                         packet_destroy(packet_reply);
236                 } else {
237                         ErrPrint("Failed to create a reply packet");
238                 }
239
240                 if (ret == BADGE_ERROR_NONE) {
241                         packet_service = packet_create("set_badge_count", "isi", ret, pkgname, count);
242                         if (packet_service != NULL) {
243                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
244                                         ErrPrint("Failed to send a muticast packet:%d", ret_p);
245                                 }
246                                 packet_destroy(packet_service);
247                         } else {
248                                 ErrPrint("Failed to create a multicast packet");
249                         }
250                 } else {
251                         ErrPrint("Failed to set count of badge:%d", ret);
252                 }
253         } else {
254                 ErrPrint("Failed to get data from the packet");
255         }
256 }
257
258 static void _handler_set_display_option(struct tcb *tcb, struct packet *packet, void *data)
259 {
260         int ret = 0, ret_p = 0;
261         struct packet *packet_reply = NULL;
262         struct packet *packet_service = NULL;
263         char *pkgname = NULL;
264         char *caller = NULL;
265         int is_display = 0;
266
267         if (packet_get(packet, "ssi", &pkgname, &caller, &is_display) == 3) {
268                 pkgname = get_string(pkgname);
269                 caller = get_string(caller);
270
271                 if (pkgname != NULL && caller != NULL) {
272                         ret = badge_db_set_display_option(pkgname, caller, is_display);
273                 } else {
274                         ret = BADGE_ERROR_INVALID_DATA;
275                 }
276
277                 packet_reply = packet_create_reply(packet, "i", ret);
278                 if (packet_reply) {
279                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
280                                 ErrPrint("Failed to send a reply packet:%d", ret_p);
281                         }
282                         packet_destroy(packet_reply);
283                 } else {
284                         ErrPrint("Failed to create a reply packet");
285                 }
286
287                 if (ret == BADGE_ERROR_NONE) {
288                         packet_service = packet_create("set_disp_option", "isi", ret, pkgname, is_display);
289                         if (packet_service != NULL) {
290                                 if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
291                                         ErrPrint("Failed to send a muticast packet:%d", ret_p);
292                                 }
293                                 packet_destroy(packet_service);
294                         } else {
295                                 ErrPrint("Failed to create a multicast packet");
296                         }
297                 } else {
298                         ErrPrint("Failed to set display option of badge:%d", ret);
299                 }
300         } else {
301                 ErrPrint("Failed to get data from the packet");
302         }
303 }
304
305 static void _handler_set_setting_property(struct tcb *tcb, struct packet *packet, void *data)
306 {
307         int ret = 0, ret_p = 0;
308         int is_display = 0;
309         struct packet *packet_reply = NULL;
310         struct packet *packet_service = NULL;
311         char *pkgname = NULL;
312         char *property = NULL;
313         char *value = NULL;
314
315         if (packet_get(packet, "sss", &pkgname, &property, &value) == 3) {
316                 pkgname = get_string(pkgname);
317                 property = get_string(property);
318                 value = get_string(value);
319
320                 if (pkgname != NULL && property != NULL && value != NULL) {
321                         ret = badge_setting_db_set(pkgname, property, value);
322                 } else {
323                         ret = BADGE_ERROR_INVALID_DATA;
324                 }
325
326                 packet_reply = packet_create_reply(packet, "ii", ret, ret);
327                 if (packet_reply) {
328                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
329                                 ErrPrint("failed to send reply packet:%d\n", ret_p);
330                         }
331                         packet_destroy(packet_reply);
332                 } else {
333                         ErrPrint("failed to create a reply packet\n");
334                 }
335
336                 if (ret == BADGE_ERROR_NONE) {
337                         if (strcmp(property, "OPT_BADGE") == 0) {
338                                 if (strcmp(value, "ON") == 0) {
339                                         is_display = 1;
340                                 } else {
341                                         is_display = 0;
342                                 }
343
344                                 packet_service = packet_create("set_disp_option", "isi", ret, pkgname, is_display);
345                                 if (packet_service != NULL) {
346                                         if ((ret_p = service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE)) < 0) {
347                                                 ErrPrint("Failed to send a muticast packet:%d", ret_p);
348                                         }
349                                         packet_destroy(packet_service);
350                                 } else {
351                                         ErrPrint("Failed to create a multicast packet");
352                                 }
353                         }
354                 } else {
355                         ErrPrint("failed to set noti property:%d\n", ret);
356                 }
357         } else {
358                 ErrPrint("Failed to get data from the packet");
359         }
360 }
361
362 static void _handler_get_setting_property(struct tcb *tcb, struct packet *packet, void *data)
363 {
364         int ret = 0, ret_p = 0;
365         struct packet *packet_reply = NULL;
366         char *pkgname = NULL;
367         char *property = NULL;
368         char *value = NULL;
369
370         if (packet_get(packet, "sss", &pkgname, &property) == 2) {
371                 pkgname = get_string(pkgname);
372                 property = get_string(property);
373
374                 if (pkgname != NULL && property != NULL) {
375                         ret = badge_setting_db_get(pkgname, property, &value);
376                 } else {
377                         ret = BADGE_ERROR_INVALID_DATA;
378                 }
379
380                 packet_reply = packet_create_reply(packet, "is", ret, value);
381                 if (packet_reply) {
382                         if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
383                                 ErrPrint("failed to send reply packet:%d\n", ret_p);
384                         }
385                         packet_destroy(packet_reply);
386                 } else {
387                         ErrPrint("failed to create a reply packet\n");
388                 }
389
390                 if (value != NULL) {
391                         DbgFree(value);
392                 }
393         }
394 }
395
396 static void _handler_service_register(struct tcb *tcb, struct packet *packet, void *data)
397 {
398         int ret = 0;
399         struct packet *packet_reply;
400
401         ret = tcb_client_type_set(tcb, TCB_CLIENT_TYPE_SERVICE);
402         if (ret < 0) {
403                 ErrPrint("Failed to set the type of client:%d", ret);
404         }
405
406         packet_reply = packet_create_reply(packet, "i", ret);
407         if (packet_reply) {
408                 if ((ret = service_common_unicast_packet(tcb, packet_reply)) < 0) {
409                         ErrPrint("Failed to send a reply packet:%d", ret);
410                 }
411                 packet_destroy(packet_reply);
412         } else {
413                 ErrPrint("Failed to create a reply packet");
414         }
415 }
416
417 static void _handler_access_control_error(struct tcb *tcb, struct packet *packet)
418 {
419         int ret_p = 0;
420         struct packet *packet_reply = NULL;
421
422         packet_reply = packet_create_reply(packet, "i", BADGE_ERROR_PERMISSION_DENIED);
423         if (packet_reply) {
424                 if ((ret_p = service_common_unicast_packet(tcb, packet_reply)) < 0) {
425                         ErrPrint("Failed to send a reply packet:%d", ret_p);
426                 }
427                 packet_destroy(packet_reply);
428         } else {
429                 ErrPrint("Failed to create a reply packet");
430         }
431 }
432
433 /*!
434  * SERVICE THREAD
435  */
436 static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
437 {
438         int i = 0;
439         const char *command;
440         static struct badge_service service_req_table[] = {
441                 {
442                         .cmd = "insert_badge",
443                         .handler = _handler_insert_badge,
444                         .rule = "data-provider-master::badge.client",
445                         .access = "w",
446                 },
447                 {
448                         .cmd = "delete_badge",
449                         .handler = _handler_delete_badge,
450                         .rule = "data-provider-master::badge.client",
451                         .access = "w",
452                 },
453                 {
454                         .cmd = "set_badge_count",
455                         .handler = _handler_set_badge_count,
456                         .rule = "data-provider-master::badge.client",
457                         .access = "w",
458                 },
459                 {
460                         .cmd = "set_disp_option",
461                         .handler = _handler_set_display_option,
462                         .rule = "data-provider-master::badge.client",
463                         .access = "w",
464                 },
465                 {
466                         .cmd = "set_noti_property",
467                         .handler = _handler_set_setting_property,
468                         .rule = "data-provider-master::badge.client",
469                         .access = "w",
470                 },
471                 {
472                         .cmd = "get_noti_property",
473                         .handler = _handler_get_setting_property,
474                         .rule = "data-provider-master::badge.client",
475                         .access = "r",
476                 },
477                 {
478                         .cmd = "service_register",
479                         .handler = _handler_service_register,
480                         .rule = NULL,
481                         .access = NULL,
482                 },
483                 {
484                         .cmd = NULL,
485                         .handler = NULL,
486                         .rule = NULL,
487                         .access = NULL,
488                 },
489         };
490
491         if (!packet) {
492                 DbgPrint("TCB: %p is terminated (NIL packet)\n", tcb);
493                 return 0;
494         }
495
496         command = packet_command(packet);
497         if (!command) {
498                 ErrPrint("Invalid command\n");
499                 return -EINVAL;
500         }
501         DbgPrint("Command: [%s], Packet type[%d]\n", command, packet_type(packet));
502
503         switch (packet_type(packet)) {
504         case PACKET_REQ:
505                 /* Need to send reply packet */
506                 for (i = 0; service_req_table[i].cmd; i++) {
507                         if (strcmp(service_req_table[i].cmd, command)) {
508                                 continue;
509                         }
510
511 #if ENABLE_BS_ACCESS_CONTROL
512                         if (_is_valid_permission(tcb_fd(tcb), &(service_req_table[i])) == 1) {
513                                 service_req_table[i].handler(tcb, packet, data);
514                         } else {
515                                 _handler_access_control_error(tcb, packet);
516                         }
517 #else
518                         _is_valid_permission(tcb_fd(tcb), &(service_req_table[i]));
519                         service_req_table[i].handler(tcb, packet, data);
520 #endif
521                         break;
522                 }
523
524                 break;
525         case PACKET_REQ_NOACK:
526                 break;
527         case PACKET_ACK:
528                 break;
529         default:
530                 ErrPrint("Packet type is not valid[%s]\n", command);
531                 return -EINVAL;
532         }
533
534         /*!
535          * return value has no meanning,
536          * it will be printed by dlogutil.
537          */
538         return 0;
539 }
540
541
542 /*!
543  * MAIN THREAD
544  * Do not try to do anyother operation in these functions
545  */
546 HAPI int badge_service_init(void)
547 {
548         if (s_info.svc_ctx) {
549                 ErrPrint("Already initialized\n");
550                 return LB_STATUS_ERROR_ALREADY;
551         }
552
553         s_info.svc_ctx = service_common_create(BADGE_SOCKET, service_thread_main, NULL);
554         if (!s_info.svc_ctx) {
555                 ErrPrint("Unable to activate service thread\n");
556                 return LB_STATUS_ERROR_FAULT;
557         }
558
559         if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), BADGE_SMACK_LABEL, SMACK_LABEL_IPOUT) != 0) {
560                 if (errno != EOPNOTSUPP) {
561                         ErrPrint("Unable to set SMACK label(%d)\n", errno);
562                         service_common_destroy(s_info.svc_ctx);
563                         s_info.svc_ctx = NULL;
564                         return LB_STATUS_ERROR_FAULT;
565                 }
566         }
567
568         if (smack_fsetlabel(service_common_fd(s_info.svc_ctx), BADGE_SMACK_LABEL, SMACK_LABEL_IPIN) != 0) {
569                 if (errno != EOPNOTSUPP) {
570                         ErrPrint("Unable to set SMACK label(%d)\n", errno);
571                         service_common_destroy(s_info.svc_ctx);
572                         s_info.svc_ctx = NULL;
573                         return LB_STATUS_ERROR_FAULT;
574                 }
575         }
576
577         DbgPrint("Successfully initiated\n");
578         return LB_STATUS_SUCCESS;
579 }
580
581 HAPI int badge_service_fini(void)
582 {
583         if (!s_info.svc_ctx) {
584                 return LB_STATUS_ERROR_INVALID;
585         }
586
587         service_common_destroy(s_info.svc_ctx);
588         s_info.svc_ctx = NULL;
589         DbgPrint("Successfully finalized\n");
590         return LB_STATUS_SUCCESS;
591 }
592
593 /* End of a file */