X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fwgtpkg-install.c;h=03cd78fd69db492b78b14efdcc203e6d5f646320;hb=70d6c64f0639b0c8ed2d8624227d1ecdf2853300;hp=31ef7c4eb4547b96d61393f06112756438e85252;hpb=bceaf2cc403176fd808d4e00be893671be3f4bb0;p=src%2Fapp-framework-main.git diff --git a/src/wgtpkg-install.c b/src/wgtpkg-install.c index 31ef7c4..03cd78f 100644 --- a/src/wgtpkg-install.c +++ b/src/wgtpkg-install.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2015-2018 IoT.bzh + Copyright (C) 2015-2020 IoT.bzh author: José Bollo @@ -53,7 +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_BASE 30000 + +#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, @@ -87,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; @@ -108,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 (p >= 0 && p < 32768) - ((uint32_t*)closure)[p >> 5] |= (uint32_t)1 << (p & 31); + if (AFID_IS_VALID(p)) + AFID_SET((uint32_t*)closure, p); } } iter = strstr(iter, key_afm_prefix); @@ -125,29 +143,61 @@ static int get_port_cb(void *closure, const char *name, const char *path, int is return 0; } -static int get_port() +static int update_afids(uint32_t *afids) { int rc; - uint32_t ports[1024]; /* 1024 * 32 = 32768 */ - - memset(ports, 0, sizeof ports); - rc = systemd_unit_list(0, get_port_cb, &ports); - if (rc >= 0) { - rc = systemd_unit_list(1, get_port_cb, ports); - if (rc >= 0) { - for (rc = 1024 ; rc < 32768 && !~ports[rc >> 5] ; rc += 32); - if (rc == 32768) { - ERROR("Can't compute a valid port"); - errno = EADDRNOTAVAIL; - rc = -1; - } else { - while (1 & (ports[rc >> 5] >> (rc & 31))) rc++; - } - } - } + + 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_afid_cb, afids); + if (rc < 0) + ERROR("troubles while updating afids"); return rc; } +static int first_free_afid(uint32_t *afids) +{ + 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; + afid = -1; + } + return afid; +} + +static int get_new_afid() +{ + int afid; + + /* 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 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 afid; +} + static int check_defined(const void *data, const char *name) { if (data) @@ -262,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); @@ -348,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 { @@ -409,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")) { @@ -431,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); @@ -458,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; } @@ -489,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 */ @@ -503,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 port, err; + int err, rc; struct unitconf uconf; NOTICE("-- INSTALLING widget %s to %s --", wgtfile, root); @@ -518,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); @@ -558,13 +728,10 @@ struct wgt_info *install_widget(const char *wgtfile, const char *root, int force if (install_file_properties(desc)) goto error4; - port = get_port(); - if (port < 0) - goto error4; - uconf.installdir = installdir; uconf.icondir = FWK_ICON_DIR; - uconf.port = port; + uconf.new_afid = get_new_afid; + uconf.base_http_ports = HTTP_PORT_BASE; if (unit_install(ifo, &uconf)) goto error4;