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