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