diff options
author | Tomas Mraz <tm@t8m.info> | 2008-07-11 15:37:28 +0000 |
---|---|---|
committer | Tomas Mraz <tm@t8m.info> | 2008-07-11 15:37:28 +0000 |
commit | 3c3bb4c3659615ffba1b23f537120ea996e8a774 (patch) | |
tree | 3e290447a93899cb391b6d2a35409f016ab1a39a /modules/pam_selinux/pam_selinux.c | |
parent | 0323cbc3d94badc4d5e941a8fb679444dcb72bbb (diff) | |
download | pam-3c3bb4c3659615ffba1b23f537120ea996e8a774.tar.gz pam-3c3bb4c3659615ffba1b23f537120ea996e8a774.tar.bz2 pam-3c3bb4c3659615ffba1b23f537120ea996e8a774.zip |
Relevant BUGIDs:
Purpose of commit: new feature
Commit summary:
---------------
2008-07-11 Tomas Mraz <t8m@centrum.cz>
* modules/pam_selinux/pam_selinux.c (config_context): Do not
ask for the level if use_current_range is set.
(context_from_env): New function to obtain the context from
PAM environment variables.
(pam_sm_open_session): Call context_from_env() if env_params option
is present. use_current_range now modifies behavior of the
context_from_env and config_context options.
* modules/pam_selinux/pam_selinux.8.xml: Describe the env_params
option. Adjust description of use_current_range option.
Diffstat (limited to 'modules/pam_selinux/pam_selinux.c')
-rw-r--r-- | modules/pam_selinux/pam_selinux.c | 208 |
1 files changed, 143 insertions, 65 deletions
diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c index da1290f0..e45d6f99 100644 --- a/modules/pam_selinux/pam_selinux.c +++ b/modules/pam_selinux/pam_selinux.c @@ -2,8 +2,9 @@ * A module for Linux-PAM that will set the default security context after login * via PAM. * - * Copyright (c) 2003 Red Hat, Inc. + * Copyright (c) 2003-2008 Red Hat, Inc. * Written by Dan Walsh <dwalsh@redhat.com> + * Additional improvements by Tomas Mraz <tmraz@redhat.com> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -252,7 +253,7 @@ static int mls_range_allowed(pam_handle_t *pamh, security_context_t src, securit } static security_context_t -config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) +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; @@ -261,7 +262,7 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) char *type=NULL; char resp_val = 0; - pam_prompt (pamh, PAM_TEXT_INFO, NULL, _("Default Security Context %s\n"), puser_context); + pam_prompt (pamh, PAM_TEXT_INFO, NULL, _("Default Security Context %s\n"), defaultcon); while (1) { if (query_response(pamh, @@ -274,7 +275,7 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) } if ((resp_val == 'y') || (resp_val == 'Y')) { - if ((new_context = context_new(puser_context)) == NULL) + if ((new_context = context_new(defaultcon)) == NULL) goto fail_set; /* Allow the user to enter role and level individually */ @@ -295,10 +296,27 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) if (mls_enabled) { - if (query_response(pamh, _("level:"), context_range_get(new_context), + 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; + if (context_range_set(new_context, response)) + goto fail_set; } _pam_drop(response); } @@ -309,15 +327,17 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) /* 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); + 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, puser_context, newcon, debug)) { - pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", puser_context, newcon); + 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, puser_context, newcon); + send_audit_message(pamh, 0, defaultcon, newcon); free(newcon); goto fail_range; @@ -325,13 +345,13 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) return newcon; } else { - send_audit_message(pamh, 0, puser_context, context_str(new_context)); + 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(puser_context); + return strdup(defaultcon); } /* end while */ return NULL; @@ -340,11 +360,105 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) free(type); _pam_drop(response); context_free (new_context); - send_audit_message(pamh, 0, puser_context, NULL); + send_audit_message(pamh, 0, defaultcon, NULL); fail_range: return NULL; } +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 void security_restorelabel_tty(const pam_handle_t *pamh, const char *tty, security_context_t context) @@ -462,6 +576,7 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int ret = 0; security_context_t* contextlist = NULL; int num_contexts = 0; + int env_params = 0; const char *username = NULL; const void *tty = NULL; char *seuser=NULL; @@ -488,13 +603,16 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, if (strcmp(argv[i], "use_current_range") == 0) { use_current_range = 1; } + if (strcmp(argv[i], "env_params") == 0) { + env_params = 1; + } } if (debug) pam_syslog(pamh, LOG_NOTICE, "Open Session"); - if (select_context && use_current_range) { - pam_syslog(pamh, LOG_ERR, "select_context cannot be used with use_current_range"); + if (select_context && env_params) { + pam_syslog(pamh, LOG_ERR, "select_context cannot be used with env_params"); select_context = 0; } @@ -526,12 +644,17 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, freeconary(contextlist); if (default_user_context == NULL) { pam_syslog(pamh, LOG_ERR, "Out of memory"); - return PAM_AUTH_ERR; + return PAM_BUF_ERR; } + user_context = default_user_context; if (select_context) { - user_context = config_context(pamh, default_user_context, debug); - if (user_context == NULL) { + user_context = config_context(pamh, default_user_context, use_current_range, debug); + } else if (env_params || use_current_range) { + user_context = context_from_env(pamh, default_user_context, env_params, use_current_range, debug); + } + + if (user_context == NULL) { freecon(default_user_context); pam_syslog(pamh, LOG_ERR, "Unable to get valid context for %s", username); @@ -540,8 +663,7 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, return PAM_AUTH_ERR; else return PAM_SUCCESS; - } - } + } } else { user_context = manual_context(pamh,seuser,debug); @@ -555,50 +677,6 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, } } - if (use_current_range && is_selinux_mls_enabled()) { - security_context_t process_context=NULL; - if (getcon(&process_context) == 0) { - context_t pcon, ucon; - char *process_level=NULL; - security_context_t orig_context; - - if (user_context) - orig_context = user_context; - else - orig_context = default_user_context; - - pcon = context_new(process_context); - freecon(process_context); - process_level = strdup(context_range_get(pcon)); - context_free(pcon); - - if (debug) - pam_syslog (pamh, LOG_DEBUG, "process level=%s", process_level); - - ucon = context_new(orig_context); - - context_range_set(ucon, process_level); - free(process_level); - - if (!mls_range_allowed(pamh, orig_context, context_str(ucon), debug)) { - send_text(pamh, _("Requested MLS level not in permitted range"), debug); - /* even if default_user_context is NULL audit that anyway */ - send_audit_message(pamh, 0, default_user_context, context_str(ucon)); - context_free(ucon); - return PAM_AUTH_ERR; - } - - if (debug) - pam_syslog (pamh, LOG_DEBUG, "adjusted context=%s", context_str(ucon)); - - /* replace the user context with the level adjusted one */ - freecon(user_context); - user_context = strdup(context_str(ucon)); - - context_free(ucon); - } - } - if (getexeccon(&prev_user_context)<0) { prev_user_context=NULL; } |