123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818 |
- /******************************************************************************
- * A module for Linux-PAM that will set the default security context after login
- * via PAM.
- *
- * 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
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * ALTERNATIVELY, this product may be distributed under the terms of
- * the GNU Public License, in which case the provisions of the GPL are
- * required INSTEAD OF the above restrictions. (This clause is
- * necessary due to a potential bad interaction between the GPL and
- * the restrictions contained in a BSD-style copyright.)
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "config.h"
- #include <errno.h>
- #include <limits.h>
- #include <pwd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <syslog.h>
- #include <security/pam_modules.h>
- #include <security/_pam_macros.h>
- #include <security/pam_modutil.h>
- #include <security/pam_ext.h>
- #include "pam_inline.h"
- #include <selinux/selinux.h>
- #include <selinux/get_context_list.h>
- #include <selinux/context.h>
- #include <selinux/get_default_type.h>
- #ifdef HAVE_LIBAUDIT
- #include <libaudit.h>
- #include <sys/select.h>
- #endif
- /* Send audit message */
- static void
- send_audit_message(const pam_handle_t *pamh, int success, const char *default_context,
- const char *selected_context)
- {
- #ifdef HAVE_LIBAUDIT
- char *msg = NULL;
- int audit_fd = audit_open();
- char *default_raw = NULL;
- char *selected_raw = NULL;
- const void *tty = NULL, *rhost = NULL;
- if (audit_fd < 0) {
- if (errno == EINVAL || errno == EPROTONOSUPPORT ||
- errno == EAFNOSUPPORT) {
- goto fallback; /* No audit support in kernel */
- }
- pam_syslog(pamh, LOG_ERR, "Error connecting to audit system: %m");
- goto fallback;
- }
- (void)pam_get_item(pamh, PAM_TTY, &tty);
- (void)pam_get_item(pamh, PAM_RHOST, &rhost);
- if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
- pam_syslog(pamh, LOG_ERR, "Error translating default context '%s'.", default_context);
- default_raw = NULL;
- }
- if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
- pam_syslog(pamh, LOG_ERR, "Error translating selected context '%s'.", selected_context);
- selected_raw = NULL;
- }
- if (asprintf(&msg, "pam: default-context=%s selected-context=%s",
- default_raw ? default_raw : (default_context ? default_context : "?"),
- selected_raw ? selected_raw : (selected_context ? selected_context : "?")) < 0) {
- msg = NULL; /* asprintf leaves msg in undefined state on failure */
- pam_syslog(pamh, LOG_ERR, "Error allocating memory.");
- goto fallback;
- }
- if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
- msg, rhost, NULL, tty, success) <= 0) {
- pam_syslog(pamh, LOG_ERR, "Error sending audit message: %m");
- goto fallback;
- }
- goto cleanup;
- fallback:
- #endif /* HAVE_LIBAUDIT */
- pam_syslog(pamh, LOG_NOTICE, "pam: default-context=%s selected-context=%s success %d",
- default_context, selected_context, success);
- #ifdef HAVE_LIBAUDIT
- cleanup:
- free(msg);
- freecon(default_raw);
- freecon(selected_raw);
- if (audit_fd >= 0)
- close(audit_fd);
- #endif /* HAVE_LIBAUDIT */
- }
- static int
- send_text (pam_handle_t *pamh, const char *text, int debug)
- {
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "%s", text);
- return pam_info (pamh, "%s", text);
- }
- /*
- * This function sends a message to the user and gets the response. The caller
- * is responsible for freeing the responses.
- */
- static int
- query_response (pam_handle_t *pamh, const char *text, const char *def,
- char **response, int debug)
- {
- int rc;
- if (def)
- rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, response, "%s [%s] ", text, def);
- else
- rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, response, "%s ", text);
- if (*response == NULL) {
- rc = PAM_CONV_ERR;
- }
- if (rc != PAM_SUCCESS) {
- pam_syslog(pamh, LOG_WARNING, "No response to query: %s", text);
- } else if (debug)
- pam_syslog(pamh, LOG_NOTICE, "%s %s", text, *response);
- return rc;
- }
- static char *
- config_context (pam_handle_t *pamh, const char *defaultcon, int use_current_range, int debug)
- {
- char *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, _("The default security context is %s."), 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,
- _("There is no default type for role %s."), 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(type);
- }
- }
- _pam_drop(response);
- if (mls_enabled)
- {
- if (use_current_range) {
- char *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 &&
- selinux_check_access(defaultcon, newcon, "context", "contains", NULL) != 0) {
- 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,_("This is 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 char *
- context_from_env (pam_handle_t *pamh, const char *defaultcon, int env_params, int use_current_range, int debug)
- {
- char *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;
- int fail = 1;
- 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) {
- char *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);
- 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 &&
- selinux_check_access(defaultcon, newcon, "context", "contains", NULL) != 0) {
- pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon);
- goto fail_set;
- }
- fail = 0;
- fail_set:
- free(type);
- context_free(my_context);
- context_free(new_context);
- if (fail) {
- send_audit_message(pamh, 0, defaultcon, newcon);
- freecon(newcon);
- newcon = NULL;
- }
- return newcon;
- }
- #define DATANAME "pam_selinux_context"
- typedef struct {
- char *exec_context;
- char *prev_exec_context;
- char *default_user_context;
- char *tty_context;
- char *prev_tty_context;
- char *tty_path;
- } module_data_t;
- static void
- free_module_data(module_data_t *data)
- {
- free(data->tty_path);
- freecon(data->prev_tty_context);
- freecon(data->tty_context);
- freecon(data->default_user_context);
- freecon(data->prev_exec_context);
- if (data->exec_context != data->default_user_context)
- freecon(data->exec_context);
- memset(data, 0, sizeof(*data));
- free(data);
- }
- static void
- cleanup(pam_handle_t *pamh UNUSED, void *data, int err UNUSED)
- {
- free_module_data(data);
- }
- static const module_data_t *
- get_module_data(const pam_handle_t *pamh)
- {
- const void *data;
- return (pam_get_data(pamh, DATANAME, &data) == PAM_SUCCESS) ? data : NULL;
- }
- static const char *
- get_item(const pam_handle_t *pamh, int item_type)
- {
- const void *item;
- return (pam_get_item(pamh, item_type, &item) == PAM_SUCCESS) ? item : NULL;
- }
- static int
- set_exec_context(const pam_handle_t *pamh, const char *context)
- {
- if (setexeccon(context) == 0)
- return 0;
- pam_syslog(pamh, LOG_ERR, "Setting executable context \"%s\" failed: %m",
- context ? context : "");
- return -1;
- }
- static int
- set_file_context(const pam_handle_t *pamh, const char *context,
- const char *file)
- {
- if (!file)
- return 0;
- if (setfilecon(file, context) == 0 || errno == ENOENT)
- return 0;
- pam_syslog(pamh, LOG_ERR, "Setting file context \"%s\" failed for %s: %m",
- context ? context : "", file);
- return -1;
- }
- static int
- compute_exec_context(pam_handle_t *pamh, module_data_t *data,
- int select_context, int use_current_range,
- int env_params, int debug)
- {
- const char *username;
- #ifdef HAVE_GETSEUSER
- const char *service;
- #endif
- char *seuser = NULL;
- char *level = NULL;
- char **contextlist = NULL;
- int num_contexts = 0;
- const struct passwd *pwd;
- if (!(username = get_item(pamh, PAM_USER))) {
- pam_syslog(pamh, LOG_ERR, "Cannot obtain the user name");
- return PAM_USER_UNKNOWN;
- }
- if ((pwd = pam_modutil_getpwnam(pamh, username)) != NULL) {
- username = pwd->pw_name;
- } /* ignore error and keep using original username */
- /* compute execute context */
- #ifdef HAVE_GETSEUSER
- if (!(service = get_item(pamh, PAM_SERVICE))) {
- pam_syslog(pamh, LOG_ERR, "Cannot obtain the service name");
- return PAM_SESSION_ERR;
- }
- if (getseuser(username, service, &seuser, &level) == 0) {
- #else
- if (getseuserbyname(username, &seuser, &level) == 0) {
- #endif
- num_contexts = get_ordered_context_list_with_level(seuser, level, NULL,
- &contextlist);
- if (debug)
- pam_syslog(pamh, LOG_DEBUG, "Username= %s SELinux User= %s Level= %s",
- username, seuser, level);
- free(level);
- }
- if (num_contexts > 0) {
- free(seuser);
- data->default_user_context = strdup(contextlist[0]);
- freeconary(contextlist);
- if (!data->default_user_context) {
- pam_syslog(pamh, LOG_CRIT, "Out of memory");
- return PAM_BUF_ERR;
- }
- data->exec_context = data->default_user_context;
- if (select_context)
- data->exec_context = config_context(pamh, data->default_user_context,
- use_current_range, debug);
- else if (env_params || use_current_range)
- data->exec_context = context_from_env(pamh, data->default_user_context,
- env_params, use_current_range,
- debug);
- }
- if (!data->exec_context) {
- pam_syslog(pamh, LOG_ERR, "Unable to get valid context for %s", username);
- pam_prompt(pamh, PAM_ERROR_MSG, NULL,
- _("A valid context for %s could not be obtained."), username);
- }
- if (getexeccon(&data->prev_exec_context) < 0)
- data->prev_exec_context = NULL;
- return PAM_SUCCESS;
- }
- static int
- compute_tty_context(const pam_handle_t *pamh, module_data_t *data)
- {
- const char *tty = get_item(pamh, PAM_TTY);
- security_class_t tclass;
- if (!tty || !*tty || !strcmp(tty, "ssh")
- || pam_str_skip_prefix(tty, "NODEV") != NULL) {
- tty = ttyname(STDIN_FILENO);
- if (!tty || !*tty)
- tty = ttyname(STDOUT_FILENO);
- if (!tty || !*tty)
- tty = ttyname(STDERR_FILENO);
- if (!tty || !*tty)
- return PAM_SUCCESS;
- }
- if (pam_str_skip_prefix(tty, "/dev/") == NULL) {
- if (asprintf(&data->tty_path, "%s%s", "/dev/", tty) < 0)
- data->tty_path = NULL;
- } else {
- data->tty_path = strdup(tty);
- }
- if (!data->tty_path) {
- pam_syslog(pamh, LOG_CRIT, "Out of memory");
- return PAM_BUF_ERR;
- }
- if (getfilecon(data->tty_path, &data->prev_tty_context) < 0) {
- data->prev_tty_context = NULL;
- if (errno == ENOENT) {
- free(data->tty_path);
- data->tty_path = NULL;
- return PAM_SUCCESS;
- }
- pam_syslog(pamh, LOG_ERR, "Failed to get current context for %s: %m",
- data->tty_path);
- return (security_getenforce() == 1) ? PAM_SESSION_ERR : PAM_SUCCESS;
- }
- tclass = string_to_security_class("chr_file");
- if (tclass == 0) {
- pam_syslog(pamh, LOG_ERR, "Failed to get chr_file security class");
- freecon(data->prev_tty_context);
- data->prev_tty_context = NULL;
- free(data->tty_path);
- data->tty_path = NULL;
- return (security_getenforce() == 1) ? PAM_SESSION_ERR : PAM_SUCCESS;
- }
- if (security_compute_relabel(data->exec_context, data->prev_tty_context,
- tclass, &data->tty_context)) {
- data->tty_context = NULL;
- pam_syslog(pamh, LOG_ERR, "Failed to compute new context for %s: %m",
- data->tty_path);
- freecon(data->prev_tty_context);
- data->prev_tty_context = NULL;
- free(data->tty_path);
- data->tty_path = NULL;
- return (security_getenforce() == 1) ? PAM_SESSION_ERR : PAM_SUCCESS;
- }
- return PAM_SUCCESS;
- }
- static int
- restore_context(const pam_handle_t *pamh, const module_data_t *data, int debug)
- {
- int err;
- if (!data) {
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "No context to restore");
- return PAM_SUCCESS;
- }
- if (debug && data->tty_path)
- pam_syslog(pamh, LOG_NOTICE,
- "Restore file context of tty %s: [%s] -> [%s]",
- data->tty_path,
- data->tty_context ? data->tty_context : "",
- data->prev_tty_context ? data->prev_tty_context : "");
- err = set_file_context(pamh, data->prev_tty_context, data->tty_path);
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "Restore executable context: [%s] -> [%s]",
- data->exec_context,
- data->prev_exec_context ? data->prev_exec_context : "");
- err |= set_exec_context(pamh, data->prev_exec_context);
- if (err && security_getenforce() == 1)
- return PAM_SESSION_ERR;
- return PAM_SUCCESS;
- }
- static int
- set_context(pam_handle_t *pamh, const module_data_t *data,
- int debug, int verbose)
- {
- int rc, err;
- if (debug && data->tty_path)
- pam_syslog(pamh, LOG_NOTICE, "Set file context of tty %s: [%s] -> [%s]",
- data->tty_path,
- data->prev_tty_context ? data->prev_tty_context : "",
- data->tty_context ? data->tty_context : "");
- err = set_file_context(pamh, data->tty_context, data->tty_path);
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "Set executable context: [%s] -> [%s]",
- data->prev_exec_context ? data->prev_exec_context : "",
- data->exec_context);
- rc = set_exec_context(pamh, data->exec_context);
- err |= rc;
- send_audit_message(pamh, !rc, data->default_user_context, data->exec_context);
- if (verbose && !rc) {
- char msg[PATH_MAX];
- snprintf(msg, sizeof(msg),
- _("Security context %s has been assigned."), data->exec_context);
- send_text(pamh, msg, debug);
- }
- #ifdef HAVE_SETKEYCREATECON
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "Set key creation context to %s",
- data->exec_context ? data->exec_context : "");
- rc = setkeycreatecon(data->exec_context);
- err |= rc;
- if (rc)
- pam_syslog(pamh, LOG_ERR, "Setting key creation context %s failed: %m",
- data->exec_context ? data->exec_context : "");
- if (verbose && !rc) {
- char msg[PATH_MAX];
- snprintf(msg, sizeof(msg),
- _("Key creation context %s has been assigned."), data->exec_context);
- send_text(pamh, msg, debug);
- }
- #endif
- if (err && security_getenforce() == 1)
- return PAM_SESSION_ERR;
- return PAM_SUCCESS;
- }
- static int
- create_context(pam_handle_t *pamh, int argc, const char **argv,
- int debug, int verbose)
- {
- int i;
- int ttys = 1;
- int select_context = 0;
- int use_current_range = 0;
- int env_params = 0;
- module_data_t *data;
- /* Parse arguments. */
- for (i = 0; i < argc; i++) {
- if (strcmp(argv[i], "nottys") == 0) {
- ttys = 0;
- }
- if (strcmp(argv[i], "select_context") == 0) {
- select_context = 1;
- }
- if (strcmp(argv[i], "use_current_range") == 0) {
- use_current_range = 1;
- }
- if (strcmp(argv[i], "env_params") == 0) {
- env_params = 1;
- }
- }
- if (is_selinux_enabled() <= 0) {
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "SELinux is not enabled");
- return PAM_SUCCESS;
- }
- if (select_context && env_params) {
- pam_syslog(pamh, LOG_ERR,
- "select_context cannot be used with env_params");
- select_context = 0;
- }
- if (!(data = calloc(1, sizeof(*data)))) {
- pam_syslog(pamh, LOG_CRIT, "Out of memory");
- return PAM_BUF_ERR;
- }
- i = compute_exec_context(pamh, data, select_context, use_current_range,
- env_params, debug);
- if (i != PAM_SUCCESS) {
- free_module_data(data);
- return i;
- }
- if (!data->exec_context) {
- free_module_data(data);
- return (security_getenforce() == 1) ? PAM_SESSION_ERR : PAM_SUCCESS;
- }
- if (ttys && (i = compute_tty_context(pamh, data)) != PAM_SUCCESS) {
- free_module_data(data);
- return i;
- }
- if ((i = pam_set_data(pamh, DATANAME, data, cleanup)) != PAM_SUCCESS) {
- pam_syslog(pamh, LOG_ERR, "Error saving context: %m");
- free_module_data(data);
- return i;
- }
- return set_context(pamh, data, debug, verbose);
- }
- int
- pam_sm_authenticate(pam_handle_t *pamh UNUSED, int flags UNUSED,
- int argc UNUSED, const char **argv UNUSED)
- {
- /* Fail by default. */
- return PAM_AUTH_ERR;
- }
- int
- pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED,
- int argc UNUSED, const char **argv UNUSED)
- {
- return PAM_SUCCESS;
- }
- int
- pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED,
- int argc, const char **argv)
- {
- const module_data_t *data;
- int i, debug = 0, verbose = 0, close_session = 0, restore = 0;
- /* Parse arguments. */
- for (i = 0; i < argc; i++) {
- if (strcmp(argv[i], "debug") == 0) {
- debug = 1;
- }
- if (strcmp(argv[i], "verbose") == 0) {
- verbose = 1;
- }
- if (strcmp(argv[i], "close") == 0) {
- close_session = 1;
- }
- if (strcmp(argv[i], "restore") == 0) {
- restore = 1;
- }
- }
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "Open Session");
- /* Is this module supposed to execute close_session only? */
- if (close_session)
- return PAM_SUCCESS;
- data = get_module_data(pamh);
- /* Is this module supposed only to restore original context? */
- if (restore)
- return restore_context(pamh, data, debug);
- /* If there is a saved context, this module is supposed to set it again. */
- return data ? set_context(pamh, data, debug, verbose) :
- create_context(pamh, argc, argv, debug, verbose);
- }
- int
- pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED,
- int argc, const char **argv)
- {
- int i, debug = 0, open_session = 0;
- /* Parse arguments. */
- for (i = 0; i < argc; i++) {
- if (strcmp(argv[i], "debug") == 0) {
- debug = 1;
- }
- if (strcmp(argv[i], "open") == 0) {
- open_session = 1;
- }
- }
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "Close Session");
- /* Is this module supposed to execute open_session only? */
- if (open_session)
- return PAM_SUCCESS;
- /* Restore original context. */
- return restore_context(pamh, get_module_data(pamh), debug);
- }
|