void die_unless_label_valid (const char *label) { #ifdef HAVE_SELINUX if (is_selinux_enabled () == 1) { if (security_check_context ((security_context_t) label) < 0) die_with_error ("invalid label %s", label); return; } #endif die ("labeling not supported on this system"); }
static int get_failsafe_context(const char *user, security_context_t * newcon) { FILE *fp; char buf[255], *ptr; size_t plen, nlen; int rc; fp = fopen(selinux_failsafe_context_path(), "r"); if (!fp) return -1; ptr = fgets_unlocked(buf, sizeof buf, fp); fclose(fp); if (!ptr) return -1; plen = strlen(ptr); if (buf[plen - 1] == '\n') buf[plen - 1] = 0; retry: nlen = strlen(user) + 1 + plen + 1; *newcon = malloc(nlen); if (!(*newcon)) return -1; rc = snprintf(*newcon, nlen, "%s:%s", user, ptr); if (rc < 0 || (size_t) rc >= nlen) { free(*newcon); *newcon = 0; return -1; } /* If possible, check the context to catch errors early rather than waiting until the caller tries to use setexeccon on the context. But this may not always be possible, e.g. if selinuxfs isn't mounted. */ if (security_check_context(*newcon) && errno != ENOENT) { free(*newcon); *newcon = 0; if (strcmp(user, SELINUX_DEFAULTUSER)) { user = SELINUX_DEFAULTUSER; goto retry; } return -1; } return 0; }
int runcon_main(int argc UNUSED_PARAM, char **argv) { char *role = NULL; char *range = NULL; char *user = NULL; char *type = NULL; char *context = NULL; unsigned opts; context_t con; selinux_or_die(); #if ENABLE_FEATURE_RUNCON_LONG_OPTIONS applet_long_options = runcon_longopts; #endif opt_complementary = "-1"; opts = getopt32(argv, "r:t:u:l:ch", &role, &type, &user, &range); argv += optind; if (!(opts & OPTS_CONTEXT_COMPONENT)) { context = *argv++; if (!argv[0]) bb_error_msg_and_die("no command given"); } if (context) { con = context_new(context); if (!con) bb_error_msg_and_die("'%s' is not a valid context", context); } else { con = runcon_compute_new_context(user, role, type, range, argv[0], opts & OPTS_COMPUTE); } if (security_check_context(context_str(con))) bb_error_msg_and_die("'%s' is not a valid context", context_str(con)); if (setexeccon(context_str(con))) bb_error_msg_and_die("cannot set up security context '%s'", context_str(con)); execvp(argv[0], argv); bb_perror_msg_and_die("cannot execute '%s'", argv[0]); }
int runcon_main(int argc UNUSED_PARAM, char **argv) { char *role = NULL; char *range = NULL; char *user = NULL; char *type = NULL; char *context = NULL; unsigned opts; context_t con; selinux_or_die(); opts = getopt32long(argv, "^" "r:t:u:l:ch" "\0" "-1", runcon_longopts, &role, &type, &user, &range ); argv += optind; if (!(opts & OPTS_CONTEXT_COMPONENT)) { context = *argv++; if (!argv[0]) bb_error_msg_and_die("no command given"); } if (context) { con = context_new(context); if (!con) bb_error_msg_and_die("'%s' is not a valid context", context); } else { con = runcon_compute_new_context(user, role, type, range, argv[0], opts & OPTS_COMPUTE); } if (security_check_context(context_str(con))) bb_error_msg_and_die("'%s' is not a valid context", context_str(con)); if (setexeccon(context_str(con))) bb_error_msg_and_die("can't set up security context '%s'", context_str(con)); BB_EXECVP_or_die(argv); }
static security_context_t context_from_env (pam_handle_t *pamh, security_context_t defaultcon, int env_params, int use_current_range, int debug) { security_context_t newcon = NULL; context_t new_context; context_t my_context = NULL; int mls_enabled = is_selinux_mls_enabled(); const char *env = NULL; char *type = NULL; if ((new_context = context_new(defaultcon)) == NULL) goto fail_set; if (env_params && (env = pam_getenv(pamh, "SELINUX_ROLE_REQUESTED")) != NULL && env[0] != '\0') { if (debug) pam_syslog(pamh, LOG_NOTICE, "Requested role: %s", env); if (get_default_type(env, &type)) { pam_syslog(pamh, LOG_NOTICE, "No default type for role %s", env); goto fail_set; } else { if (context_role_set(new_context, env)) goto fail_set; if (context_type_set(new_context, type)) goto fail_set; } } if (mls_enabled) { if ((env = pam_getenv(pamh, "SELINUX_USE_CURRENT_RANGE")) != NULL && env[0] == '1') { if (debug) pam_syslog(pamh, LOG_NOTICE, "SELINUX_USE_CURRENT_RANGE is set"); use_current_range = 1; } if (use_current_range) { security_context_t mycon = NULL; if (getcon(&mycon) != 0) goto fail_set; my_context = context_new(mycon); if (my_context == NULL) { freecon(mycon); goto fail_set; } freecon(mycon); env = context_range_get(my_context); } else { env = pam_getenv(pamh, "SELINUX_LEVEL_REQUESTED"); } if (env != NULL && env[0] != '\0') { if (debug) pam_syslog(pamh, LOG_NOTICE, "Requested level: %s", env); if (context_range_set(new_context, env)) goto fail_set; } } newcon = strdup(context_str(new_context)); if (newcon == NULL) goto fail_set; if (debug) pam_syslog(pamh, LOG_NOTICE, "Selected Security Context %s", newcon); /* Get the string value of the context and see if it is valid. */ if (security_check_context(newcon)) { pam_syslog(pamh, LOG_NOTICE, "Not a valid security context %s", newcon); send_audit_message(pamh, 0, defaultcon, newcon); freecon(newcon); newcon = NULL; goto fail_set; } /* 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); freecon(newcon); newcon = NULL; } fail_set: free(type); context_free(my_context); context_free(new_context); send_audit_message(pamh, 0, defaultcon, NULL); return newcon; }
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 security_context_t manual_context (pam_handle_t *pamh, const char *user, int debug) { security_context_t newcon=NULL; context_t new_context; int mls_enabled = is_selinux_mls_enabled(); char *type=NULL; char *response=NULL; while (1) { if (query_response(pamh, _("Would you like to enter a security context? [N] "), NULL, &response, debug) != PAM_SUCCESS) return NULL; if ((response[0] == 'y') || (response[0] == 'Y')) { if (mls_enabled) new_context = context_new ("user:role:type:level"); else new_context = context_new ("user:role:type"); if (!new_context) goto fail_set; if (context_user_set (new_context, user)) goto fail_set; _pam_drop(response); /* Allow the user to enter each field of the context individually */ if (query_response(pamh, _("role:"), NULL, &response, debug) == PAM_SUCCESS && response[0] != '\0') { if (context_role_set (new_context, response)) goto fail_set; if (get_default_type(response, &type)) goto fail_set; if (context_type_set (new_context, type)) goto fail_set; } _pam_drop(response); if (mls_enabled) { if (query_response(pamh, _("level:"), NULL, &response, debug) == PAM_SUCCESS && response[0] != '\0') { if (context_range_set (new_context, response)) goto fail_set; } _pam_drop(response); } /* 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)); context_free (new_context); return newcon; } else send_text(pamh,_("Not a valid security context"),debug); context_free (new_context); } else { _pam_drop(response); return NULL; } } /* end while */ fail_set: free(type); _pam_drop(response); context_free (new_context); return NULL; }
/* * Returns a new security context based on the old context and the * specified role and type. */ security_context_t get_exec_context(security_context_t old_context, const char *role, const char *type) { security_context_t new_context = NULL; context_t context = NULL; char *typebuf = NULL; debug_decl(get_exec_context, SUDO_DEBUG_SELINUX) /* We must have a role, the type is optional (we can use the default). */ if (!role) { sudo_warnx(U_("you must specify a role for type %s"), type); errno = EINVAL; goto bad; } if (!type) { if (get_default_type(role, &typebuf)) { sudo_warnx(U_("unable to get default type for role %s"), role); errno = EINVAL; goto bad; } type = typebuf; } /* * Expand old_context into a context_t so that we extract and modify * its components easily. */ context = context_new(old_context); /* * Replace the role and type in "context" with the role and * type we will be running the command as. */ if (context_role_set(context, role)) { sudo_warn(U_("failed to set new role %s"), role); goto bad; } if (context_type_set(context, type)) { sudo_warn(U_("failed to set new type %s"), type); goto bad; } /* * Convert "context" back into a string and verify it. */ if ((new_context = strdup(context_str(context))) == NULL) { sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); goto bad; } if (security_check_context(new_context) < 0) { sudo_warnx(U_("%s is not a valid context"), new_context); errno = EINVAL; goto bad; } #ifdef DEBUG sudo_warnx("Your new context is %s", new_context); #endif context_free(context); debug_return_ptr(new_context); bad: free(typebuf); context_free(context); freecon(new_context); debug_return_ptr(NULL); }
/* * Returns a new security context based on the old context and the * specified role and type. */ security_context_t get_exec_context(security_context_t old_context, const char *role, const char *type) { security_context_t new_context = NULL; context_t context = NULL; char *typebuf = NULL; /* We must have a role, the type is optional (we can use the default). */ if (!role) { warningx("you must specify a role for type %s", type); errno = EINVAL; return NULL; } if (!type) { if (get_default_type(role, &typebuf)) { warningx("unable to get default type for role %s", role); errno = EINVAL; return NULL; } type = typebuf; } /* * Expand old_context into a context_t so that we extract and modify * its components easily. */ context = context_new(old_context); /* * Replace the role and type in "context" with the role and * type we will be running the command as. */ if (context_role_set(context, role)) { warning("failed to set new role %s", role); goto bad; } if (context_type_set(context, type)) { warning("failed to set new type %s", type); goto bad; } /* * Convert "context" back into a string and verify it. */ new_context = estrdup(context_str(context)); if (security_check_context(new_context) < 0) { warningx("%s is not a valid context", new_context); errno = EINVAL; goto bad; } #ifdef DEBUG warningx("Your new context is %s", new_context); #endif context_free(context); return new_context; bad: free(typebuf); context_free(context); freecon(new_context); return NULL; }