X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fwgtpkg-install.c;h=03cd78fd69db492b78b14efdcc203e6d5f646320;hb=70d6c64f0639b0c8ed2d8624227d1ecdf2853300;hp=f994b8ff159bb4ea31b0882b9bd7e097a3d15037;hpb=2a319cf90daa6e3b01e8139923f7073e1c9bcf28;p=src%2Fapp-framework-main.git diff --git a/src/wgtpkg-install.c b/src/wgtpkg-install.c index f994b8f..03cd78f 100644 --- a/src/wgtpkg-install.c +++ b/src/wgtpkg-install.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2015-2019 IoT.bzh + Copyright (C) 2015-2020 IoT.bzh author: José Bollo @@ -53,19 +53,25 @@ static const char* exec_type_strings[] = { }; static const char key_afm_prefix[] = "X-AFM-"; -static const char key_http_port[] = "http-port"; +static const char key_afid[] = "ID"; -#define HTTP_PORT_MIN 31000 -#define HTTP_PORT_MAX 32759 -#define HTTP_PORT_IS_VALID(port) (HTTP_PORT_MIN <= (port) && (port) <= HTTP_PORT_MAX) -#define HTTP_PORT_COUNT (HTTP_PORT_MAX - HTTP_PORT_MIN + 1) -#define HTTP_PORT_ACNT ((HTTP_PORT_COUNT + 31) >> 5) -#define HTTP_PORT_ASFT(port) (((port) - HTTP_PORT_MIN) & 31) -#define HTTP_PORT_AIDX(port) (((port) - HTTP_PORT_MIN) >> 5) -#define HTTP_PORT_TEST(array,port) ((((array)[HTTP_PORT_AIDX(port)]) >> HTTP_PORT_ASFT(port)) & 1) -#define HTTP_PORT_SET(array,port) (((array)[HTTP_PORT_AIDX(port)]) |= (((uint32_t)1) << HTTP_PORT_ASFT(port))) +#define HTTP_PORT_BASE 30000 -static uint32_t *port_bits = NULL; +#define AFID_MIN 1 +#define AFID_MAX 1999 +#define AFID_IS_VALID(afid) (AFID_MIN <= (afid) && (afid) <= AFID_MAX) +#define AFID_COUNT (AFID_MAX - AFID_MIN + 1) +#define AFID_ACNT ((AFID_COUNT + 31) >> 5) +#define AFID_ASFT(afid) (((afid) - AFID_MIN) & 31) +#define AFID_AIDX(afid) (((afid) - AFID_MIN) >> 5) +#define AFID_TEST(array,afid) ((((array)[AFID_AIDX(afid)]) >> AFID_ASFT(afid)) & 1) +#define AFID_SET(array,afid) (((array)[AFID_AIDX(afid)]) |= (((uint32_t)1) << AFID_ASFT(afid))) + +static uint32_t *afids_array = NULL; + +static const char *default_permissions[] = { + "urn:AGL:token:valid" +}; /* * normalize unit files: remove comments, remove heading blanks, @@ -99,7 +105,7 @@ static void normalize_unit_file(char *content) *write = c; } -static int get_port_cb(void *closure, const char *name, const char *path, int isuser) +static int get_afid_cb(void *closure, const char *name, const char *path, int isuser) { char *iter; char *content; @@ -120,15 +126,15 @@ static int get_port_cb(void *closure, const char *name, const char *path, int is iter += sizeof key_afm_prefix - 1; if (*iter == '-') iter++; - if (!strncmp(iter, key_http_port, sizeof key_http_port - 1)) { - iter += sizeof key_http_port - 1; + if (!strncmp(iter, key_afid, sizeof key_afid - 1)) { + iter += sizeof key_afid - 1; while(*iter && *iter != '=' && *iter != '\n') iter++; if (*iter == '=') { while(*++iter == ' '); p = atoi(iter); - if (HTTP_PORT_IS_VALID(p)) - HTTP_PORT_SET((uint32_t*)closure, p); + if (AFID_IS_VALID(p)) + AFID_SET((uint32_t*)closure, p); } } iter = strstr(iter, key_afm_prefix); @@ -137,53 +143,59 @@ static int get_port_cb(void *closure, const char *name, const char *path, int is return 0; } -static int update_portbits(uint32_t *portbits) +static int update_afids(uint32_t *afids) { int rc; - memset(portbits, 0, HTTP_PORT_ACNT * sizeof(uint32_t)); - rc = systemd_unit_list(0, get_port_cb, portbits); + memset(afids, 0, AFID_ACNT * sizeof(uint32_t)); + rc = systemd_unit_list(0, get_afid_cb, afids); if (rc >= 0) - rc = systemd_unit_list(1, get_port_cb, portbits); + rc = systemd_unit_list(1, get_afid_cb, afids); if (rc < 0) - ERROR("troubles while updating ports"); + ERROR("troubles while updating afids"); return rc; } -static int first_free_port(uint32_t *portbits) +static int first_free_afid(uint32_t *afids) { - int port; - - port = HTTP_PORT_MIN; - while (port <= HTTP_PORT_MAX && !~portbits[HTTP_PORT_AIDX(port)]) - port += 32; - while (port <= HTTP_PORT_MAX && HTTP_PORT_TEST(portbits, port)) - port++; - if (port > HTTP_PORT_MAX) { - ERROR("Can't compute a valid port"); + int afid; + + afid = AFID_MIN; + while (afid <= AFID_MAX && !~afids[AFID_AIDX(afid)]) + afid += 32; + while (afid <= AFID_MAX && AFID_TEST(afids, afid)) + afid++; + if (afid > AFID_MAX) { + ERROR("Can't compute a valid afid"); errno = EADDRNOTAVAIL; - port = -1; + afid = -1; } - return port; + return afid; } -static int get_port() +static int get_new_afid() { - int port; + int afid; - /* ensure existing port bitmap */ - if (port_bits == NULL) { - port_bits = malloc(HTTP_PORT_ACNT * sizeof(uint32_t)); - if (port_bits == NULL || update_portbits(port_bits) < 0) + /* ensure existing afid bitmap */ + if (afids_array == NULL) { + afids_array = malloc(AFID_ACNT * sizeof(uint32_t)); + if (afids_array == NULL || update_afids(afids_array) < 0) return -1; } - /* allocates the port */ - port = first_free_port(port_bits); - if (port >= 0) - HTTP_PORT_SET(port_bits, port); + /* allocates the afid */ + afid = first_free_afid(afids_array); + if (afid < 0 && errno == EADDRNOTAVAIL) { + /* no more ids, try to rescan */ + memset(afids_array, 0, AFID_ACNT * sizeof(uint32_t)); + if (update_afids(afids_array) >= 0) + afid = first_free_afid(afids_array); + } + if (afid >= 0) + AFID_SET(afids_array, afid); - return port; + return afid; } static int check_defined(const void *data, const char *name) @@ -300,7 +312,7 @@ static int for_all_content(const struct wgt_desc *desc, int (*action)(const char rc = action(desc->content_src, desc->content_type); feat = desc->features; while (feat) { - if (!strcmp(feat->name, "urn:AGL:widget:provided-unit")) { + if (!strcmp(feat->name, FWK_PREFIX"widget:provided-unit")) { src = wgt_info_param(feat, "content.src"); type = wgt_info_param(feat, "content.type"); rc2 = action(src, type); @@ -386,7 +398,11 @@ static int get_target_directory(char target[PATH_MAX], const char *root, const s { int rc; +#if DISTINCT_VERSIONS rc = snprintf(target, PATH_MAX, "%s/%s/%s", root, desc->id, desc->ver); +#else + rc = snprintf(target, PATH_MAX, "%s/%s", root, desc->id); +#endif if (rc < PATH_MAX) rc = 0; else { @@ -447,7 +463,7 @@ static int install_file_properties(const struct wgt_desc *desc) rc = 0; feat = desc->features; while (feat) { - if (!strcmp(feat->name, "urn:AGL:widget:file-properties")) { + if (!strcmp(feat->name, FWK_PREFIX"widget:file-properties")) { param = feat->params; while (param) { if (!strcmp(param->value, "executable")) { @@ -469,22 +485,60 @@ static int install_file_properties(const struct wgt_desc *desc) return rc; } +static int is_path_public(const char *path, const struct wgt_desc *desc) +{ + const struct wgt_desc_icon *icon; + const struct wgt_desc_feature *feat; + const struct wgt_desc_param *param; + size_t len; + + /* icons are public */ + icon = desc->icons; + while (icon != NULL) { + len = strlen(icon->src); + if (!memcmp(path, icon->src, len) && (path[len] == 0 || path[len] == '/')) + return 1; + icon = icon->next; + } + + /* provided bindings are public */ + feat = desc->features; + while (feat != NULL) { + if (strcasecmp(feat->name, "urn:AGL:widget:provided-binding") == 0 + || strcasecmp(feat->name, "urn:AGL:widget:public-files") == 0) { + param = feat->params; + while(param != NULL) { + if (strcmp(param->value, path) == 0) + return 1; + param = param->next; + } + } + feat = feat->next; + } + + /* otherwise no */ + return 0; +} + static int install_security(const struct wgt_desc *desc) { char path[PATH_MAX], *head; - const char *icon, *perm; - int rc; - unsigned int i, n, len, lic, lf; + const char *perm; + int rc, public; + unsigned int i, n, len, lf, j; struct filedesc *f; - + struct pathent { + struct pathent *next; + unsigned int len; + int public; + char name[]; + } *pe0, *pe2, *ppe; + + pe0 = NULL; rc = secmgr_init(desc->id); if (rc) goto error; - rc = secmgr_path_public_read_only(workdir); - if (rc) - goto error2; - /* instal the files */ head = stpcpy(path, workdir); assert(head < path + sizeof path); @@ -496,23 +550,78 @@ static int install_security(const struct wgt_desc *desc) } len--; *head++ = '/'; - icon = desc->icons ? desc->icons->src : NULL; - lic = (unsigned)(icon ? strlen(icon) : 0); + + /* build root entry */ + pe0 = malloc(1 + sizeof *pe0); + if (pe0 == NULL) + goto error2; + pe0->next = NULL; + pe0->len = 0; + pe0->public = 0; + pe0->name[0] = 0; + + /* build list of entries */ n = file_count(); - i = 0; - while(i < n) { - f = file_of_index(i++); - lf = (unsigned)strlen(f->name); - if (lf >= len) { - ERROR("path too long in install_security"); - errno = ENAMETOOLONG; - goto error2; + for (i = 0 ; i < n ; i++) { + f = file_of_index(i); + public = is_path_public(f->name, desc); + pe0->public |= public; + lf = j = 0; + while(f->name[j] == '/') + j++; + while (f->name[j] != 0) { + /* copy next entry of the path */ + while(f->name[j] && f->name[j] != '/') { + if (lf + 1 >= len) { + ERROR("path too long in install_security"); + errno = ENAMETOOLONG; + goto error2; + } + head[lf++] = f->name[j++]; + } + head[lf] = 0; + + /* search if it already exists */ + ppe = pe0; + pe2 = pe0->next; + while (pe2 != NULL && pe2->len < lf) { + ppe = pe2; + pe2 = pe2->next; + } + while (pe2 != NULL && pe2->len == lf && strcmp(head, pe2->name)) { + ppe = pe2; + pe2 = pe2->next; + } + + if (pe2 != NULL && pe2->len == lf) + /* existing, update public status */ + pe2->public |= public; + else { + /* not existing, create it */ + pe2 = malloc(lf + 1 + sizeof *pe2); + if (pe2 == NULL) + goto error2; + pe2->next = ppe->next; + pe2->len = lf; + pe2->public = public; + memcpy(pe2->name, head, 1 + lf); + ppe->next = pe2; + } + + /* prepare next path entry */ + head[lf++] = '/'; + while(f->name[j] == '/') + j++; } - strcpy(head, f->name); - if (lf <= lic && icon && !memcmp(f->name, icon, lf) && (!f->name[lf] || f->name[lf] == '/')) + } + + /* set the path entries */ + for (pe2 = pe0 ; pe2 != NULL ; pe2 = pe2->next) { + strcpy(head, pe2->name); + if (pe2->public) rc = secmgr_path_public_read_only(path); else - rc = secmgr_path_read_only(path); + rc = secmgr_path_private(path); if (rc) goto error2; } @@ -527,12 +636,30 @@ static int install_security(const struct wgt_desc *desc) perm = next_usable_permission(); } + /* install default permissions */ + n = (unsigned int)(sizeof default_permissions / sizeof *default_permissions); + for (i = 0 ; i < n ; i++) { + perm = default_permissions[i]; + rc = secmgr_permit(perm); + INFO("permitting %s %s", perm, rc ? "FAILED!" : "success"); + if (rc) + goto error2; + } + rc = secmgr_install(); - return rc; + goto end; error2: secmgr_cancel(); error: - return -1; + rc = -1; +end: + /* free memory of path entries */ + while (pe0 != NULL) { + ppe = pe0; + pe0 = pe0->next; + free(ppe); + } + return rc; } /* install the widget of the file */ @@ -541,7 +668,7 @@ struct wgt_info *install_widget(const char *wgtfile, const char *root, int force struct wgt_info *ifo; const struct wgt_desc *desc; char installdir[PATH_MAX]; - int err; + int err, rc; struct unitconf uconf; NOTICE("-- INSTALLING widget %s to %s --", wgtfile, root); @@ -556,7 +683,12 @@ struct wgt_info *install_widget(const char *wgtfile, const char *root, int force if (zread(wgtfile, 0)) goto error2; - if (check_all_signatures(DEFAULT_ALLOW_NO_SIGNATURE)) +#if defined(ALLOW_NO_SIGNATURE) + rc = check_all_signatures(1); +#else + rc = check_all_signatures(0); +#endif + if (rc) goto error2; ifo = wgt_info_createat(workdirfd, NULL, 1, 1, 1); @@ -598,7 +730,8 @@ struct wgt_info *install_widget(const char *wgtfile, const char *root, int force uconf.installdir = installdir; uconf.icondir = FWK_ICON_DIR; - uconf.port = get_port; + uconf.new_afid = get_new_afid; + uconf.base_http_ports = HTTP_PORT_BASE; if (unit_install(ifo, &uconf)) goto error4;