int main(int argc, char **argv) { char **buf, **ptr; int ret; if (argc != 3) { fprintf(stderr, "usage: %s context user\n", argv[0]); exit(1); } ret = security_compute_user(argv[1], argv[2], &buf); if (ret < 0) { fprintf(stderr, "%s: security_compute_user(%s,%s) failed\n", argv[0], argv[1], argv[2]); exit(2); } if (!buf[0]) { printf("none\n"); exit(0); } for (ptr = buf; *ptr; ptr++) { printf("%s\n", *ptr); } freeconary(buf); exit(0); }
int get_ordered_context_list(const char *user, security_context_t fromcon, security_context_t ** list) { security_context_t *reachable = NULL; unsigned int *ordering = NULL; struct context_order *co = NULL; char **ptr; int rc = 0; unsigned int nreach = 0, nordered = 0, freefrom = 0, i; FILE *fp; char *fname = NULL; size_t fname_len; const char *user_contexts_path = selinux_user_contexts_path(); if (!fromcon) { /* Get the current context and use it for the starting context */ rc = getcon(&fromcon); if (rc < 0) return rc; freefrom = 1; } /* Determine the set of reachable contexts for the user. */ rc = security_compute_user(fromcon, user, &reachable); if (rc < 0) { /* Retry with the default SELinux user identity. */ user = SELINUX_DEFAULTUSER; rc = security_compute_user(fromcon, user, &reachable); if (rc < 0) goto failsafe; } nreach = 0; for (ptr = reachable; *ptr; ptr++) nreach++; if (!nreach) goto failsafe; /* Initialize ordering array. */ ordering = malloc(nreach * sizeof(unsigned int)); if (!ordering) goto oom_order; for (i = 0; i < nreach; i++) ordering[i] = nreach; /* Determine the ordering to apply from the optional per-user config and from the global config. */ fname_len = strlen(user_contexts_path) + strlen(user) + 2; fname = malloc(fname_len); if (!fname) goto oom_order; snprintf(fname, fname_len, "%s%s", user_contexts_path, user); fp = fopen(fname, "r"); if (fp) { __fsetlocking(fp, FSETLOCKING_BYCALLER); rc = get_context_order(fp, fromcon, reachable, nreach, ordering, &nordered); fclose(fp); if (rc < 0 && errno != ENOENT) { fprintf(stderr, "%s: error in processing configuration file %s\n", __FUNCTION__, fname); /* Fall through, try global config */ } } free(fname); fp = fopen(selinux_default_context_path(), "r"); if (fp) { __fsetlocking(fp, FSETLOCKING_BYCALLER); rc = get_context_order(fp, fromcon, reachable, nreach, ordering, &nordered); fclose(fp); if (rc < 0 && errno != ENOENT) { fprintf(stderr, "%s: error in processing configuration file %s\n", __FUNCTION__, selinux_default_context_path()); /* Fall through */ } } /* Apply the ordering. */ if (nordered) { co = malloc(nreach * sizeof(struct context_order)); if (!co) goto oom_order; for (i = 0; i < nreach; i++) { co[i].con = reachable[i]; co[i].order = ordering[i]; } qsort(co, nreach, sizeof(struct context_order), order_compare); for (i = 0; i < nreach; i++) reachable[i] = co[i].con; free(co); } /* Return the ordered list. If we successfully ordered it, then only report the ordered entries to the caller. Otherwise, fall back to the entire reachable list. */ if (nordered && nordered < nreach) { for (i = nordered; i < nreach; i++) free(reachable[i]); reachable[nordered] = NULL; rc = nordered; } else { rc = nreach; } out: *list = reachable; free(ordering); if (freefrom) freecon(fromcon); return rc; failsafe: /* Unable to determine a reachable context list, try to fall back to the "failsafe" context to at least permit root login for emergency recovery if possible. */ freeconary(reachable); reachable = malloc(2 * sizeof(security_context_t)); if (!reachable) { rc = -1; goto out; } reachable[0] = reachable[1] = 0; rc = get_failsafe_context(user, &reachable[0]); if (rc < 0) { freeconary(reachable); reachable = NULL; goto out; } rc = 1; /* one context in the list */ goto out; oom_order: /* Unable to order context list due to OOM condition. Fall back to unordered reachable context list. */ fprintf(stderr, "%s: out of memory, unable to order list\n", __FUNCTION__); rc = nreach; goto out; }