static int parse_components(context_t con, char **components) { components[COLOR_USER] = (char *)context_user_get(con); components[COLOR_ROLE] = (char *)context_role_get(con); components[COLOR_TYPE] = (char *)context_type_get(con); components[COLOR_RANGE] = (char *)context_range_get(con); 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 find_partialcon(security_context_t * list, unsigned int nreach, char *part) { const char *conrole, *contype; char *partrole, *parttype, *ptr; context_t con; unsigned int i; partrole = part; ptr = part; while (*ptr && !isspace(*ptr) && *ptr != ':') ptr++; if (*ptr != ':') return -1; *ptr++ = 0; parttype = ptr; while (*ptr && !isspace(*ptr) && *ptr != ':') ptr++; *ptr = 0; for (i = 0; i < nreach; i++) { con = context_new(list[i]); if (!con) return -1; conrole = context_role_get(con); contype = context_type_get(con); if (!conrole || !contype) { context_free(con); return -1; } if (!strcmp(conrole, partrole) && !strcmp(contype, parttype)) { context_free(con); return i; } context_free(con); } return -1; }
static void disp_con(security_context_t scon) { context_t con = NULL; if (!*scon) { /* --self-exec and --self-fs etc. */ if (opts->disp_user) disp__con_val("user", NULL); if (opts->disp_role) disp__con_val("role", NULL); if (opts->disp_type) disp__con_val("type", NULL); if (opts->disp_sen) disp__con_val("sensitivity", NULL); if (opts->disp_clr) disp__con_val("clearance", NULL); if (opts->disp_mlsr) disp__con_val("mls-range", NULL); return; } if (!(con = context_new(scon))) errx(EXIT_FAILURE, "Couldn't create context from: %s", scon); if (opts->disp_user) disp__con_val("user", context_user_get(con)); if (opts->disp_role) disp__con_val("role", context_role_get(con)); if (opts->disp_type) disp__con_val("type", context_type_get(con)); if (opts->disp_sen) { const char *val = NULL; char *tmp = NULL; val = context_range_get(con); if (!val) val = ""; /* targeted has no "level" etc., any errors should happen at context_new() time */ tmp = strdup(val); if (!tmp) errx(EXIT_FAILURE, "Couldn't create context from: %s", scon); if (strchr(tmp, '-')) *strchr(tmp, '-') = 0; disp__con_val("sensitivity", tmp); free(tmp); } if (opts->disp_clr) { const char *val = NULL; char *tmp = NULL; val = context_range_get(con); if (!val) val = ""; /* targeted has no "level" etc., any errors should happen at context_new() time */ tmp = strdup(val); if (!tmp) errx(EXIT_FAILURE, "Couldn't create context from: %s", scon); if (strchr(tmp, '-')) disp__con_val("clearance", strchr(tmp, '-') + 1); else disp__con_val("clearance", tmp); free(tmp); } if (opts->disp_mlsr) disp__con_val("mls-range", context_range_get(con)); context_free(con); }
/* * do_set_domain * It tries to replace the domain/range of the current context. */ static int do_set_domain(security_context_t old_context, char *domain, server_rec *s) { security_context_t new_context; security_context_t raw_context; context_t context; char *range; /* * Compute the new security context */ context = context_new(old_context); if (!context) { ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "SELinux: context_new(\"%s\") failed", old_context); return -1; } range = strchr(domain, ':'); if (range) *range++ = '\0'; if (domain && strcmp(domain, "*") != 0) context_type_set(context, domain); if (range && strcmp(range, "*") != 0) context_range_set(context, range); if (range) *--range = ':'; /* fixup */ new_context = context_str(context); if (!new_context) { ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "SELinux: context_str(\"%s:%s:%s:%s\") failed", context_user_get(context), context_role_get(context), context_type_get(context), context_range_get(context)); context_free(context); return -1; } /* * If old_context == new_context, we don't need to do anything */ if (selinux_trans_to_raw_context(new_context, &raw_context) < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "SELinux: selinux_trans_to_raw_context(\"%s\") failed", new_context); context_free(context); return -1; } context_free(context); if (!strcmp(old_context, raw_context)) { freecon(raw_context); return 1; } if (setcon_raw(raw_context) < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "SELinux: setcon_raw(\"%s\") failed", raw_context); freecon(raw_context); return -1; } freecon(raw_context); return 0; }
static security_context_t config_context (pam_handle_t *pamh, security_context_t defaultcon, int use_current_range, int debug) { security_context_t newcon=NULL; context_t new_context; int mls_enabled = is_selinux_mls_enabled(); char *response=NULL; char *type=NULL; char resp_val = 0; pam_prompt (pamh, PAM_TEXT_INFO, NULL, _("Default Security Context %s\n"), defaultcon); while (1) { if (query_response(pamh, _("Would you like to enter a different role or level?"), "n", &response, debug) == PAM_SUCCESS) { resp_val = response[0]; _pam_drop(response); } else { resp_val = 'N'; } if ((resp_val == 'y') || (resp_val == 'Y')) { if ((new_context = context_new(defaultcon)) == NULL) goto fail_set; /* Allow the user to enter role and level individually */ if (query_response(pamh, _("role:"), context_role_get(new_context), &response, debug) == PAM_SUCCESS && response[0]) { if (get_default_type(response, &type)) { pam_prompt (pamh, PAM_ERROR_MSG, NULL, _("No default type for role %s\n"), response); _pam_drop(response); continue; } else { if (context_role_set(new_context, response)) goto fail_set; if (context_type_set (new_context, type)) goto fail_set; } } _pam_drop(response); if (mls_enabled) { if (use_current_range) { security_context_t mycon = NULL; context_t my_context; if (getcon(&mycon) != 0) goto fail_set; my_context = context_new(mycon); if (my_context == NULL) { freecon(mycon); goto fail_set; } freecon(mycon); if (context_range_set(new_context, context_range_get(my_context))) { context_free(my_context); goto fail_set; } context_free(my_context); } else if (query_response(pamh, _("level:"), context_range_get(new_context), &response, debug) == PAM_SUCCESS && response[0]) { if (context_range_set(new_context, response)) goto fail_set; } _pam_drop(response); } if (debug) pam_syslog(pamh, LOG_NOTICE, "Selected Security Context %s", context_str(new_context)); /* Get the string value of the context and see if it is valid. */ if (!security_check_context(context_str(new_context))) { newcon = strdup(context_str(new_context)); if (newcon == NULL) goto fail_set; context_free(new_context); /* we have to check that this user is allowed to go into the range they have specified ... role is tied to an seuser, so that'll be checked at setexeccon time */ if (mls_enabled && !mls_range_allowed(pamh, defaultcon, newcon, debug)) { pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon); send_audit_message(pamh, 0, defaultcon, newcon); free(newcon); goto fail_range; } return newcon; } else { send_audit_message(pamh, 0, defaultcon, context_str(new_context)); send_text(pamh,_("Not a valid security context"),debug); } context_free(new_context); /* next time around allocates another */ } else return strdup(defaultcon); } /* end while */ return NULL; fail_set: free(type); _pam_drop(response); context_free (new_context); send_audit_message(pamh, 0, defaultcon, NULL); fail_range: return NULL; }
static bool testSELinuxCheckCon(context_t con, const char *user, const char *role, const char *type, int sensMin, int sensMax ATTRIBUTE_UNUSED, int catMin, int catMax) { const char *range; char *tmp; int gotSens; int gotCatOne; int gotCatTwo; if (STRNEQ(context_user_get(con), user)) { fprintf(stderr, "Expect user %s got %s\n", user, context_user_get(con)); return false; } if (STRNEQ(context_role_get(con), role)) { fprintf(stderr, "Expect role %s got %s\n", role, context_role_get(con)); return false; } if (STRNEQ(context_type_get(con), type)) { fprintf(stderr, "Expect type %s got %s\n", type, context_type_get(con)); return false; } range = context_range_get(con); if (range[0] != 's') { fprintf(stderr, "Malformed range %s, cannot find sensitivity\n", range); return false; } if (virStrToLong_i(range + 1, &tmp, 10, &gotSens) < 0 || !tmp) { fprintf(stderr, "Malformed range %s, cannot parse sensitivity\n", range + 1); return false; } if (*tmp != ':') { fprintf(stderr, "Malformed range %s, too many sensitivity values\n", tmp); return false; } tmp++; if (*tmp != 'c') { fprintf(stderr, "Malformed range %s, cannot find first category\n", tmp); return false; } tmp++; if (virStrToLong_i(tmp, &tmp, 10, &gotCatOne) < 0) { fprintf(stderr, "Malformed range %s, cannot parse category one\n", tmp); return false; } if (tmp && *tmp == ',') tmp++; if (tmp && *tmp == 'c') { tmp++; if (virStrToLong_i(tmp, &tmp, 10, &gotCatTwo) < 0) { fprintf(stderr, "Malformed range %s, cannot parse category two\n", tmp); return false; } if (*tmp != '\0') { fprintf(stderr, "Malformed range %s, junk after second category\n", tmp); return false; } if (gotCatOne == gotCatTwo) { fprintf(stderr, "Saw category pair %d,%d where cats were equal\n", gotCatOne, gotCatTwo); return false; } } else { gotCatTwo = gotCatOne; } if (gotSens != sensMin) { fprintf(stderr, "Sensitivity %d is not equal to min %d\n", gotSens, sensMin); return false; } if (gotCatOne < catMin || gotCatOne > catMax) { fprintf(stderr, "Category one %d is out of range %d-%d\n", gotCatTwo, catMin, catMax); return false; } if (gotCatTwo < catMin || gotCatTwo > catMax) { fprintf(stderr, "Category two %d is out of range %d-%d\n", gotCatTwo, catMin, catMax); return false; } if (gotCatOne > gotCatTwo) { fprintf(stderr, "Category one %d is greater than category two %d\n", gotCatOne, gotCatTwo); return false; } return true; }
static int get_context_order(FILE * fp, security_context_t fromcon, security_context_t * reachable, unsigned int nreach, unsigned int *ordering, unsigned int *nordered) { char *start, *end = NULL; char *line = NULL; size_t line_len = 0; ssize_t len; int found = 0; const char *fromrole, *fromtype; char *linerole, *linetype; unsigned int i; context_t con; int rc; errno = -EINVAL; /* Extract the role and type of the fromcon for matching. User identity and MLS range can be variable. */ con = context_new(fromcon); if (!con) return -1; fromrole = context_role_get(con); fromtype = context_type_get(con); if (!fromrole || !fromtype) { context_free(con); return -1; } while ((len = getline(&line, &line_len, fp)) > 0) { if (line[len - 1] == '\n') line[len - 1] = 0; /* Skip leading whitespace. */ start = line; while (*start && isspace(*start)) start++; if (!(*start)) continue; /* Find the end of the (partial) fromcon in the line. */ end = start; while (*end && !isspace(*end)) end++; if (!(*end)) continue; /* Check for a match. */ linerole = start; while (*start && !isspace(*start) && *start != ':') start++; if (*start != ':') continue; *start = 0; linetype = ++start; while (*start && !isspace(*start) && *start != ':') start++; if (!(*start)) continue; *start = 0; if (!strcmp(fromrole, linerole) && !strcmp(fromtype, linetype)) { found = 1; break; } } if (!found) { errno = ENOENT; rc = -1; goto out; } start = ++end; while (*start) { /* Skip leading whitespace */ while (*start && isspace(*start)) start++; if (!(*start)) break; /* Find the end of this partial context. */ end = start; while (*end && !isspace(*end)) end++; if (*end) *end++ = 0; /* Check for a match in the reachable list. */ rc = find_partialcon(reachable, nreach, start); if (rc < 0) { /* No match, skip it. */ start = end; continue; } /* If a match is found and the entry is not already ordered (e.g. due to prior match in prior config file), then set the ordering for it. */ i = rc; if (ordering[i] == nreach) ordering[i] = (*nordered)++; start = end; } rc = 0; out: context_free(con); free(line); return rc; }