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 main(int argc, char **argv) { char *seuser = NULL, *level = NULL; security_context_t *contextlist; int rc, n, i; if (argc != 3) { fprintf(stderr, "usage: %s linuxuser fromcon\n", argv[0]); exit(1); } rc = getseuserbyname(argv[1], &seuser, &level); if (rc) { fprintf(stderr, "getseuserbyname failed: %s\n", strerror(errno)); exit(2); } printf("seuser: %s, level %s\n", seuser, level); n = get_ordered_context_list_with_level(seuser, level, argv[2], &contextlist); if (n <= 0) { fprintf(stderr, "get_ordered_context_list_with_level failed: %s\n", strerror(errno)); exit(3); } free(seuser); free(level); for (i = 0; i < n; i++) printf("Context %d\t%s\n", i, contextlist[i]); freeconary(contextlist); exit(0); }
int main(int argc, char **argv) { security_context_t *list, usercon = NULL, cur_context = NULL; char *user = NULL, *level = NULL; int ret, i, opt; while ((opt = getopt(argc, argv, "l:")) > 0) { switch (opt) { case 'l': level = strdup(optarg); break; default: usage(argv[0], "invalid option", 1); } } if (((argc - optind) < 1) || ((argc - optind) > 2)) usage(argv[0], "invalid number of arguments", 2); /* If selinux isn't available, bail out. */ if (!is_selinux_enabled()) { fprintf(stderr, "getconlist may be used only on a SELinux kernel.\n"); return 1; } user = argv[optind]; /* If a context wasn't passed, use the current context. */ if (((argc - optind) < 2)) { if (getcon(&cur_context) < 0) { fprintf(stderr, "Couldn't get current context.\n"); return 2; } } else cur_context = argv[optind + 1]; /* Get the list and print it */ if (level) ret = get_ordered_context_list_with_level(user, level, cur_context, &list); else ret = get_ordered_context_list(user, cur_context, &list); if (ret != -1) { for (i = 0; list[i]; i++) puts(list[i]); freeconary(list); } free(usercon); return 0; }
/* * Launch sulogin and wait it for finish */ void initng_main_su_login(void) { pid_t sulogin_pid; int status; #ifdef SELINUX if (is_selinux_enabled > 0) { security_context_t *contextlist = NULL; if (get_ordered_context_list("root", 0, &contextlist) > 0) { if (setexeccon(contextlist[0]) != 0) fprintf(stderr, "setexeccon failed\n"); freeconary(contextlist); } } #endif /* sulogin nicely 2 times */ if (local_sulogin_count <= TRY_TIMES) { printf("This is a sulogin offer,\n" "you will be able to login for %i times (now %i),\n" "and on return initng will try continue where it was,\n" "if the times go out, initng will launch\n" "/sbin/initng-segfault on next su_login request.\n\n", TRY_TIMES, local_sulogin_count); sulogin_pid = fork(); if (sulogin_pid == 0) { const char *sulogin_argv[] = { "/sbin/sulogin", NULL }; const char *sulogin_env[] = { NULL }; /* launch sulogin */ execve(sulogin_argv[0], (char **)sulogin_argv, (char **)sulogin_env); printf("Unable to execute /sbin/sulogin!\n"); } else if (sulogin_pid > 0) { do { sulogin_pid = waitpid(sulogin_pid, &status, WUNTRACED); } while (!WIFEXITED(status) && !WIFSIGNALED(status)); /* increase the sulogin_count */ local_sulogin_count++; } } /* else run segfault script */ initng_main_segfault(); }
int get_default_context(const char *user, security_context_t fromcon, security_context_t * newcon) { security_context_t *conary; int rc; rc = get_ordered_context_list(user, fromcon, &conary); if (rc <= 0) return -1; *newcon = strdup(conary[0]); freeconary(conary); if (!(*newcon)) return -1; return 0; }
int get_default_context_with_level(const char *user, const char *level, char * fromcon, char ** newcon) { char **conary; int rc; rc = get_ordered_context_list_with_level(user, level, fromcon, &conary); if (rc <= 0) return -1; *newcon = strdup(conary[0]); freeconary(conary); if (!(*newcon)) return -1; return 0; }
int get_default_context_with_role(const char *user, const char *role, char * fromcon, char ** newcon) { char **conary; char **ptr; context_t con; const char *role2; int rc; rc = get_ordered_context_list(user, fromcon, &conary); if (rc <= 0) return -1; for (ptr = conary; *ptr; ptr++) { con = context_new(*ptr); if (!con) continue; role2 = context_role_get(con); if (role2 && !strcmp(role, role2)) { context_free(con); break; } context_free(con); } rc = -1; if (!(*ptr)) { errno = EINVAL; goto out; } *newcon = strdup(*ptr); if (!(*newcon)) goto out; rc = 0; out: freeconary(conary); return rc; }
static int get_security_context(char *name, int crontab_fd, security_context_t *rcontext, char *tabname) { security_context_t *context_list = NULL; security_context_t current_con; int list_count = 0; security_context_t file_context=NULL; struct av_decision avd; int retval=0; char *seuser = NULL; char *level = NULL; int i; if (name != NULL) { if (getseuserbyname(name, &seuser, &level)) { log_it(name, getpid(), "getseuserbyname FAILED", tabname); return (security_getenforce() > 0); } } else { seuser = strdup("system_u"); } *rcontext = NULL; if(getcon(¤t_con)) { log_it(name, getpid(), "Can't get current context", tabname); return -1; } list_count = get_ordered_context_list_with_level(seuser, level, current_con, &context_list); freecon(current_con); free(seuser); free(level); if (list_count == -1) { if (security_getenforce() > 0) { log_it(name, getpid(), "No SELinux security context", tabname); return -1; } else { log_it(name, getpid(), "No security context but SELinux in permissive mode," " continuing", tabname); return 0; } } if (fgetfilecon(crontab_fd, &file_context) < OK) { if (security_getenforce() > 0) { log_it(name, getpid(), "getfilecon FAILED", tabname); freeconary(context_list); return -1; } else { log_it(name, getpid(), "getfilecon FAILED but SELinux in " "permissive mode, continuing", tabname); *rcontext = strdup(context_list[0]); freeconary(context_list); return 0; } } /* * Since crontab files are not directly executed, * crond must ensure that the crontab file has * a context that is appropriate for the context of * the user cron job. It performs an entrypoint * permission check for this purpose. */ for(i = 0; i < list_count; i++) { retval = security_compute_av(context_list[i], file_context, SECCLASS_FILE, FILE__ENTRYPOINT, &avd); if(!retval && ((FILE__ENTRYPOINT & avd.allowed) == FILE__ENTRYPOINT)) { *rcontext = strdup(context_list[i]); freecon(file_context); freeconary(context_list); return 0; } } freecon(file_context); if (security_getenforce() > 0) { log_it(name, getpid(), "ENTRYPOINT FAILED", tabname); freeconary(context_list); return -1; } else { log_it(name, getpid(), "ENTRYPOINT FAILED but SELinux in permissive mode, continuing", tabname); *rcontext = strdup(context_list[0]); freeconary(context_list); } return 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; }