2 Copyright 2015, 2016, 2017 IoT.bzh
4 author: José Bollo <jose.bollo@iot.bzh>
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
10 http://www.apache.org/licenses/LICENSE-2.0
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.
35 #include "wgt-strings.h"
36 #include "wgtpkg-files.h"
37 #include "wgtpkg-workdir.h"
38 #include "wgtpkg-zip.h"
39 #include "wgtpkg-permissions.h"
40 #include "wgtpkg-digsig.h"
41 #include "wgtpkg-install.h"
42 #include "secmgr-wrap.h"
43 #include "utils-dir.h"
44 #include "wgtpkg-unit.h"
45 #include "utils-systemd.h"
46 #include "utils-file.h"
48 static const char* exec_type_strings[] = {
49 "application/x-executable",
50 "application/vnd.agl.native"
53 static const char key_http_port[] = "X-AFM--http-port";
55 static int get_port_cb(void *closure, const char *name, const char *path, int isuser)
63 rc = getfile(path, &content, &length);
67 /* process the file */
68 iter = strstr(content, key_http_port);
70 iter += sizeof key_http_port - 1;
71 while(*iter && *iter != '=' && *iter != '\n')
74 while(*++iter == ' ');
76 if (p >= 0 && p < 32768)
77 ((uint32_t*)closure)[p >> 5] |= (uint32_t)1 << (p & 31);
79 iter = strstr(iter, key_http_port);
88 uint32_t ports[1024]; /* 1024 * 32 = 32768 */
90 memset(ports, 0, sizeof ports);
91 rc = systemd_unit_list(0, get_port_cb, &ports);
93 rc = systemd_unit_list(1, get_port_cb, ports);
95 for (rc = 1024 ; rc < 32768 && !~ports[rc >> 5] ; rc += 32);
97 errno = EADDRNOTAVAIL;
100 while (1 & (ports[rc >> 5] >> (rc & 31))) rc++;
107 static int check_defined(const void *data, const char *name)
111 ERROR("widget has no defined '%s' (temporary constraints)", name);
116 static int check_valid_string(const char *value, const char *name)
121 if (check_defined(value, name))
126 ERROR("empty string forbidden in '%s' (temporary constraints)", name);
131 if (!isalnum(c) && !strchr(".-_", c)) {
132 ERROR("forbidden char %c in '%s' -> '%s' (temporary constraints)", c, name, value);
141 static int check_temporary_constraints(const struct wgt_desc *desc)
145 result = check_valid_string(desc->id, "id");
146 result |= check_valid_string(desc->version, "version");
147 result |= check_valid_string(desc->ver, "ver");
148 result |= check_defined(desc->icons, "icon");
149 result |= check_defined(desc->content_src, "content");
153 if (desc->icons->next) {
154 ERROR("widget has more than one icon defined (temporary constraints)");
161 static int set_required_permissions(struct wgt_desc_param *params, int required)
166 /* check if target */
167 if (!strcmp(params->name, string_sharp_target)) {
168 /* do nothing when #target */
170 /* check the value */
171 if (!strcmp(params->value, string_required))
172 optional = !required;
173 else if (!strcmp(params->value, string_optional))
176 ERROR("unexpected parameter value: %s found for %s", params->value, params->name);
180 /* set the permission */
181 if (request_permission(params->name)) {
182 DEBUG("granted permission: %s", params->name);
183 } else if (optional) {
184 INFO("optional permission ungranted: %s", params->name);
186 ERROR("ungranted permission required: %s", params->name);
191 params = params->next;
196 static int check_permissions(const struct wgt_desc *desc)
199 const struct wgt_desc_feature *feature;
202 feature = desc->features;
203 while(result >= 0 && feature) {
204 if (!strcmp(feature->name, feature_required_permission))
205 result = set_required_permissions(feature->params, feature->required);
206 feature = feature->next;
211 static int check_widget(const struct wgt_desc *desc)
215 result = check_temporary_constraints(desc);
217 result = check_permissions(desc);
221 static int get_target_directory(char target[PATH_MAX], const char *root, const struct wgt_desc *desc)
225 rc = snprintf(target, PATH_MAX, "%s/%s/%s", root, desc->id, desc->ver);
229 ERROR("path too long");
236 static int move_widget_to(const char *destdir, int force)
238 return move_workdir(destdir, 1, force);
241 static int install_icon(const struct wgt_desc *desc)
244 char target[PATH_MAX];
247 create_directory(FWK_ICON_DIR, 0755, 1);
248 rc = snprintf(link, sizeof link, "%s/%s", FWK_ICON_DIR, desc->idaver);
249 if (rc >= (int)sizeof link) {
250 ERROR("link too long in install_icon");
255 rc = snprintf(target, sizeof target, "%s/%s", workdir, desc->icons->src);
256 if (rc >= (int)sizeof target) {
257 ERROR("target too long in install_icon");
263 rc = symlink(target, link);
265 ERROR("can't create link %s -> %s", link, target);
269 static int install_exec_flag(const struct wgt_desc *desc)
273 if (desc->content_type) {
274 i = sizeof exec_type_strings / sizeof *exec_type_strings;
276 if (!strcasecmp(desc->content_type, exec_type_strings[--i])) {
277 rc = fchmodat(workdirfd, desc->content_src, 0755, 0);
279 ERROR("can't make executable the file %s", desc->content_src);
287 static int install_security(const struct wgt_desc *desc)
289 char path[PATH_MAX], *head;
290 const char *icon, *perm;
292 unsigned int i, n, len, lic, lf;
295 rc = secmgr_init(desc->id);
299 rc = secmgr_path_public_read_only(workdir);
303 /* instal the files */
304 head = stpcpy(path, workdir);
305 assert(head < path + sizeof path);
306 len = (unsigned)((path + sizeof path) - head);
308 ERROR("root path too long in install_security");
309 errno = ENAMETOOLONG;
314 icon = desc->icons->src;
315 lic = (unsigned)strlen(icon);
319 f = file_of_index(i++);
320 lf = (unsigned)strlen(f->name);
322 ERROR("path too long in install_security");
323 errno = ENAMETOOLONG;
326 strcpy(head, f->name);
327 if (lf <= lic && !memcmp(f->name, icon, lf) && (!f->name[lf] || f->name[lf] == '/'))
328 rc = secmgr_path_public_read_only(path);
330 rc = secmgr_path_read_only(path);
335 /* install the permissions */
336 perm = first_usable_permission();
338 rc = secmgr_permit(perm);
339 INFO("permitting %s %s", perm, rc ? "FAILED!" : "success");
342 perm = next_usable_permission();
345 rc = secmgr_install();
353 /* install the widget of the file */
354 struct wgt_info *install_widget(const char *wgtfile, const char *root, int force)
356 struct wgt_info *ifo;
357 const struct wgt_desc *desc;
358 char installdir[PATH_MAX];
360 struct unitconf uconf;
362 NOTICE("-- INSTALLING widget %s to %s --", wgtfile, root);
365 create_directory(root, 0755, 1);
366 if (make_workdir(root, "TMP", 0)) {
367 ERROR("failed to create a working directory");
371 if (zread(wgtfile, 0))
374 if (check_all_signatures())
377 ifo = wgt_info_createat(workdirfd, NULL, 1, 1, 1);
381 reset_requested_permissions();
382 desc = wgt_info_desc(ifo);
383 if (check_widget(desc))
386 if (get_target_directory(installdir, root, desc))
389 if (move_widget_to(installdir, force))
392 if (install_icon(desc))
395 if (install_security(desc))
398 if (install_exec_flag(desc))
405 uconf.installdir = installdir;
406 uconf.icondir = FWK_ICON_DIR;
408 if (unit_install(ifo, &uconf))