31a6cd18d2ef6003094045c9fd92ba8a7920a35d
[src/app-framework-main.git] / src / wgtpkg-permissions.c
1 /*
2  Copyright 2015, 2016, 2017 IoT.bzh
3
4  author: José Bollo <jose.bollo@iot.bzh>
5
6  Licensed under the Apache License, Version 2.0 (the "License");
7  you may not use this file except in compliance with the License.
8  You may obtain a copy of the License at
9
10      http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 */
18
19 #define _GNU_SOURCE
20
21 #include <errno.h>
22 #include <string.h>
23 #include <stdlib.h>
24
25 #include "verbose.h"
26 #include "wgtpkg-permissions.h"
27
28 struct permission {
29         char *name;
30         unsigned granted: 1;
31         unsigned requested: 1;
32         unsigned level: 3;
33 };
34
35 static unsigned int nrpermissions = 0;
36 static struct permission *permissions = NULL;
37 static unsigned int indexiter = 0;
38
39 /* retrieves the permission of name */
40 static struct permission *get_permission(const char *name)
41 {
42         unsigned int i;
43
44         for (i = 0 ; i < nrpermissions ; i++)
45                 if (0 == strcmp(permissions[i].name, name))
46                         return permissions+i;
47         return NULL;
48 }
49
50 /* add a permission of name */
51 static struct permission *add_permission(const char *name)
52 {
53         struct permission *p = get_permission(name);
54         if (!p) {
55                 p = realloc(permissions,
56                         ((nrpermissions + 8) & ~(unsigned)7) * sizeof(*p));
57                 if (p) {
58                         permissions = p;
59                         p = permissions + nrpermissions;
60                         memset(p, 0, sizeof(*p));
61                         p->name = strdup(name);
62                         if (!p->name)
63                                 p = NULL;
64                         else
65                                 nrpermissions++;
66                 }
67         }
68         return p;
69 }
70
71 /* remove any granting */
72 void reset_permissions()
73 {
74         unsigned int i;
75         for (i = 0 ; i < nrpermissions ; i++)
76                 permissions[i].granted = permissions[i].requested = 0;
77 }
78
79 /* remove any requested permission */
80 void reset_requested_permissions()
81 {
82         unsigned int i;
83         for (i = 0 ; i < nrpermissions ; i++)
84                 permissions[i].requested = 0;
85 }
86
87 /* remove any granting */
88 void crop_permissions(unsigned level)
89 {
90         unsigned int i;
91         for (i = 0 ; i < nrpermissions ; i++)
92                 if (permissions[i].level < level)
93                         permissions[i].granted = 0;
94 }
95
96 /* add permissions granted for installation */
97 int grant_permission_list(const char *list)
98 {
99         struct permission *p;
100         char *iter, c;
101         unsigned int n;
102         static const char separators[] = " \t\n\r,";
103
104         iter = strdupa(list);
105         iter += strspn(iter, separators);
106         while(*iter) {
107                 n = (unsigned)strcspn(iter, separators);
108                 c = iter[n];
109                 iter[n] = 0;
110                 p = add_permission(iter);
111                 if (!p) {
112                         errno = ENOMEM;
113                         return -1;
114                 }
115                 p->granted = 1;
116                 iter += n;
117                 *iter =c;
118                 iter += strspn(iter, separators);
119         }
120         return 0;
121 }
122
123 /* checks if the permission 'name' is recorded */
124 int permission_exists(const char *name)
125 {
126         return !!get_permission(name);
127 }
128
129 /* request the permission, returns 1 if granted or 0 otherwise */
130 int request_permission(const char *name)
131 {
132 #define HACK_ALLOWING_REQUESTED_PERMISSIONS 1
133
134         struct permission *p = get_permission(name);
135
136 #if defined(HACK_ALLOWING_REQUESTED_PERMISSIONS) && HACK_ALLOWING_REQUESTED_PERMISSIONS
137         if (!p)
138                 p = add_permission(name);
139 #endif
140         if (p) {
141 #if defined(HACK_ALLOWING_REQUESTED_PERMISSIONS) && HACK_ALLOWING_REQUESTED_PERMISSIONS
142                 p->granted = 1;
143 #endif
144                 p->requested = 1;
145                 if (p->granted)
146                         return 1;
147         }
148         return 0;
149
150 #undef HACK_ALLOWING_REQUESTED_PERMISSIONS
151 }
152
153 /* iteration over granted and requested permissions */
154 const char *first_usable_permission()
155 {
156         indexiter = 0;
157         return next_usable_permission();
158 }
159
160 const char *next_usable_permission()
161 {
162         while(indexiter < nrpermissions) {
163                 struct permission *p = &permissions[indexiter++];
164                 if (p->granted && p->requested)
165                         return p->name;
166         }
167         return NULL;
168 }
169