summaryrefslogtreecommitdiff
path: root/modules/pam_selinux
diff options
context:
space:
mode:
authorSteve Langasek <steve.langasek@ubuntu.com>2019-01-03 17:53:41 -0800
committerSteve Langasek <steve.langasek@ubuntu.com>2019-01-03 18:17:08 -0800
commit212b52cf29c06cc209bc8ac0540dbab1acdf1464 (patch)
tree58da0bf39f5c4122e4a1b4da20fdeea52b97a671 /modules/pam_selinux
parent9c52e721044e7501c3d4567b36d222dc7326224a (diff)
parent56c8282d128fb484ffc77dff73abf42229b291d3 (diff)
New upstream version 1.1.0
Diffstat (limited to 'modules/pam_selinux')
-rw-r--r--modules/pam_selinux/Makefile.in75
-rw-r--r--modules/pam_selinux/README15
-rw-r--r--modules/pam_selinux/pam_selinux.8242
-rw-r--r--modules/pam_selinux/pam_selinux.8.xml37
-rw-r--r--modules/pam_selinux/pam_selinux.c360
5 files changed, 531 insertions, 198 deletions
diff --git a/modules/pam_selinux/Makefile.in b/modules/pam_selinux/Makefile.in
index ffa6e9a4..6c1f4fb5 100644
--- a/modules/pam_selinux/Makefile.in
+++ b/modules/pam_selinux/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -44,13 +44,16 @@ subdir = modules/pam_selinux
DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
- $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
+ $(top_srcdir)/m4/japhar_grep_cflags.m4 \
$(top_srcdir)/m4/jh_path_xml_catalog.m4 \
$(top_srcdir)/m4/ld-O1.m4 $(top_srcdir)/m4/ld-as-needed.m4 \
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libprelude.m4 \
- $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
- $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
@@ -114,23 +117,19 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
-CXX = @CXX@
-CXXCPP = @CXXCPP@
-CXXDEPMODE = @CXXDEPMODE@
-CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DSYMUTIL = @DSYMUTIL@
-ECHO = @ECHO@
+DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
-F77 = @F77@
-FFLAGS = @FFLAGS@
+FGREP = @FGREP@
FO2PDF = @FO2PDF@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
GREP = @GREP@
@@ -142,6 +141,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INTLLIBS = @INTLLIBS@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
@@ -165,6 +165,7 @@ LIBPRELUDE_PTHREAD_CFLAGS = @LIBPRELUDE_PTHREAD_CFLAGS@
LIBS = @LIBS@
LIBSELINUX = @LIBSELINUX@
LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
LN_S = @LN_S@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
@@ -174,15 +175,18 @@ MKDIR_P = @MKDIR_P@
MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
MSGMERGE = @MSGMERGE@
+NM = @NM@
NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
-PAM_READ_BOTH_CONFS = @PAM_READ_BOTH_CONFS@
PATH_SEPARATOR = @PATH_SEPARATOR@
PIE_CFLAGS = @PIE_CFLAGS@
PIE_LDFLAGS = @PIE_LDFLAGS@
@@ -196,10 +200,9 @@ SHELL = @SHELL@
STRIP = @STRIP@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
-WITH_DEBUG = @WITH_DEBUG@
-WITH_PAMLOCKING = @WITH_PAMLOCKING@
XGETTEXT = @XGETTEXT@
XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
XMLCATALOG = @XMLCATALOG@
XMLLINT = @XMLLINT@
XML_CATALOG_FILE = @XML_CATALOG_FILE@
@@ -211,8 +214,7 @@ abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
-ac_ct_CXX = @ac_ct_CXX@
-ac_ct_F77 = @ac_ct_F77@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -244,6 +246,7 @@ libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
@@ -258,6 +261,7 @@ sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
CLEANFILES = *~
@@ -290,8 +294,8 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
- && exit 0; \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
@@ -401,8 +405,8 @@ install-man8: $(man8_MANS) $(man_MANS)
esac; \
done; \
for i in $$list; do \
- if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
- else file=$$i; fi; \
+ if test -f $$i; then file=$$i; \
+ else file=$(srcdir)/$$i; fi; \
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
case "$$ext" in \
8*) ;; \
@@ -441,7 +445,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
- $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
@@ -484,7 +488,7 @@ distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
check-TESTS: $(TESTS)
- @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
srcdir=$(srcdir); export srcdir; \
list=' $(TESTS) '; \
if test -n "$$list"; then \
@@ -495,7 +499,7 @@ check-TESTS: $(TESTS)
if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
- *$$ws$$tst$$ws*) \
+ *[\ \ ]$$tst[\ \ ]*) \
xpass=`expr $$xpass + 1`; \
failed=`expr $$failed + 1`; \
echo "XPASS: $$tst"; \
@@ -507,7 +511,7 @@ check-TESTS: $(TESTS)
elif test $$? -ne 77; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
- *$$ws$$tst$$ws*) \
+ *[\ \ ]$$tst[\ \ ]*) \
xfail=`expr $$xfail + 1`; \
echo "XFAIL: $$tst"; \
;; \
@@ -521,23 +525,36 @@ check-TESTS: $(TESTS)
echo "SKIP: $$tst"; \
fi; \
done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
if test "$$failed" -eq 0; then \
if test "$$xfail" -eq 0; then \
- banner="All $$all tests passed"; \
+ banner="$$All$$all $$tests passed"; \
else \
- banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
fi; \
else \
if test "$$xpass" -eq 0; then \
- banner="$$failed of $$all tests failed"; \
+ banner="$$failed of $$all $$tests failed"; \
else \
- banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
fi; \
fi; \
dashes="$$banner"; \
skipped=""; \
if test "$$skip" -ne 0; then \
- skipped="($$skip tests were not run)"; \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
dashes="$$skipped"; \
fi; \
diff --git a/modules/pam_selinux/README b/modules/pam_selinux/README
index 9e841f2e..67217905 100644
--- a/modules/pam_selinux/README
+++ b/modules/pam_selinux/README
@@ -48,10 +48,21 @@ select_context
Attempt to ask the user for a custom security context role. If MLS is on
ask also for sensitivity level.
+env_params
+
+ Attempt to obtain a custom security context role from PAM environment. If
+ MLS is on obtain also sensitivity level. This option and the select_context
+ option are mutually exclusive. The respective PAM environment variables are
+ SELINUX_ROLE_REQUESTED, SELINUX_LEVEL_REQUESTED, and
+ SELINUX_USE_CURRENT_RANGE. The first two variables are self describing and
+ the last one if set to 1 makes the PAM module behave as if the
+ use_current_range was specified on the command line of the module.
+
use_current_range
- Use the sensitivity range of the process for the user context. This option
- and the select_context option are mutually exclusive.
+ Use the sensitivity level of the current process for the user context
+ instead of the default level. Also suppresses asking of the sensitivity
+ level from the user or obtaining it from PAM environment.
EXAMPLES
diff --git a/modules/pam_selinux/pam_selinux.8 b/modules/pam_selinux/pam_selinux.8
index bfcf7ba7..dfbcd4bb 100644
--- a/modules/pam_selinux/pam_selinux.8
+++ b/modules/pam_selinux/pam_selinux.8
@@ -1,101 +1,285 @@
.\" Title: pam_selinux
-.\" Author:
-.\" Generator: DocBook XSL Stylesheets v1.73.1 <http://docbook.sf.net/>
-.\" Date: 04/16/2008
+.\" Author: [see the "AUTHOR" section]
+.\" Generator: DocBook XSL Stylesheets v1.74.0 <http://docbook.sf.net/>
+.\" Date: 06/16/2009
.\" Manual: Linux-PAM Manual
.\" Source: Linux-PAM Manual
+.\" Language: English
.\"
-.TH "PAM_SELINUX" "8" "04/16/2008" "Linux-PAM Manual" "Linux\-PAM Manual"
+.TH "PAM_SELINUX" "8" "06/16/2009" "Linux-PAM Manual" "Linux\-PAM Manual"
+.\" -----------------------------------------------------------------
+.\" * (re)Define some macros
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" toupper - uppercase a string (locale-aware)
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.de toupper
+.tr aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ
+\\$*
+.tr aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz
+..
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" SH-xref - format a cross-reference to an SH section
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.de SH-xref
+.ie n \{\
+.\}
+.toupper \\$*
+.el \{\
+\\$*
+.\}
+..
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" SH - level-one heading that works better for non-TTY output
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.de1 SH
+.\" put an extra blank line of space above the head in non-TTY output
+.if t \{\
+.sp 1
+.\}
+.sp \\n[PD]u
+.nr an-level 1
+.set-an-margin
+.nr an-prevailing-indent \\n[IN]
+.fi
+.in \\n[an-margin]u
+.ti 0
+.HTML-TAG ".NH \\n[an-level]"
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+\." make the size of the head bigger
+.ps +3
+.ft B
+.ne (2v + 1u)
+.ie n \{\
+.\" if n (TTY output), use uppercase
+.toupper \\$*
+.\}
+.el \{\
+.nr an-break-flag 0
+.\" if not n (not TTY), use normal case (not uppercase)
+\\$1
+.in \\n[an-margin]u
+.ti 0
+.\" if not n (not TTY), put a border/line under subheading
+.sp -.6
+\l'\n(.lu'
+.\}
+..
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" SS - level-two heading that works better for non-TTY output
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.de1 SS
+.sp \\n[PD]u
+.nr an-level 1
+.set-an-margin
+.nr an-prevailing-indent \\n[IN]
+.fi
+.in \\n[IN]u
+.ti \\n[SN]u
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.ps \\n[PS-SS]u
+\." make the size of the head bigger
+.ps +2
+.ft B
+.ne (2v + 1u)
+.if \\n[.$] \&\\$*
+..
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" BB/BE - put background/screen (filled box) around block of text
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.de BB
+.if t \{\
+.sp -.5
+.br
+.in +2n
+.ll -2n
+.gcolor red
+.di BX
+.\}
+..
+.de EB
+.if t \{\
+.if "\\$2"adjust-for-leading-newline" \{\
+.sp -1
+.\}
+.br
+.di
+.in
+.ll
+.gcolor
+.nr BW \\n(.lu-\\n(.i
+.nr BH \\n(dn+.5v
+.ne \\n(BHu+.5v
+.ie "\\$2"adjust-for-leading-newline" \{\
+\M[\\$1]\h'1n'\v'+.5v'\D'P \\n(BWu 0 0 \\n(BHu -\\n(BWu 0 0 -\\n(BHu'\M[]
+.\}
+.el \{\
+\M[\\$1]\h'1n'\v'-.5v'\D'P \\n(BWu 0 0 \\n(BHu -\\n(BWu 0 0 -\\n(BHu'\M[]
+.\}
+.in 0
+.sp -.5v
+.nf
+.BX
+.in
+.sp .5v
+.fi
+.\}
+..
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" BM/EM - put colored marker in margin next to block of text
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.de BM
+.if t \{\
+.br
+.ll -2n
+.gcolor red
+.di BX
+.\}
+..
+.de EM
+.if t \{\
+.br
+.di
+.ll
+.gcolor
+.nr BH \\n(dn
+.ne \\n(BHu
+\M[\\$1]\D'P -.75n 0 0 \\n(BHu -(\\n[.i]u - \\n(INu - .75n) 0 0 -\\n(BHu'\M[]
+.in 0
+.nf
+.BX
+.in
+.fi
+.\}
+..
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
-.SH "NAME"
-pam_selinux - PAM module to set the default security context
-.SH "SYNOPSIS"
-.HP 15
-\fBpam_selinux\.so\fR [close] [debug] [open] [nottys] [verbose] [select_context] [use_current_range]
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "Name"
+pam_selinux \- PAM module to set the default security context
+.SH "Synopsis"
+.fam C
+.HP \w'\fBpam_selinux\&.so\fR\ 'u
+\fBpam_selinux\&.so\fR [close] [debug] [open] [nottys] [verbose] [select_context] [env_params] [use_current_range]
+.fam
.SH "DESCRIPTION"
.PP
-In a nutshell, pam_selinux sets up the default security context for the next execed shell\.
+In a nutshell, pam_selinux sets up the default security context for the next execed shell\&.
.PP
-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\.
+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\&.
.PP
-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 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\.
+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 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 "OPTIONS"
.PP
\fBclose\fR
.RS 4
-Only execute the close_session portion of the module\.
+Only execute the close_session portion of the module\&.
.RE
.PP
\fBdebug\fR
.RS 4
Turns on debugging via
-\fBsyslog\fR(3)\.
+\fBsyslog\fR(3)\&.
.RE
.PP
\fBopen\fR
.RS 4
-Only execute the open_session portion of the module\.
+Only execute the open_session portion of the module\&.
.RE
.PP
\fBnottys\fR
.RS 4
-Do not try to setup the ttys security context\.
+Do not try to setup the ttys security context\&.
.RE
.PP
\fBverbose\fR
.RS 4
-attempt to inform the user when security context is set\.
+attempt to inform the user when security context is set\&.
.RE
.PP
\fBselect_context\fR
.RS 4
-Attempt to ask the user for a custom security context role\. If MLS is on ask also for sensitivity level\.
+Attempt to ask the user for a custom security context role\&. If MLS is on ask also for sensitivity level\&.
+.RE
+.PP
+\fBenv_params\fR
+.RS 4
+Attempt to obtain a custom security context role from PAM environment\&. If MLS is on obtain also sensitivity level\&. This option and the select_context option are mutually exclusive\&. The respective PAM environment variables are
+\fISELINUX_ROLE_REQUESTED\fR,
+\fISELINUX_LEVEL_REQUESTED\fR, and
+\fISELINUX_USE_CURRENT_RANGE\fR\&. The first two variables are self describing and the last one if set to 1 makes the PAM module behave as if the use_current_range was specified on the command line of the module\&.
.RE
.PP
\fBuse_current_range\fR
.RS 4
-Use the sensitivity range of the process for the user context\. This option and the select_context option are mutually exclusive\.
+Use the sensitivity level of the current process for the user context instead of the default level\&. Also suppresses asking of the sensitivity level from the user or obtaining it from PAM environment\&.
.RE
-.SH "MODULE SERVICES PROVIDED"
+.SH "MODULE TYPES PROVIDED"
.PP
Only the
\fBsession\fR
-service is supported\.
+module type is provided\&.
.SH "RETURN VALUES"
.PP
PAM_AUTH_ERR
.RS 4
-Unable to get or set a valid context\.
+Unable to get or set a valid context\&.
.RE
.PP
PAM_SUCCESS
.RS 4
-The security context was set successfull\.
+The security context was set successfully\&.
.RE
.PP
PAM_USER_UNKNOWN
.RS 4
-The user is not known to the system\.
+The user is not known to the system\&.
.RE
.SH "EXAMPLES"
.sp
+.if n \{\
.RS 4
+.\}
+.fam C
+.ps -1
.nf
-auth required pam_unix\.so
-session required pam_permit\.so
-session optional pam_selinux\.so
+.if t \{\
+.sp -1
+.\}
+.BB lightgray adjust-for-leading-newline
+.sp -1
+
+auth required pam_unix\&.so
+session required pam_permit\&.so
+session optional pam_selinux\&.so
+.EB lightgray adjust-for-leading-newline
+.if t \{\
+.sp 1
+.\}
.fi
+.fam
+.ps +1
+.if n \{\
.RE
+.\}
.SH "SEE ALSO"
.PP
\fBpam.conf\fR(5),
-\fBpam.d\fR(8),
+\fBpam.d\fR(5),
\fBpam\fR(8)
.SH "AUTHOR"
.PP
-pam_selinux was written by Dan Walsh <dwalsh@redhat\.com>\.
+pam_selinux was written by Dan Walsh <dwalsh@redhat\&.com>\&.
diff --git a/modules/pam_selinux/pam_selinux.8.xml b/modules/pam_selinux/pam_selinux.8.xml
index 3acd1322..2c1cdb24 100644
--- a/modules/pam_selinux/pam_selinux.8.xml
+++ b/modules/pam_selinux/pam_selinux.8.xml
@@ -37,6 +37,9 @@
select_context
</arg>
<arg choice="opt">
+ env_params
+ </arg>
+ <arg choice="opt">
use_current_range
</arg>
</cmdsynopsis>
@@ -137,22 +140,40 @@
</varlistentry>
<varlistentry>
<term>
+ <option>env_params</option>
+ </term>
+ <listitem>
+ <para>
+ Attempt to obtain a custom security context role from PAM environment.
+ If MLS is on obtain also sensitivity level. This option and the
+ select_context option are mutually exclusive. The respective PAM
+ environment variables are <emphasis>SELINUX_ROLE_REQUESTED</emphasis>,
+ <emphasis>SELINUX_LEVEL_REQUESTED</emphasis>, and
+ <emphasis>SELINUX_USE_CURRENT_RANGE</emphasis>. The first two variables
+ are self describing and the last one if set to 1 makes the PAM module behave as
+ if the use_current_range was specified on the command line of the module.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
<option>use_current_range</option>
</term>
<listitem>
<para>
- Use the sensitivity range of the process for the user context.
- This option and the select_context option are mutually exclusive.
+ Use the sensitivity level of the current process for the user context
+ instead of the default level. Also suppresses asking of the
+ sensitivity level from the user or obtaining it from PAM environment.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
- <refsect1 id="pam_selinux-services">
- <title>MODULE SERVICES PROVIDED</title>
+ <refsect1 id="pam_selinux-types">
+ <title>MODULE TYPES PROVIDED</title>
<para>
- Only the <option>session</option> service is supported.
+ Only the <option>session</option> module type is provided.
</para>
</refsect1>
@@ -171,7 +192,7 @@
<term>PAM_SUCCESS</term>
<listitem>
<para>
- The security context was set successfull.
+ The security context was set successfully.
</para>
</listitem>
</varlistentry>
@@ -190,7 +211,7 @@
<title>EXAMPLES</title>
<programlisting>
auth required pam_unix.so
-session required pam_permit.so
+session required pam_permit.so
session optional pam_selinux.so
</programlisting>
</refsect1>
@@ -202,7 +223,7 @@ session optional pam_selinux.so
<refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>,
<citerefentry>
- <refentrytitle>pam.d</refentrytitle><manvolnum>8</manvolnum>
+ <refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>,
<citerefentry>
<refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c
index f679e33d..c6f887a6 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
@@ -138,15 +139,22 @@ send_text (pam_handle_t *pamh, const char *text, int debug)
*/
static int
query_response (pam_handle_t *pamh, const char *text, const char *def,
- char **responses, int debug)
+ char **response, int debug)
{
int rc;
if (def)
- rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, responses, "%s [%s] ", text, def);
+ rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, response, "%s [%s] ", text, def);
else
- rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, responses, "%s ", text);
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "%s %s", text, responses[0]);
+ 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;
}
@@ -157,13 +165,15 @@ manual_context (pam_handle_t *pamh, const char *user, int debug)
context_t new_context;
int mls_enabled = is_selinux_mls_enabled();
char *type=NULL;
- char *responses=NULL;
+ char *response=NULL;
while (1) {
- query_response(pamh,
- _("Would you like to enter a security context? [N] "), NULL,
- &responses,debug);
- if ((responses[0] == 'y') || (responses[0] == 'Y'))
+ 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");
@@ -176,26 +186,29 @@ manual_context (pam_handle_t *pamh, const char *user, int debug)
if (context_user_set (new_context, user))
goto fail_set;
- _pam_drop(responses);
+ _pam_drop(response);
/* Allow the user to enter each field of the context individually */
- query_response(pamh,_("role:"), NULL, &responses,debug);
- if (responses[0] != '\0') {
- if (context_role_set (new_context, responses))
+ 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(responses, &type))
+ if (get_default_type(response, &type))
goto fail_set;
if (context_type_set (new_context, type))
goto fail_set;
}
- _pam_drop(responses);
+ _pam_drop(response);
+
if (mls_enabled)
{
- query_response(pamh,_("level:"), NULL, &responses,debug);
- if (responses[0] != '\0') {
- if (context_range_set (new_context, responses))
+ 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));
@@ -204,16 +217,17 @@ manual_context (pam_handle_t *pamh, const char *user, int debug)
}
else
send_text(pamh,_("Not a valid security context"),debug);
- context_free (new_context);
+
+ context_free (new_context);
}
else {
- _pam_drop(responses);
+ _pam_drop(response);
return NULL;
}
} /* end while */
fail_set:
free(type);
- _pam_drop(responses);
+ _pam_drop(response);
context_free (new_context);
return NULL;
}
@@ -239,69 +253,91 @@ 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;
int mls_enabled = is_selinux_mls_enabled();
- char *responses=NULL;
+ char *response=NULL;
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) {
- query_response(pamh,
+ if (query_response(pamh,
_("Would you like to enter a different role or level?"), "n",
- &responses,debug);
-
- resp_val = responses[0];
- _pam_drop(responses);
+ &response, debug) == PAM_SUCCESS) {
+ resp_val = response[0];
+ _pam_drop(response);
+ } else {
+ resp_val = 'N';
+ }
if ((resp_val == 'y') || (resp_val == 'Y'))
{
- new_context = context_new(puser_context);
-
+ if ((new_context = context_new(defaultcon)) == NULL)
+ goto fail_set;
+
/* Allow the user to enter role and level individually */
- query_response(pamh,_("role:"), context_role_get(new_context),
- &responses, debug);
- if (responses[0]) {
- if (get_default_type(responses, &type)) {
- pam_prompt (pamh, PAM_ERROR_MSG, NULL, _("No default type for role %s\n"), responses);
- _pam_drop(responses);
+ 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, responses))
+ if (context_role_set(new_context, response))
goto fail_set;
if (context_type_set (new_context, type))
goto fail_set;
}
}
- _pam_drop(responses);
+ _pam_drop(response);
+
if (mls_enabled)
{
- query_response(pamh,_("level:"), context_range_get(new_context),
- &responses, debug);
- if (responses[0]) {
- if (context_range_set(new_context, responses))
- goto fail_set;
+ 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(responses);
+ _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));
- 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;
@@ -309,26 +345,120 @@ 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;
fail_set:
free(type);
- _pam_drop(responses);
+ _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)
@@ -439,18 +569,24 @@ 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 i, debug = 0, ttys=1;
int verbose=0, close_session=0;
int select_context = 0;
int use_current_range = 0;
int ret = 0;
security_context_t* contextlist = NULL;
int num_contexts = 0;
- const char *username = NULL;
+ int env_params = 0;
+ const char *username;
+ const void *void_username;
const void *tty = NULL;
char *seuser=NULL;
char *level=NULL;
security_context_t default_user_context=NULL;
+#ifdef HAVE_GETSEUSER
+ const void *void_service;
+ const char *service;
+#endif
/* Parse arguments. */
for (i = 0; i < argc; i++) {
@@ -472,13 +608,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;
}
@@ -489,12 +628,23 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED,
if (!(selinux_enabled = is_selinux_enabled()>0) )
return PAM_SUCCESS;
- if (pam_get_item(pamh, PAM_USER, (void *) &username) != PAM_SUCCESS ||
- username == NULL) {
+ if (pam_get_item(pamh, PAM_USER, &void_username) != PAM_SUCCESS ||
+ void_username == NULL) {
return PAM_USER_UNKNOWN;
}
+ username = void_username;
- if (getseuserbyname(username, &seuser, &level)==0) {
+#ifdef HAVE_GETSEUSER
+ if (pam_get_item(pamh, PAM_SERVICE, (void *) &void_service) != PAM_SUCCESS ||
+ void_service == NULL) {
+ return PAM_SESSION_ERR;
+ }
+ service = void_service;
+
+ 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,
@@ -510,12 +660,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 && has_tty) {
- user_context = config_context(pamh, default_user_context, debug);
- if (user_context == NULL) {
+ if (select_context) {
+ 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);
@@ -524,11 +679,9 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED,
return PAM_AUTH_ERR;
else
return PAM_SUCCESS;
- }
- }
+ }
}
else {
- if (has_tty) {
user_context = manual_context(pamh,seuser,debug);
if (user_context == NULL) {
pam_syslog (pamh, LOG_ERR, "Unable to get valid context for %s",
@@ -538,59 +691,6 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED,
else
return PAM_SUCCESS;
}
- } else {
- pam_syslog (pamh, LOG_ERR,
- "Unable to get valid context for %s, No valid tty",
- username);
- if (security_getenforce() == 1)
- return PAM_AUTH_ERR;
- else
- return PAM_SUCCESS;
- }
- }
-
- 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) {
@@ -613,7 +713,7 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED,
}
}
}
- if(ttys && tty ) {
+ if (ttys && tty) {
ttyn=strdup(tty);
ttyn_context=security_label_tty(pamh,ttyn,user_context);
}
@@ -702,21 +802,21 @@ pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED,
free(ttyn);
ttyn=NULL;
}
- if (prev_user_context) {
- if (setexeccon(prev_user_context)) {
+
+ if (setexeccon(prev_user_context)) {
pam_syslog(pamh, LOG_ERR, "Unable to restore executable context %s.",
- prev_user_context);
+ prev_user_context ? prev_user_context : "");
if (security_getenforce() == 1)
status = PAM_AUTH_ERR;
else
status = PAM_SUCCESS;
- }
+ } else if (debug)
+ pam_syslog(pamh, LOG_NOTICE, "Executable context back to original");
+
+ if (prev_user_context) {
freecon(prev_user_context);
prev_user_context = NULL;
}
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "setcontext back to orginal");
-
return status;
}