+static int install_security(const struct wgt_desc *desc)
+{
+ char path[PATH_MAX], *head;
+ 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;
+
+ /* instal the files */
+ head = stpcpy(path, workdir);
+ assert(head < path + sizeof path);
+ len = (unsigned)((path + sizeof path) - head);
+ if (!len) {
+ ERROR("root path too long in install_security");
+ errno = ENAMETOOLONG;
+ goto error2;
+ }
+ len--;
+ *head++ = '/';
+
+ /* 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();
+ 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++;
+ }
+ }
+
+ /* 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_private(path);
+ if (rc)
+ goto error2;
+ }
+
+ /* install the permissions */
+ perm = first_usable_permission();
+ while(perm) {
+ rc = secmgr_permit(perm);
+ INFO("permitting %s %s", perm, rc ? "FAILED!" : "success");
+ if (rc)
+ goto error2;
+ 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();
+ goto end;
+error2:
+ secmgr_cancel();
+error:
+ rc = -1;
+end:
+ /* free memory of path entries */
+ while (pe0 != NULL) {
+ ppe = pe0;
+ pe0 = pe0->next;
+ free(ppe);
+ }
+ return rc;
+}
+