add privilege enum type
[framework/appfw/slp-pkgmgr.git] / tool / pkg_smack.c
1 /*
2  * slp-pkgmgr
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7  * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23 #define _GNU_SOURCE
24
25 #include <unistd.h>
26 #include <stdio.h>
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdbool.h>
31 #include <dlfcn.h>
32 #include <sys/stat.h>
33
34 #include <pkgmgr-info.h>
35
36 static int __pkg_list_cb (const pkgmgrinfo_pkginfo_h handle, void *user_data);
37
38
39 #ifdef _E
40 #undef _E
41 #endif
42 #define _E(fmt, arg...) fprintf(stderr, "[PKG_SMACK][E][%s,%d] "fmt"\n", __FUNCTION__, __LINE__, ##arg);
43
44 #ifdef _D
45 #undef _D
46 #endif
47 #define _D(fmt, arg...) fprintf(stderr, "[PKG_SMACK][D][%s,%d] "fmt"\n", __FUNCTION__, __LINE__, ##arg);
48
49 #define LIB_PRIVILEGE_CONTROL           "libprivilege-control.so.0"
50 #define LIB_SMACK                                       "libsmack.so.1"
51
52 #define BUFF_SIZE                       256
53 #define APP_OWNER_ID            5000
54 #define APP_GROUP_ID            5000
55
56 enum rpm_path_type {
57         RPM_PATH_PRIVATE,
58         RPM_PATH_GROUP_RW,
59         RPM_PATH_PUBLIC_RO,
60         RPM_PATH_SETTINGS_RW,
61         RPM_PATH_NPRUNTIME,
62         RPM_PATH_ANY_LABEL
63 };
64
65 static int __is_dir(char *dirname)
66 {
67         struct stat stFileInfo;
68         stat(dirname, &stFileInfo);
69         if (S_ISDIR(stFileInfo.st_mode)) {
70                 return 1;
71         }
72         return 0;
73 }
74
75 int __pkg_smack_register_package(const char *pkgid)
76 {
77         int ret = 0;
78         void *handle = NULL;
79         char *errmsg = NULL;
80         int (*app_install)(const char*) = NULL;
81
82         if (pkgid == NULL)
83                 return -1;
84
85         handle = dlopen(LIB_PRIVILEGE_CONTROL, RTLD_LAZY | RTLD_GLOBAL);
86         if (!handle) {
87                 _E( "register package: dlopen() failed. [%s]", dlerror());
88                 return -1;
89         }
90
91         app_install = dlsym(handle, "app_install");
92         errmsg = dlerror();
93         if ((errmsg != NULL) || (app_install == NULL)) {
94                 _E( "register package: dlsym() failed. [%s]", errmsg);
95                 dlclose(handle);
96                 return -1;
97         }
98
99         _E( "[smack] app_install(%s)", pkgid);
100         ret = app_install(pkgid);
101         _E( "[smack] app_install(%s), result = [%d]", pkgid, ret);
102
103         dlclose(handle);
104         return ret;
105 }
106
107 int __pkg_smack_unregister_package(const char *pkgid)
108 {
109         int ret = 0;
110         void *handle = NULL;
111         char *errmsg = NULL;
112         int (*app_uninstall)(const char*) = NULL;
113
114         if (pkgid == NULL)
115                 return -1;
116
117         handle = dlopen(LIB_PRIVILEGE_CONTROL, RTLD_LAZY | RTLD_GLOBAL);
118         if (!handle) {
119                 _E( "unregister package: dlopen() failed. [%s]", dlerror());
120                 return -1;
121         }
122
123         app_uninstall = dlsym(handle, "app_uninstall");
124         errmsg = dlerror();
125         if ((errmsg != NULL) || (app_uninstall == NULL)) {
126                 _E( "unregister package: dlsym() failed. [%s]", errmsg);
127                 dlclose(handle);
128                 return -1;
129         }
130
131         _E( "[smack] app_uninstall(%s)", pkgid);
132         ret = app_uninstall(pkgid);
133         _E( "[smack] app_uninstall(%s), result = [%d]", pkgid, ret);
134
135         dlclose(handle);
136         return ret;
137 }
138
139 int __pkg_smack_revoke_permissions(const char *pkgid)
140 {
141         int ret = 0;
142         void *handle = NULL;
143         char *errmsg = NULL;
144         int (*app_revoke_permissions)(const char*) = NULL;
145
146         if (pkgid == NULL)
147                 return -1;
148
149         handle = dlopen(LIB_PRIVILEGE_CONTROL, RTLD_LAZY | RTLD_GLOBAL);
150         if (!handle) {
151                 _E( "revoke permissions: dlopen() failed. [%s][%s]", pkgid, dlerror());
152                 return -1;
153         }
154
155         app_revoke_permissions = dlsym(handle, "app_revoke_permissions");
156         errmsg = dlerror();
157         if ((errmsg != NULL) || (app_revoke_permissions == NULL)) {
158                 _E( "revoke permissions(): dlsym() failed. [%s][%s]", pkgid, errmsg);
159                 dlclose(handle);
160                 return -1;
161         }
162
163         _E( "[smack] app_revoke_permissions(%s)", pkgid);
164         ret = app_revoke_permissions(pkgid);
165         _E( "[smack] app_revoke_permissions(%s), result = [%d]", pkgid, ret);
166
167         dlclose(handle);
168         return ret;
169 }
170
171 int __pkg_smack_enable_permissions(const char *pkgid, int apptype,
172                                                 const char **perms, int persistent)
173 {
174         int ret = 0;
175         void *handle = NULL;
176         char *errmsg = NULL;
177         int (*app_enable_permissions)(const char*, int, const char**, bool) = NULL;
178
179         if (pkgid == NULL)
180                 return -1;
181
182         handle = dlopen(LIB_PRIVILEGE_CONTROL, RTLD_LAZY | RTLD_GLOBAL);
183         if (!handle) {
184                 _E( "enable permissions(): dlopen() failed. [%s]", dlerror());
185                 return -1;
186         }
187
188         app_enable_permissions = dlsym(handle, "app_enable_permissions");
189         errmsg = dlerror();
190         if ((errmsg != NULL) || (app_enable_permissions == NULL)) {
191                 _E( "enable permissions(): dlsym() failed. [%s]", errmsg);
192                 dlclose(handle);
193                 return -1;
194         }
195
196         _E( "[smack] app_enable_permissions(%s, %d)", pkgid, apptype);
197         ret = app_enable_permissions(pkgid, apptype, perms, persistent);
198         _E( "[smack] app_enable_permissions(%s, %d), result = [%d]", pkgid, apptype, ret);
199
200         dlclose(handle);
201         return ret;
202 }
203
204 int __pkg_smack_setup_path(const char *pkgid, const char *dirpath,
205                                                 int apppathtype, const char *groupid)
206 {
207         int ret = 0;
208         void *handle = NULL;
209         char *errmsg = NULL;
210         int (*app_setup_path)(const char*, const char*, int, ...) = NULL;
211
212         if (pkgid == NULL || dirpath == NULL)
213                 return -1;
214
215         handle = dlopen(LIB_PRIVILEGE_CONTROL, RTLD_LAZY | RTLD_GLOBAL);
216         if (!handle) {
217                 _E( "setup path: dlopen() failed. [%s]", dlerror());
218                 return -1;
219         }
220
221         app_setup_path = dlsym(handle, "app_setup_path");
222         errmsg = dlerror();
223         if ((errmsg != NULL) || (app_setup_path == NULL)) {
224                 _E( "setup path: dlsym() failed. [%s]", errmsg);
225                 dlclose(handle);
226                 return -1;
227         }
228
229         if (groupid == NULL) {
230                 _E( "[smack] app_setup_path(%s, %s, %d)", pkgid, dirpath, apppathtype);
231                 ret = app_setup_path(pkgid, dirpath, apppathtype);
232                 _E( "[smack] app_setup_path(), result = [%d]", ret);
233         } else {
234                 _E( "[smack] app_setup_path(%s, %s, %d, %s)", pkgid, dirpath, apppathtype, groupid);
235                 ret = app_setup_path(pkgid, dirpath, apppathtype, groupid);
236                 _E( "[smack] app_setup_path(), result = [%d]", ret);
237         }
238
239         dlclose(handle);
240         return ret;
241 }
242
243 int __pkg_smack_add_friend(const char *pkgid1, const char *pkgid2)
244 {
245         int ret = 0;
246         void *handle = NULL;
247         char *errmsg = NULL;
248         int (*app_add_friend)(const char*, const char*) = NULL;
249
250         if (pkgid1 == NULL || pkgid2 == NULL)
251                 return -1;
252
253         handle = dlopen(LIB_PRIVILEGE_CONTROL, RTLD_LAZY | RTLD_GLOBAL);
254         if (!handle) {
255                 _E( "add friend: dlopen() failed. [%s]", dlerror());
256                 return -1;
257         }
258
259         app_add_friend = dlsym(handle, "app_add_friend");
260         errmsg = dlerror();
261         if ((errmsg != NULL) || (app_add_friend == NULL)) {
262                 _E( "add friend: dlsym() failed. [%s]", errmsg);
263                 dlclose(handle);
264                 return -1;
265         }
266
267         _E( "[smack] app_add_friend(%s, %s)", pkgid1, pkgid2);
268         ret = app_add_friend(pkgid1, pkgid2);
269         _E( "[smack] app_add_friend(%s, %s), result = [%d]", pkgid1, pkgid2, ret);
270
271         dlclose(handle);
272         return ret;
273 }
274
275 int __pkg_smack_change_smack_label(const char *path, const char *label,
276                                                 int label_type)
277 {
278         if (path == NULL || label == NULL)
279                 return -1;
280         int ret = 0;
281         void *handle = NULL;
282         char *errmsg = NULL;
283         int (*smack_lsetlabel)(const char*, const char*, int) = NULL;
284
285         handle = dlopen(LIB_SMACK, RTLD_LAZY | RTLD_GLOBAL);
286         if (!handle) {
287                 _E( "change smack label: dlopen() failed. [%s]", dlerror());
288                 return -1;
289         }
290
291         smack_lsetlabel = dlsym(handle, "smack_lsetlabel");
292         errmsg = dlerror();
293         if ((errmsg != NULL) || (smack_lsetlabel == NULL)) {
294                 _E( "change smack label: dlsym() failed. [%s]", errmsg);
295                 dlclose(handle);
296                 return -1;
297         }
298
299         _E( "[smack] smack_lsetlabel(%s, %s, %d)", path, label, label_type);
300         ret = smack_lsetlabel(path, label, label_type);
301         _E( "[smack] smack_lsetlabel(%s, %s, %d), result = [%d]", path, label, label_type, ret);
302
303         dlclose(handle);
304         return ret;
305 }
306
307 static void __apply_shared_privileges(char *pkgname, int flag)
308 {
309         char dirpath[BUFF_SIZE] = {'\0'};
310         /*execute privilege APIs. The APIs should not fail*/
311         __pkg_smack_register_package(pkgname);
312
313 #if 1
314         /*home dir. Dont setup path but change smack access to "_" */
315         snprintf(dirpath, BUFF_SIZE, "/usr/apps/%s", pkgname);
316         if (__is_dir(dirpath))
317                 __pkg_smack_change_smack_label(dirpath, "_", 0);/*0 is SMACK_LABEL_ACCESS*/
318         memset(dirpath, '\0', BUFF_SIZE);
319         snprintf(dirpath, BUFF_SIZE, "/opt/usr/apps/%s", pkgname);
320         if (__is_dir(dirpath))
321                 __pkg_smack_change_smack_label(dirpath, "_", 0);/*0 is SMACK_LABEL_ACCESS*/
322         memset(dirpath, '\0', BUFF_SIZE);
323
324         /*/shared dir. Dont setup path but change smack access to "_" */
325         snprintf(dirpath, BUFF_SIZE, "/usr/apps/%s/shared", pkgname);
326         if (__is_dir(dirpath))
327                 __pkg_smack_change_smack_label(dirpath, "_", 0);/*0 is SMACK_LABEL_ACCESS*/
328         memset(dirpath, '\0', BUFF_SIZE);
329         snprintf(dirpath, BUFF_SIZE, "/opt/usr/apps/%s/shared", pkgname);
330         if (__is_dir(dirpath))
331                 __pkg_smack_change_smack_label(dirpath, "_", 0);/*0 is SMACK_LABEL_ACCESS*/
332         memset(dirpath, '\0', BUFF_SIZE);
333
334         /*/shared/res dir. Dont setup path but change smack access to "_" */
335         if (flag == 0)
336                 snprintf(dirpath, BUFF_SIZE, "/usr/apps/%s/shared/res", pkgname);
337         else
338                 snprintf(dirpath, BUFF_SIZE, "/opt/usr/apps/%s/shared/res", pkgname);
339         if (__is_dir(dirpath))
340                 __pkg_smack_setup_path(pkgname, dirpath, RPM_PATH_ANY_LABEL, "_");
341         memset(dirpath, '\0', BUFF_SIZE);
342
343         /*/shared/data dir. setup path and change group to 'app'*/
344         if (flag == 0)
345                 snprintf(dirpath, BUFF_SIZE, "/usr/apps/%s/shared/data", pkgname);
346         else
347                 snprintf(dirpath, BUFF_SIZE, "/opt/usr/apps/%s/shared/data", pkgname);
348         if (__is_dir(dirpath)) {
349                 chown(dirpath, APP_OWNER_ID, APP_GROUP_ID);
350                 __pkg_smack_setup_path(pkgname, dirpath, RPM_PATH_PUBLIC_RO, NULL);
351         } else {
352                 memset(dirpath, '\0', BUFF_SIZE);
353                 if (flag == 0)
354                         snprintf(dirpath, BUFF_SIZE, "/opt/usr/apps/%s/shared/data", pkgname);
355                 else
356                         snprintf(dirpath, BUFF_SIZE, "/usr/apps/%s/shared/data", pkgname);
357                 if (__is_dir(dirpath))
358                         chown(dirpath, APP_OWNER_ID, APP_GROUP_ID);
359                         __pkg_smack_setup_path(pkgname, dirpath, RPM_PATH_PUBLIC_RO, NULL);
360         }
361 #endif
362 }
363
364 static int __is_authorized()
365 {
366         /* pkg_init db should be called by as root privilege. */
367
368         uid_t uid = getuid();
369         if ((uid_t) 0 == uid)
370                 return 1;
371         else
372                 return 0;
373 }
374
375 static int __pkg_list_cb (const pkgmgrinfo_pkginfo_h handle, void *user_data)
376 {
377         int ret = -1;
378         char *pkgid = NULL;
379
380         ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
381         if(ret < 0) {
382                 printf("pkgmgrinfo_pkginfo_get_pkgid() failed\n");
383         }
384
385         __apply_shared_privileges(pkgid, 0);
386
387         return 0;
388 }
389
390 static int __additional_rpm_for_smack()
391 {
392         char *pkgid = "ui-gadget::client";
393         char *perm[] = {"http://tizen.org/privilege/appsetting", NULL};
394
395         __apply_shared_privileges(pkgid, 0);
396         __pkg_smack_enable_permissions(pkgid, 1, perm, 1);
397         return 0;
398 }
399
400 static int __find_rpm_for_smack()
401 {
402         int ret = 0;
403         pkgmgrinfo_pkginfo_filter_h handle = NULL;
404
405         ret = pkgmgrinfo_pkginfo_filter_create(&handle);
406         if (ret > 0) {
407                 printf("pkginfo filter handle create failed\n");
408                 return -1;
409         }
410
411         ret = pkgmgrinfo_pkginfo_filter_add_string(handle,
412                 PMINFO_PKGINFO_PROP_PACKAGE_TYPE, "rpm");
413         if (ret < 0) {
414                 printf("pkgmgrinfo_pkginfo_filter_add_string() failed\n");
415                 ret = -1;
416         }
417
418         ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(handle, __pkg_list_cb, NULL);
419         if (ret < 0) {
420                 printf("pkgmgrinfo_pkginfo_filter_foreach_pkginfo() failed\n");
421                 ret = -1;
422         }
423
424         pkgmgrinfo_pkginfo_filter_destroy(handle);
425         return ret;
426 }
427
428 int main(int argc, char *argv[])
429 {
430         int ret = 0;
431
432         if (!__is_authorized()) {
433                 _E("You are not an authorized user!\n");
434                 return -1;
435         }
436
437         ret = __find_rpm_for_smack();
438         if (ret < 0)
439                 printf("__find_rpm_for_smack() failed\n");
440
441         ret = __additional_rpm_for_smack();
442         if (ret < 0)
443                 printf("__additional_rpm_for_smack() failed\n");
444
445         return 0;
446 }
447
448