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; }
/* * 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); }
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; /* 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; }