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 return fchmodat(workdirfd, desc->content_src, 0755, 0);
283 static int install_security(const struct wgt_desc *desc)
285 char path[PATH_MAX], *head;
286 const char *icon, *perm;
288 unsigned int i, n, len, lic, lf;
291 rc = secmgr_init(desc->id);
295 rc = secmgr_path_public_read_only(workdir);
299 /* instal the files */
300 head = stpcpy(path, workdir);
301 assert(head < path + sizeof path);
302 len = (unsigned)((path + sizeof path) - head);
304 ERROR("root path too long in install_security");
305 errno = ENAMETOOLONG;
310 icon = desc->icons->src;
311 lic = (unsigned)strlen(icon);
315 f = file_of_index(i++);
316 lf = (unsigned)strlen(f->name);
318 ERROR("path too long in install_security");
319 errno = ENAMETOOLONG;
322 strcpy(head, f->name);
323 if (lf <= lic && !memcmp(f->name, icon, lf) && (!f->name[lf] || f->name[lf] == '/'))
324 rc = secmgr_path_public_read_only(path);
326 rc = secmgr_path_read_only(path);
331 /* install the permissions */
332 perm = first_usable_permission();
334 rc = secmgr_permit(perm);
335 INFO("permitting %s %s", perm, rc ? "FAILED!" : "success");
338 perm = next_usable_permission();
341 rc = secmgr_install();
349 /* install the widget of the file */
350 struct wgt_info *install_widget(const char *wgtfile, const char *root, int force)
352 struct wgt_info *ifo;
353 const struct wgt_desc *desc;
354 char installdir[PATH_MAX];
357 NOTICE("-- INSTALLING widget %s to %s --", wgtfile, root);
360 create_directory(root, 0755, 1);
361 if (make_workdir(root, "TMP", 0)) {
362 ERROR("failed to create a working directory");
366 if (zread(wgtfile, 0))
369 if (check_all_signatures())
372 ifo = wgt_info_createat(workdirfd, NULL, 1, 1, 1);
376 reset_requested_permissions();
377 desc = wgt_info_desc(ifo);
378 if (check_widget(desc))
381 if (get_target_directory(installdir, root, desc))
384 if (move_widget_to(installdir, force))
387 if (install_icon(desc))
390 if (install_security(desc))
393 if (install_exec_flag(desc))
400 if (unit_install(ifo, installdir, FWK_ICON_DIR, port))