From 72188ec3483744ef54c20245ac4125eb1c67e92e Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Mon, 16 May 2005 11:04:31 +0000 Subject: Relevant BUGIDs: none Purpose of commit: new feature Commit summary: --------------- Add pam_selinux module --- modules/pam_selinux/Makefile | 26 ++ modules/pam_selinux/README | 17 + modules/pam_selinux/pam_selinux.8 | 63 ++++ modules/pam_selinux/pam_selinux.c | 645 ++++++++++++++++++++++++++++++++ modules/pam_selinux/pam_selinux_check.8 | 35 ++ modules/pam_selinux/pam_selinux_check.c | 43 +++ 6 files changed, 829 insertions(+) create mode 100644 modules/pam_selinux/Makefile create mode 100644 modules/pam_selinux/README create mode 100644 modules/pam_selinux/pam_selinux.8 create mode 100644 modules/pam_selinux/pam_selinux.c create mode 100644 modules/pam_selinux/pam_selinux_check.8 create mode 100644 modules/pam_selinux/pam_selinux_check.c (limited to 'modules/pam_selinux') diff --git a/modules/pam_selinux/Makefile b/modules/pam_selinux/Makefile new file mode 100644 index 00000000..a11a7c57 --- /dev/null +++ b/modules/pam_selinux/Makefile @@ -0,0 +1,26 @@ +# +# $Id$ +# + +include ../../Make.Rules + +ifeq ($(HAVE_LIBSELINUX),yes) + +TITLE=pam_selinux +APPLICATION=$(TITLE)_check +APPMODE=04511 +MAN8=$(TITLE).8 $(TITLE)_check.8 +MODULE_SIMPLE_EXTRALIBS=-lselinux + +#MODULE_SIMPLE_INSTALL=$(MAKE) $(APPLICATION); $(INSTALL) -m $(APPMODE) $(APPLICATION) $(FAKEROOT)$(SUPLEMENTED) + +include ../Simple.Rules + +$(APPLICATION): $(APPLICATION).c + $(CC) $(CFLAGS) $(INCLUDE_PAMMODUTILS) -o $@ $^ $(LINK_PAMMODUTILS) -lpam -lpam_misc + +else + +include ../dont_makefile + +endif \ No newline at end of file diff --git a/modules/pam_selinux/README b/modules/pam_selinux/README new file mode 100644 index 00000000..174c4bda --- /dev/null +++ b/modules/pam_selinux/README @@ -0,0 +1,17 @@ +This is pam_selinux, a module for setting the default security context after +login via PAM. + +Background: SELinux provides a mechanism for allowing people to login with +different security contexts. + +The module takes these arguments: +The module takes these arguments: + close Only execute the close_session portion of the module. + debug Log debug messages (with priority DEBUG) to syslog. + nottys Do not set security context on controlling tty + verbose Attempt to tell the user when security context is set. + open Only execute the open_session portion of the module. + +Dan Walsh + + diff --git a/modules/pam_selinux/pam_selinux.8 b/modules/pam_selinux/pam_selinux.8 new file mode 100644 index 00000000..4ccec58c --- /dev/null +++ b/modules/pam_selinux/pam_selinux.8 @@ -0,0 +1,63 @@ +.TH pam_selinux 8 2003/08/26 "Red Hat Linux" "System Administrator's Manual" +.SH NAME +pam_selinux \- set the default security context after login via PAM. +.SH SYNOPSIS +.B session optional /lib/security/pam_selinux.so +.br + +.SH DESCRIPTION +In a nutshell, pam_selinux sets up the default security context for the next execed +shell. + +When an application opens a session using pam_selinux, the shell that gets +executed will be run in the default security context, or if the user chooses +and the pam file allows the selected security context. Also the controlling +tty will have it's security context modified to match the users. + +Adding pam_selinux into a pam file could cause other pam modules to change +their behavior if the exec another application. The close and open option help +mitigate this problem. close option will only cause the close portion of the +pam_selinux to execute, and open will only cause the open portion to run. You +can add pam_selinux to the config file twice. Add the pam_selinux close as the +'first' session entry and open as the 'last' session entry. This way when pam +executes the open pass through the modules, pam_selinux open_session will +happen last. When pam executes the close pass through the modules pam_selinux +close_session will happen first. + +.SH ARGUMENTS +.IP close +Only execute the close_session portion of the module. +.IP debug +turns on debugging via \fBsyslog(3)\fR. +.IP multiple +tells pam_selinux.so to allow the user to select the security context they will +login with, if the user has more than one role. +.IP open +Only execute the open_session portion of the module. +.IP nottys +Do not try to setup the ttys security context. +.IP verbose +attempt to inform the user when security context is set. + +.SH EXAMPLE +\fB/etc/pam.d/some-login-program\fP: +.br +auth required /lib/security/pam_unix.so +.br +session required /lib/security/pam_permit.so +session optional /lib/security/pam_selinux.so +.br + +.SH CAVEATS +Setting the following line will cause the login to fail +auth sufficient /lib/security/pam_selinux.so verbose + + +.SH SEE ALSO +pam_selinux_check(8) + +.SH BUGS +Let's hope not, but if you find any, please email the author. + +.SH AUTHOR +Dan Walsh diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c new file mode 100644 index 00000000..0c05d18b --- /dev/null +++ b/modules/pam_selinux/pam_selinux.c @@ -0,0 +1,645 @@ +/****************************************************************************** + * 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 + * + * 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. + * + */ + +#define PAM_SM_AUTH +#define PAM_SM_SESSION + +#include "../../_pam_aconf.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../_pam_aconf.h" +#include +#include +#include + +#include +#define _(x) gettext(x) + +#ifndef PAM_SELINUX_MAIN +#define MODULE "pam_selinux" + +#include +#include +#include +#include +#include + +static int send_text( struct pam_conv *conv, const char *text, int debug) { + struct pam_message message; + const struct pam_message *messages[] = {&message}; + struct pam_response *responses; + int retval; + + memset(&message, 0, sizeof(message)); + message.msg_style = PAM_TEXT_INFO; + message.msg = text; + if (debug) + syslog(LOG_NOTICE, MODULE ": %s", message.msg); + retval = conv->conv(1, messages, &responses, conv->appdata_ptr); + if (responses) + _pam_drop_reply(responses, 1); + return retval; +} + +/* + * This function sends a message to the user and gets the response. The caller + * is responsible for freeing the responses. + */ +static int query_response( struct pam_conv *conv, const char *text, + struct pam_response **responses, int debug) { + struct pam_message message; + const struct pam_message *messages[] = {&message}; + + memset(&message, 0, sizeof(message)); + message.msg_style = PAM_PROMPT_ECHO_ON; + message.msg = text; + + if (debug) + syslog(LOG_NOTICE, MODULE ": %s", message.msg); + + return conv->conv(1, messages, responses, conv->appdata_ptr); +} + +static security_context_t +select_context (pam_handle_t *pamh, security_context_t* contextlist, + int debug) +{ + struct pam_conv *conv; + + if (pam_get_item(pamh, PAM_CONV, (const void**) &conv) == PAM_SUCCESS && + conv) { + if (conv->conv != NULL) { + struct pam_response *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(conv,text,debug); + free(text); + query_response(conv,_("Do you want to choose a different one? [n]"), + &responses,debug); + if (responses && ((responses[0].resp[0] == 'y') || + (responses[0].resp[0] == 'Y'))) + { + int choice=0; + int i; + char *prompt=_("Enter number of choice: "); + int len=strlen(prompt); + char buf[PATH_MAX]; + + _pam_drop_reply(responses, 1); + 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(conv,text,&responses,debug); + choice = strtol (responses[0].resp, NULL, 10); + _pam_drop_reply(responses, 1); + } + free(text); + return (security_context_t) strdup(contextlist[choice-1]); + } + else if (responses) + _pam_drop_reply(responses, 1); + } else { + if (debug) + syslog(LOG_NOTICE, _("%s: bogus conversation function"),MODULE); + } + } else { + if (debug) + syslog(LOG_NOTICE, _("%s: no conversation function"),MODULE); + } + return (security_context_t) strdup(contextlist[0]); +} + +static security_context_t +manual_context (pam_handle_t *pamh, char *user, int debug) +{ + struct pam_conv *conv; + security_context_t newcon; + context_t new_context; + int mls_enabled = is_selinux_mls_enabled(); + + if (pam_get_item(pamh, PAM_CONV, (const void**) &conv) == PAM_SUCCESS) { + if (conv && conv->conv != NULL) { + struct pam_response *responses; + + while (1) { + query_response(conv, + _("Would you like to enter a security context? [y] "), + &responses,debug); + if ((responses[0].resp[0] == 'y') || (responses[0].resp[0] == 'Y') || + (responses[0].resp[0] == '\0') ) + { + if (mls_enabled) + new_context = context_new ("user:role:type:level"); + else + new_context = context_new ("user:role:type"); + _pam_drop_reply(responses, 1); + + /* 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(conv,_("role: "),&responses,debug); + if (context_role_set (new_context, responses[0].resp)) + { + _pam_drop_reply(responses, 1); + context_free (new_context); + return NULL; + } + _pam_drop_reply(responses, 1); + query_response(conv,_("type: "),&responses,debug); + if (context_type_set (new_context, responses[0].resp)) + { + _pam_drop_reply(responses, 1); + context_free (new_context); + return NULL; + } + _pam_drop_reply(responses, 1); + if (mls_enabled) + { + query_response(conv,_("level: "),&responses,debug); + if (context_range_set (new_context, responses[0].resp)) + { + context_free (new_context); + return NULL; + } + } + /* 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(conv,_("Not a valid security context"),debug); + } + else { + _pam_drop_reply(responses, 1); + return NULL; + } + } /* end while */ + } else { + if (debug) + syslog(LOG_NOTICE, _("%s: bogus conversation function"),MODULE); + } + } else { + if (debug) + syslog(LOG_NOTICE, _("%s: no conversation function"),MODULE); + } + return NULL; +} + +static void security_restorelabel_tty(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) + { + syslog(LOG_NOTICE, + _("Warning! Could not relabel %s with %s, not relabeling.\n"), + ptr, context); + } +} + +static security_context_t security_label_tty(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) + { + syslog(LOG_NOTICE, + _("Warning! Could not get current context for %s, not relabeling."), ptr); + return NULL; + } + if( security_compute_relabel(usercon,prev_context,SECCLASS_CHR_FILE, + &newdev_context)!=0) + { + syslog(LOG_NOTICE, + _("Warning! Could not get new context for %s, not relabeling."), + ptr); + syslog(LOG_NOTICE, "usercon=%s, prev_context=%s\n", usercon, prev_context); + freecon(prev_context); + return NULL; + } + status=setfilecon(ptr,newdev_context); + if (status) + { + syslog(LOG_NOTICE, + _("Warning! Could not relabel %s with %s, not relabeling.%s"), + ptr,newdev_context,strerror(errno)); + 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) +{ + struct pam_conv *conv; + struct pam_message message; + const struct pam_message *messages[] = {&message}; + struct pam_response *responses; + if (pam_get_item(pamh, PAM_CONV, (const void**) &conv) == PAM_SUCCESS) { + if (conv && conv->conv != NULL) { + char text[PATH_MAX]; + + memset(&message, 0, sizeof(message)); + message.msg_style = PAM_TEXT_INFO; + snprintf(text, sizeof(text), msg); + + message.msg = text; + if (debug) + syslog(LOG_NOTICE, MODULE ": %s", message.msg); + conv->conv(1, messages, &responses, conv->appdata_ptr); + if (responses) + _pam_drop_reply(responses, 1); + } else { + if (debug) + syslog(LOG_NOTICE, _("%s: bogus conversation function"),MODULE); + } + } else { + if (debug) + syslog(LOG_NOTICE,_("%s: no conversation function"),MODULE); + } +} + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + /* Fail by default. */ + return PAM_AUTH_ERR; +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return PAM_SUCCESS; +} + +PAM_EXTERN int +pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + int i, debug = 0, ttys=1, has_tty=isatty(0), verbose=0, multiple=0, close_session=0; + int ret=0; + security_context_t* contextlist=NULL; + int num_contexts = 0; + char *username=NULL; + const char *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) + syslog(LOG_NOTICE, MODULE ": %s", "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, (const void**)&username) != PAM_SUCCESS || + username == NULL) { + return PAM_AUTH_ERR; + } + 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) { + syslog (LOG_ERR, _("Unable to get valid context for %s"), username); + return PAM_AUTH_ERR; + } + } else { + syslog (LOG_ERR, _("Unable to get valid context for %s, No valid tty"), 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, (const void**)&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(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) { + syslog(LOG_ERR, _("Error! Unable to set %s executable context %s."), + username, user_context); + freecon(user_context); + return PAM_AUTH_ERR; + } else { + if (debug) + syslog(LOG_NOTICE, _("%s: set %s security context to %s"),MODULE, + username, user_context); + } + freecon(user_context); + + return PAM_SUCCESS; +} + +PAM_EXTERN int +pam_sm_close_session(pam_handle_t *pamh, int flags, 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) + syslog(LOG_NOTICE, MODULE ": %s", "Close Session"); + + if (open_session) + return PAM_SUCCESS; + + if (ttyn) { + if (debug) + syslog(LOG_NOTICE, MODULE ":Restore tty %s -> %s", ttyn,ttyn_context); + + security_restorelabel_tty(ttyn,ttyn_context); + freecon(ttyn_context); + free(ttyn); + ttyn=NULL; + } + status=setexeccon(prev_user_context); + freecon(prev_user_context); + if (status) { + syslog(LOG_ERR, _("Error! Unable to set executable context %s."), + prev_user_context); + return PAM_AUTH_ERR; + } + + if (debug) + syslog(LOG_NOTICE, _("%s: setcontext back to orginal"),MODULE); + + return PAM_SUCCESS; +} + +#else /* PAM_SELINUX_MAIN */ + +/************************************************************************ + * + * All PAM code goes in this section. + * + ************************************************************************/ + +#include /* for getuid(), exit(), getopt() */ +#include +#include /* for wait() */ + +#include /* for PAM functions */ +#include /* for misc_conv PAM utility function */ + +#define SERVICE_NAME "pam_selinux_check" /* the name of this program for PAM */ + /* The file containing the context to run + * the scripts under. */ +int authenticate_via_pam( const char *user , pam_handle_t **pamh); + +/* authenticate_via_pam() + * + * in: user + * out: nothing + * return: value condition + * ----- --------- + * 1 pam thinks that the user authenticated themselves properly + * 0 otherwise + * + * this function uses pam to authenticate the user running this + * program. this is the only function in this program that makes pam + * calls. + * + */ + +int authenticate_via_pam( const char *user , pam_handle_t **pamh) { + + struct pam_conv *conv; + int result = 0; /* our result, set to 0 (not authenticated) by default */ + + /* this is a jump table of functions for pam to use when it wants to * + * communicate with the user. we'll be using misc_conv(), which is * + * provided for us via pam_misc.h. */ + struct pam_conv pam_conversation = { + misc_conv, + NULL + }; + conv = &pam_conversation; + + + /* make `p_pam_handle' a valid pam handle so we can use it when * + * calling pam functions. */ + if( PAM_SUCCESS != pam_start( SERVICE_NAME, + user, + conv, + pamh ) ) { + fprintf( stderr, _("failed to initialize PAM\n") ); + exit( -1 ); + } + + if( PAM_SUCCESS != pam_set_item(*pamh, PAM_RUSER, user)) + { + fprintf( stderr, _("failed to pam_set_item()\n") ); + exit( -1 ); + } + + /* Ask PAM to authenticate the user running this program */ + if( PAM_SUCCESS == pam_authenticate(*pamh,0) ) { + if ( PAM_SUCCESS == pam_open_session(*pamh, 0) ) + result = 1; /* user authenticated OK! */ + } + return( result ); + +} /* authenticate_via_pam() */ + +int main(int argc, char **argv) { + pam_handle_t *pamh; + int childPid; + + if (!authenticate_via_pam(argv[1],&pamh)) + exit(-1); + + childPid = fork(); + if (childPid < 0) { + int errsv = errno; + + /* error in fork() */ + fprintf(stderr, _("login: failure forking: %s"), strerror(errsv)); + pam_close_session(pamh, 0); + /* We're done with PAM. Free `pam_handle'. */ + pam_end( pamh, PAM_SUCCESS ); + exit(0); + } + if (childPid) { + close(0); close(1); close(2); + struct sigaction sa; + memset(&sa,0,sizeof(sa)); + sa.sa_handler = SIG_IGN; + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + while(wait(NULL) == -1 && errno == EINTR) /**/ ; + openlog("login", LOG_ODELAY, LOG_AUTHPRIV); + pam_close_session(pamh, 0); + /* We're done with PAM. Free `pam_handle'. */ + pam_end( pamh, PAM_SUCCESS ); + exit(0); + } + argv[0]="/bin/sh"; + argv[1]=NULL; + + /* NOTE: The environment has not been sanitized. LD_PRELOAD and other fun + * things could be set. */ + execv("/bin/sh",argv); + fprintf(stderr,"Failure\n"); + return 0; +} +#endif diff --git a/modules/pam_selinux/pam_selinux_check.8 b/modules/pam_selinux/pam_selinux_check.8 new file mode 100644 index 00000000..5151be7d --- /dev/null +++ b/modules/pam_selinux/pam_selinux_check.8 @@ -0,0 +1,35 @@ +.TH pam_selinux_check 8 2002/05/23 "Red Hat Linux" "System Administrator's Manual" +.SH NAME +pam_selinux_check \- login program to test pam_selinux_check +.SH SYNOPSIS +.B pam_selinux_check [user] +.br + +.SH DESCRIPTION +With no arguments, +.B pam_selinux_check +will prompt for user + +.SH OPTIONS +.IP target_user +The user to login as. + +.SH DIAGNOSTICS +You must setup a /etc/pam.d/pam_selinux_check file, in order for the check to work. + +When checking if a selinux is valid, +.B pam_selinux_check +returns an exit code of 0 for success and > 0 on error: + +.nf +1: Authentication failure +.fi + +.SH SEE ALSO +pam_selinux(8) + +.SH BUGS +Let's hope not, but if you find any, please email the author. + +.SH AUTHOR +Dan Walsh diff --git a/modules/pam_selinux/pam_selinux_check.c b/modules/pam_selinux/pam_selinux_check.c new file mode 100644 index 00000000..f2aa795e --- /dev/null +++ b/modules/pam_selinux/pam_selinux_check.c @@ -0,0 +1,43 @@ +/****************************************************************************** + * 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 + * + * 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. + * + */ + +#define PAM_SELINUX_MAIN 1 +#include "pam_selinux.c" + -- cgit v1.2.3