in progress
[src/app-framework-main.git] / src / wgtpkg-install.c
1 /*
2  Copyright 2015 IoT.bzh
3
4  Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
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 #define _GNU_SOURCE
18
19 #include <errno.h>
20 #include <syslog.h>
21 #include <string.h>
22 #include <ctype.h>
23 #include <assert.h>
24 #include <unistd.h>
25
26 #include "verbose.h"
27 #include "wgtpkg.h"
28 #include "wgt.h"
29 #include "wgt-info.h"
30 #include "secmgr-wrap.h"
31 #include "utils-dir.h"
32
33 static int check_defined(const void *data, const char *name)
34 {
35         if (data)
36                 return 0;
37         ERROR("widget has no defined '%s' (temporary constraints)", name);
38         errno = EINVAL;
39         return -1;
40 }
41
42 static int check_valid_string(const char *value, const char *name)
43 {
44         int pos;
45         char c;
46
47         if (check_defined(value, name))
48                 return -1;
49         pos = 0;
50         c = value[pos];
51         while(c) {
52                 if (!isalnum(c) && !strchr(".-_", c)) {
53                         ERROR("forbidden char %c in '%s' -> '%s' (temporary constraints)", c, name, value);
54                         errno = EINVAL;
55                         return -1;                      
56                 }
57                 c = value[++pos];
58         }
59         return 0;
60 }
61
62 static int check_temporary_constraints(const struct wgt_desc *desc)
63 {
64         int result = check_valid_string(desc->id, "id");
65         result |= check_valid_string(desc->version, "version");
66         result |= check_defined(desc->icons, "icon");
67         result |= check_defined(desc->content_src, "content");
68         if (result)
69                 return result;
70         if (desc->icons->next) {
71                 ERROR("widget has more than one icon defined (temporary constraints)");
72                 errno = EINVAL;
73                 result = -1;
74         }
75         return 0;
76 }
77
78 static int check_permissions(const char *name, int required)
79 {
80         if (permission_exists(name)) {
81                 if (request_permission(name)) {
82                         DEBUG("granted permission: %s", name);
83                 } else if (required) {
84                         ERROR("ungranted permission required: %s", name);
85                         errno = EPERM;
86                         return 0;
87                 } else {
88                         INFO("ungranted permission optional: %s", name);
89                 }
90         }
91         return 1;
92 }
93
94 static int check_widget(const struct wgt_desc *desc)
95 {
96         int result;
97         const struct wgt_desc_feature *feature;
98
99         result = check_temporary_constraints(desc);
100         feature = desc->features;
101         while(feature) {
102                 if (!check_permissions(feature->name, feature->required))
103                         result = -1;
104                 feature = feature->next;
105         }
106         return result;
107 }
108
109 static int move_widget(const char *root, const struct wgt_desc *desc, int force)
110 {
111         char newdir[PATH_MAX];
112         int rc;
113
114         rc = snprintf(newdir, sizeof newdir, "%s/%s/%s", root, desc->id, desc->version);
115         if (rc >= sizeof newdir) {
116                 ERROR("path to long in move_widget");
117                 errno = EINVAL;
118                 return -1;
119         }
120
121         return move_workdir(newdir, 1, force);
122 }
123
124 static int install_icon(const struct wgt_desc *desc)
125 {
126         char link[PATH_MAX];
127         char target[PATH_MAX];
128         int rc;
129
130         create_directory(FWK_ICON_DIR, 0755, 1);
131         rc = snprintf(link, sizeof link, "%s/%s@%s", FWK_ICON_DIR, desc->id, desc->version);
132         if (rc >= sizeof link) {
133                 ERROR("link to long in install_icon");
134                 errno = EINVAL;
135                 return -1;
136         }
137
138         rc = snprintf(target, sizeof target, "%s/%s", workdir, desc->icons->src);
139         if (rc >= sizeof target) {
140                 ERROR("target to long in install_icon");
141                 errno = EINVAL;
142                 return -1;
143         }
144
145         unlink(link);
146         rc = symlink(target, link);
147         if (rc)
148                 ERROR("can't create link %s -> %s", link, target);
149         return rc;
150 }
151
152 static int install_security(const struct wgt_desc *desc)
153 {
154         char path[PATH_MAX], *head;
155         const char *icon, *perm;
156         int rc, len, lic, lf;
157         unsigned int i, n;
158         struct filedesc *f;
159
160         rc = secmgr_init(desc->id);
161         if (rc)
162                 goto error;
163
164         rc = secmgr_path_public_read_only(workdir);
165         if (rc)
166                 goto error2;
167
168         /* instal the files */
169         head = stpcpy(path, workdir);
170         assert(sizeof path > (head - path));
171         len = (int)(sizeof path - (head - path));
172         if (!len) {
173                 ERROR("root path too long in install_security");
174                 errno = ENAMETOOLONG;
175                 goto error2;
176         }
177         len--;
178         *head++ = '/';
179         icon = desc->icons->src;
180         lic = (int)strlen(icon);
181         n = file_count();
182         i = 0;
183         while(i < n) {
184                 f = file_of_index(i++);
185                 lf = (int)strlen(f->name);
186                 if (lf >= len) {
187                         ERROR("path too long in install_security");
188                         errno = ENAMETOOLONG;
189                         goto error2;
190                 }
191                 strcpy(head, f->name);
192                 if (lf <= lic && !memcmp(f->name, icon, lf) && (!f->name[lf] || f->name[lf] == '/'))
193                         rc = secmgr_path_public_read_only(path);
194                 else
195                         rc = secmgr_path_read_only(path);
196                 if (rc)
197                         goto error2;
198         }
199
200         /* install the permissions */
201         perm = first_usable_permission();
202         while(perm) {
203                 rc = secmgr_permit(perm);
204                 if (rc)
205                         goto error2;
206                 perm = next_usable_permission();
207         }
208
209         rc = secmgr_install();
210         return rc;
211 error2:
212         secmgr_cancel();
213 error:
214         return -1;
215 }
216
217 /* install the widget of the file */
218 void install_widget(const char *wgtfile, const char *root, int force)
219 {
220         struct wgt_info *ifo;
221         const struct wgt_desc *desc;
222
223         NOTICE("-- INSTALLING widget %s --", wgtfile);
224
225         /* workdir */
226         create_directory(root, 0755, 1);
227         if (make_workdir_base(root, "TMP", 0)) {
228                 ERROR("failed to create a working directory");
229                 goto error1;
230         }
231
232         if (zread(wgtfile, 0))
233                 goto error2;
234
235         if (check_all_signatures())
236                 goto error2;
237
238         ifo = wgt_info_createat(workdirfd, NULL, 1, 1, 1);
239         if (!ifo)
240                 goto error2;
241
242         desc = wgt_info_desc(ifo);
243         if (check_widget(desc))
244                 goto error3;
245
246         if (move_widget(root, desc, force))
247                 goto error3;
248
249         if (install_icon(desc))
250                 goto error3;
251
252         if (install_security(desc))
253                 goto error3;
254         
255         return;
256
257 error3:
258         wgt_info_unref(ifo);
259
260 error2:
261         remove_workdir();
262
263 error1:
264         return;
265 }
266