8a8a0aca01c0ab78f23fb2dd7f1cdad454663b14
[platform/core/uifw/libds-tizen.git] / src / libds-tizen / util / security.c
1 #include <stdio.h>
2 #include <stdarg.h>
3 #include <stdint.h>
4 #include <stdlib.h>
5 #include <stdbool.h>
6
7 #include <cynara-session.h>
8 #include <cynara-client.h>
9 #include <cynara-creds-socket.h>
10 #include <sys/smack.h>
11
12 #include <libds/log.h>
13 #include "util.h"
14
15 #define CYNARA_BUFSIZE 128
16
17 struct ds_cynara
18 {
19     cynara *handle;
20     int references;
21 };
22
23 static struct ds_cynara ds_cynara;
24
25 static bool ds_cynara_init(void);
26 static void ds_cynara_finish(void);
27 static bool ds_cynara_check_privilege(pid_t pid, uid_t uid,
28         const char *privilege);
29
30 bool
31 tizen_security_check_privilege(pid_t pid, uid_t uid, const char *privilege)
32 {
33     return ds_cynara_check_privilege(pid, uid, privilege);
34 }
35
36 bool
37 tizen_security_init(void)
38 {
39     return ds_cynara_init();
40 }
41
42 void
43 tizen_security_finish(void)
44 {
45     ds_cynara_finish();
46 }
47
48 static void
49 print_cynara_error(int err, const char *fmt, ...)
50 {
51     int ret;
52     va_list args;
53     char buf[CYNARA_BUFSIZE] = "\0";
54     char tmp[CYNARA_BUFSIZE + CYNARA_BUFSIZE] = "\0";
55
56     if (fmt) {
57         va_start(args, fmt);
58         vsnprintf(tmp, CYNARA_BUFSIZE + CYNARA_BUFSIZE, fmt, args);
59         va_end(args);
60     }
61
62     ret = cynara_strerror(err, buf, CYNARA_BUFSIZE);
63     if (ret != CYNARA_API_SUCCESS) {
64         ds_err("Failed to get cynara_strerror. error : %d (error log about %s: %d)\n", ret, tmp, err);
65         return;
66     }
67
68     ds_err("%s is failed. (%s)\n", tmp, buf);
69 }
70
71 static bool
72 ds_cynara_init(void)
73 {
74     int ret = CYNARA_API_SUCCESS;
75     int retry_cnt = 0;
76
77     if (++ds_cynara.references != 1)
78         return true;
79
80     for (retry_cnt = 0; retry_cnt < 5; retry_cnt++) {
81         ds_dbg("Retry cynara initialize: %d\n", retry_cnt + 1);
82
83         ret = cynara_initialize(&ds_cynara.handle, NULL);
84
85         if (CYNARA_API_SUCCESS == ret) {
86             ds_dbg("Succeed to initialize cynara !\n");
87             return true;
88         }
89
90         print_cynara_error(ret, "cynara_initialize");
91     }
92
93     ds_err("Failed to initialize cynara! (error:%d, retry_cnt=%d)\n",
94         ret, retry_cnt);
95
96     --ds_cynara.references;
97
98     return false;
99
100 }
101
102 static void
103 ds_cynara_finish(void)
104 {
105     if (ds_cynara.references < 1) {
106         ds_err("%s called without ds_cynara_init\n", __FUNCTION__);
107         return;
108     }
109
110     if (--ds_cynara.references != 0)
111         return;
112
113     cynara_finish(ds_cynara.handle);
114     ds_cynara.handle = NULL;
115 }
116
117 static bool
118 ds_cynara_check_privilege(pid_t pid, uid_t uid, const char *privilege)
119 {
120     bool res = false;
121     char *client_smack = NULL;
122     char *client_session = NULL;
123     char uid_str[16] = { 0, };
124     int len = -1;
125     int ret = -1;
126
127     if (!ds_cynara.handle) {
128         ds_err("ds_cynara has not been initialized.\n");
129         return false;
130     }
131
132     ret = smack_new_label_from_process((int)pid, &client_smack);
133     if (ret <= 0)
134         goto finish;
135
136     snprintf(uid_str, 15, "%d", (int)uid);
137
138     client_session = cynara_session_from_pid(pid);
139     if (!client_session)
140         goto finish;
141
142     ret = cynara_check(ds_cynara.handle, client_smack, client_session,
143             uid_str, privilege);
144
145     if (ret == CYNARA_API_ACCESS_ALLOWED)
146         res = true;
147     else
148         print_cynara_error(ret, "privilege: %s, client_smack: %s, pid: %d",
149                 privilege, client_smack, pid);
150
151 finish:
152     ds_dbg("Privilege Check For '%s' %s pid:%u uid:%u client_smack:%s(len:%d) "
153             "client_session:%s ret:%d",
154             privilege, res ? "SUCCESS" : "FAIL", pid, uid,
155             client_smack ? client_smack : "N/A", len,
156             client_session ? client_session: "N/A", ret);
157
158     if (client_session)
159         free(client_session);
160
161     if (client_smack)
162         free(client_smack);
163
164     return res;
165 }