aboutsummaryrefslogtreecommitdiff
path: root/modules/pam_selinux/pam_selinux.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_selinux/pam_selinux.c')
-rw-r--r--modules/pam_selinux/pam_selinux.c482
1 files changed, 0 insertions, 482 deletions
diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c
deleted file mode 100644
index 5aaec2e7..00000000
--- a/modules/pam_selinux/pam_selinux.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/******************************************************************************
- * A module for Linux-PAM that will set the default security context after login
- * via PAM.
- *
- * Copyright (c) 2003 Red Hat, Inc.
- * Written by Dan Walsh <dwalsh@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>
-
-#define PAM_SM_AUTH
-#define PAM_SM_SESSION
-
-#include <security/pam_modules.h>
-#include <security/_pam_macros.h>
-#include <security/pam_modutil.h>
-#include <security/pam_ext.h>
-
-#include <selinux/selinux.h>
-#include <selinux/get_context_list.h>
-#include <selinux/flask.h>
-#include <selinux/selinux.h>
-#include <selinux/context.h>
-
-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,
- char **responses, int debug)
-{
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "%s", text);
-
- return pam_prompt (pamh, PAM_PROMPT_ECHO_ON, responses, "%s", text);
-}
-
-static security_context_t
-select_context (pam_handle_t *pamh, security_context_t* contextlist,
- int debug)
-{
- char *responses;
- char *text=calloc(PATH_MAX,1);
-
- if (text == NULL)
- return (security_context_t) strdup(contextlist[0]);
-
- snprintf(text, PATH_MAX,
- _("Your default context is %s. \n"), contextlist[0]);
- send_text(pamh,text,debug);
- free(text);
- query_response(pamh,_("Do you want to choose a different one? [n]"),
- &responses,debug);
- if (responses && ((responses[0] == 'y') ||
- (responses[0] == 'Y')))
- {
- int choice=0;
- int i;
- const char *prompt=_("Enter number of choice: ");
- int len=strlen(prompt);
- char buf[PATH_MAX];
-
- _pam_drop(responses);
- for (i = 0; contextlist[i]; i++) {
- len+=strlen(contextlist[i]) + 10;
- }
- text=calloc(len,1);
- for (i = 0; contextlist[i]; i++) {
- snprintf(buf, PATH_MAX,
- "[%d] %s\n", i+1, contextlist[i]);
- strncat(text,buf,len);
- }
- strcat(text,prompt);
- while ((choice < 1) || (choice > i)) {
- query_response(pamh,text,&responses,debug);
- choice = strtol (responses, NULL, 10);
- _pam_drop(responses);
- }
- free(text);
- return (security_context_t) strdup(contextlist[choice-1]);
- }
- else if (responses)
- _pam_drop(responses);
-
- return (security_context_t) strdup(contextlist[0]);
-}
-
-static security_context_t
-manual_context (pam_handle_t *pamh, const char *user, int debug)
-{
- security_context_t newcon;
- context_t new_context;
- int mls_enabled = is_selinux_mls_enabled();
-
- char *responses;
-
- while (1) {
- query_response(pamh,
- _("Would you like to enter a security context? [y] "),
- &responses,debug);
- if ((responses[0] == 'y') || (responses[0] == 'Y') ||
- (responses[0] == '\0') )
- {
- if (mls_enabled)
- new_context = context_new ("user:role:type:level");
- else
- new_context = context_new ("user:role:type");
- _pam_drop(responses);
-
- /* Allow the user to enter each field of the context individually */
- if (context_user_set (new_context, user))
- {
- context_free (new_context);
- return NULL;
- }
- query_response(pamh,_("role: "),&responses,debug);
- if (context_role_set (new_context, responses))
- {
- _pam_drop(responses);
- context_free (new_context);
- return NULL;
- }
- _pam_drop(responses);
- query_response(pamh,_("type: "),&responses,debug);
- if (context_type_set (new_context, responses))
- {
- _pam_drop(responses);
- context_free (new_context);
- return NULL;
- }
- _pam_drop(responses);
- if (mls_enabled)
- {
- query_response(pamh,_("level: "),&responses,debug);
- if (context_range_set (new_context, responses))
- {
- _pam_drop(responses);
- context_free (new_context);
- return NULL;
- }
- _pam_drop(responses);
- }
- /* 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);
- }
- else {
- _pam_drop(responses);
- return NULL;
- }
- } /* end while */
-
- return NULL;
-}
-
-static void
-security_restorelabel_tty(const pam_handle_t *pamh,
- const char *tty, security_context_t context)
-{
- char ttybuf[PATH_MAX];
- const char *ptr;
-
- if (context==NULL)
- return;
-
- if(strncmp("/dev/", tty, 5)) {
- snprintf(ttybuf,sizeof(ttybuf),"/dev/%s",tty);
- ptr = ttybuf;
- }
- else
- ptr = tty;
-
- if (setfilecon(ptr, context) && errno != ENOENT)
- {
- pam_syslog(pamh, LOG_NOTICE,
- "Warning! Could not relabel %s with %s, not relabeling: %m",
- ptr, context);
- }
-}
-
-static security_context_t
-security_label_tty(pam_handle_t *pamh, char *tty,
- security_context_t usercon)
-{
- char ttybuf[PATH_MAX];
- int status=0;
- security_context_t newdev_context=NULL; /* The new context of a device */
- security_context_t prev_context=NULL; /* The new context of a device */
- const char *ptr;
-
- if(strncmp("/dev/", tty, 5))
- {
- snprintf(ttybuf,sizeof(ttybuf),"/dev/%s",tty);
- ptr = ttybuf;
- }
- else
- ptr = tty;
-
- if (getfilecon(ptr, &prev_context) < 0)
- {
- if(errno != ENOENT)
- pam_syslog(pamh, LOG_NOTICE,
- "Warning! Could not get current context for %s, not relabeling: %m",
- ptr);
- return NULL;
- }
- if( security_compute_relabel(usercon,prev_context,SECCLASS_CHR_FILE,
- &newdev_context)!=0)
- {
- pam_syslog(pamh, LOG_NOTICE,
- "Warning! Could not get new context for %s, not relabeling: %m",
- ptr);
- pam_syslog(pamh, LOG_NOTICE,
- "usercon=%s, prev_context=%s", usercon, prev_context);
- freecon(prev_context);
- return NULL;
- }
- status=setfilecon(ptr,newdev_context);
- if (status)
- {
- pam_syslog(pamh, LOG_NOTICE,
- "Warning! Could not relabel %s with %s, not relabeling: %m",
- ptr,newdev_context);
- freecon(prev_context);
- prev_context=NULL;
- }
- freecon(newdev_context);
- return prev_context;
-}
-
-static security_context_t user_context=NULL;
-static security_context_t prev_user_context=NULL;
-static security_context_t ttyn_context=NULL; /* The current context of ttyn device */
-static int selinux_enabled=0;
-static char *ttyn=NULL;
-
-/* Tell the user that access has been granted. */
-static void
-verbose_message(pam_handle_t *pamh, char *msg, int debug)
-{
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, msg);
-
- pam_info (pamh, "%s", msg);
-}
-
-PAM_EXTERN 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;
-}
-
-PAM_EXTERN int
-pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED,
- int argc UNUSED, const char **argv UNUSED)
-{
- return PAM_SUCCESS;
-}
-
-PAM_EXTERN int
-pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED,
- int argc, const char **argv)
-{
- int i, debug = 0, ttys=1, has_tty=isatty(0);
- int verbose=0, multiple=0, close_session=0;
- int ret = 0;
- security_context_t* contextlist = NULL;
- int num_contexts = 0;
- const void *username = NULL;
- const void *tty = NULL;
-
- /* Parse arguments. */
- for (i = 0; i < argc; i++) {
- if (strcmp(argv[i], "debug") == 0) {
- debug = 1;
- }
- if (strcmp(argv[i], "nottys") == 0) {
- ttys = 0;
- }
- if (strcmp(argv[i], "verbose") == 0) {
- verbose = 1;
- }
- if (strcmp(argv[i], "multiple") == 0) {
- multiple = 1;
- }
- if (strcmp(argv[i], "close") == 0) {
- close_session = 1;
- }
- }
-
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "Open Session");
-
- /* this module is only supposed to execute close_session */
- if (close_session)
- return PAM_SUCCESS;
-
- if (!(selinux_enabled = is_selinux_enabled()>0) )
- return PAM_SUCCESS;
-
- if (pam_get_item(pamh, PAM_USER, &username) != PAM_SUCCESS ||
- username == NULL) {
- return PAM_USER_UNKNOWN;
- }
- num_contexts = get_ordered_context_list(username, 0, &contextlist);
- if (num_contexts > 0) {
- if (multiple && (num_contexts > 1) && has_tty) {
- user_context = select_context(pamh,contextlist, debug);
- freeconary(contextlist);
- } else {
- user_context = (security_context_t) strdup(contextlist[0]);
- freeconary(contextlist);
- }
- } else {
- if (has_tty) {
- user_context = manual_context(pamh,username,debug);
- if (user_context == NULL) {
- pam_syslog (pamh, LOG_ERR, "Unable to get valid context for %s",
- (const char *)username);
- return PAM_AUTH_ERR;
- }
- } else {
- pam_syslog (pamh, LOG_ERR,
- "Unable to get valid context for %s, No valid tty",
- (const char *)username);
- return PAM_AUTH_ERR;
- }
- }
- if (getexeccon(&prev_user_context)<0) {
- prev_user_context=NULL;
- }
- if (ttys) {
- /* Get the name of the terminal. */
- if (pam_get_item(pamh, PAM_TTY, &tty) != PAM_SUCCESS) {
- tty = NULL;
- }
-
- if ((tty == NULL) || (strlen(tty) == 0) ||
- strcmp(tty, "ssh") == 0 || strncmp(tty, "NODEV", 5) == 0) {
- tty = ttyname(STDIN_FILENO);
- if ((tty == NULL) || (strlen(tty) == 0)) {
- tty = ttyname(STDOUT_FILENO);
- }
- if ((tty == NULL) || (strlen(tty) == 0)) {
- tty = ttyname(STDERR_FILENO);
- }
- }
- }
- if(ttys && tty ) {
- ttyn=strdup(tty);
- ttyn_context=security_label_tty(pamh,ttyn,user_context);
- }
- ret = setexeccon(user_context);
- if (ret==0 && verbose) {
- char msg[PATH_MAX];
- snprintf(msg, sizeof(msg),
- _("Security Context %s Assigned"), user_context);
- verbose_message(pamh, msg, debug);
- }
- if (ret) {
- pam_syslog(pamh, LOG_ERR,
- "Error! Unable to set %s executable context %s.",
- (const char *)username, user_context);
- freecon(user_context);
- return PAM_AUTH_ERR;
- } else {
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "set %s security context to %s",
- (const char *)username, user_context);
- }
- freecon(user_context);
-
- return PAM_SUCCESS;
-}
-
-PAM_EXTERN int
-pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED,
- int argc, const char **argv)
-{
- int i, debug = 0,status=0, open_session=0;
- if (! (selinux_enabled ))
- return PAM_SUCCESS;
-
- /* 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");
-
- if (open_session)
- return PAM_SUCCESS;
-
- if (ttyn) {
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "Restore tty %s -> %s",
- ttyn,ttyn_context);
-
- security_restorelabel_tty(pamh,ttyn,ttyn_context);
- freecon(ttyn_context);
- free(ttyn);
- ttyn=NULL;
- }
- status=setexeccon(prev_user_context);
- freecon(prev_user_context);
- if (status) {
- pam_syslog(pamh, LOG_ERR, "Error! Unable to set executable context %s.",
- prev_user_context);
- return PAM_AUTH_ERR;
- }
-
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "setcontext back to orginal");
-
- return PAM_SUCCESS;
-}